1 /*
2  * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "gpio/gpio_service.h"
10 #include "gpio/gpio_core.h"
11 #include "gpio_if.h"
12 #include "hdf_device_desc.h"
13 #include "hdf_device_object.h"
14 #include "platform_core.h"
15 #include "platform_listener_common.h"
16 #include "securec.h"
17 
18 #define HDF_LOG_TAG gpio_service
19 
GpioServiceIoRead(struct HdfSBuf * data,struct HdfSBuf * reply)20 static int32_t GpioServiceIoRead(struct HdfSBuf *data, struct HdfSBuf *reply)
21 {
22     int32_t ret;
23     uint16_t gpio;
24     uint16_t value;
25 
26     if (data == NULL || reply == NULL) {
27         HDF_LOGE("GpioServiceIoRead: data or reply is null!");
28         return HDF_ERR_INVALID_PARAM;
29     }
30 
31     if (!HdfSbufReadUint16(data, &gpio)) {
32         HDF_LOGE("GpioServiceIoRead: fail to read gpio number!");
33         return HDF_ERR_IO;
34     }
35 
36     ret = GpioRead(gpio, &value);
37     if (ret != HDF_SUCCESS) {
38         HDF_LOGE("GpioServiceIoRead: fail to read gpio, ret: %d!", ret);
39         return ret;
40     }
41 
42     if (!HdfSbufWriteUint16(reply, value)) {
43         HDF_LOGE("GpioServiceIoRead: fail to write gpio value, ret: %d!", ret);
44         return ret;
45     }
46 
47     return ret;
48 }
49 
GpioServiceIoWrite(struct HdfSBuf * data,struct HdfSBuf * reply)50 static int32_t GpioServiceIoWrite(struct HdfSBuf *data, struct HdfSBuf *reply)
51 {
52     int32_t ret;
53     uint16_t gpio;
54     uint16_t value;
55 
56     (void)reply;
57     if (data == NULL) {
58         HDF_LOGE("GpioServiceIoWrite: data is null!");
59     }
60 
61     if (!HdfSbufReadUint16(data, &gpio)) {
62         HDF_LOGE("GpioServiceIoWrite: fail to read gpio number!");
63         return HDF_ERR_IO;
64     }
65 
66     if (!HdfSbufReadUint16(data, &value)) {
67         HDF_LOGE("GpioServiceIoWrite: fail to read gpio value!");
68         return HDF_ERR_IO;
69     }
70 
71     ret = GpioWrite(gpio, value);
72     if (ret != HDF_SUCCESS) {
73         HDF_LOGE("GpioServiceIoWrite: fail to write gpio value, ret: %d!", ret);
74         return ret;
75     }
76 
77     return ret;
78 }
79 
GpioServiceIoGetDir(struct HdfSBuf * data,struct HdfSBuf * reply)80 static int32_t GpioServiceIoGetDir(struct HdfSBuf *data, struct HdfSBuf *reply)
81 {
82     int32_t ret;
83     uint16_t gpio;
84     uint16_t dir;
85 
86     if (data == NULL || reply == NULL) {
87         HDF_LOGE("GpioServiceIoGetDir: data or reply is null!");
88         return HDF_ERR_INVALID_PARAM;
89     }
90 
91     if (!HdfSbufReadUint16(data, &gpio)) {
92         HDF_LOGE("GpioServiceIoGetDir: fail to read gpio number!");
93         return HDF_ERR_IO;
94     }
95 
96     ret = GpioGetDir(gpio, &dir);
97     if (ret != HDF_SUCCESS) {
98         HDF_LOGE("GpioServiceIoGetDir: fail to get gpio dir, ret: %d!", ret);
99         return ret;
100     }
101 
102     if (!HdfSbufWriteUint16(reply, dir)) {
103         HDF_LOGE("GpioServiceIoGetDir: fail to write gpio dir, ret: %d!", ret);
104         return ret;
105     }
106 
107     return ret;
108 }
109 
GpioServiceIoSetDir(struct HdfSBuf * data,struct HdfSBuf * reply)110 static int32_t GpioServiceIoSetDir(struct HdfSBuf *data, struct HdfSBuf *reply)
111 {
112     int32_t ret;
113     uint16_t gpio;
114     uint16_t dir;
115 
116     (void)reply;
117     if (data == NULL) {
118         HDF_LOGE("GpioServiceIoSetDir: data is null!");
119         return HDF_ERR_INVALID_PARAM;
120     }
121 
122     if (!HdfSbufReadUint16(data, &gpio)) {
123         HDF_LOGE("GpioServiceIoSetDir: fail to read gpio number!");
124         return HDF_ERR_IO;
125     }
126 
127     if (!HdfSbufReadUint16(data, &dir)) {
128         HDF_LOGE("GpioServiceIoSetDir: fail to read gpio dir!");
129         return HDF_ERR_IO;
130     }
131 
132     ret = GpioSetDir(gpio, dir);
133     if (ret != HDF_SUCCESS) {
134         HDF_LOGE("GpioServiceIoSetDir: fail to set gpio dir, ret: %d!", ret);
135         return ret;
136     }
137 
138     return ret;
139 }
140 
GpioServiceUpdate(uint16_t gpio)141 static void GpioServiceUpdate(uint16_t gpio)
142 {
143     int32_t ret;
144     uint32_t id;
145     struct HdfSBuf *data = NULL;
146     struct PlatformManager *gpioMgr = NULL;
147 
148     gpioMgr = GpioManagerGet();
149     if (gpioMgr == NULL || gpioMgr->device.hdfDev == NULL) {
150         HDF_LOGE("GpioServiceUpdate: fail to get gpio manager!");
151         return;
152     }
153 
154     id = PLATFORM_LISTENER_EVENT_GPIO_INT_NOTIFY;
155     data = HdfSbufObtainDefaultSize();
156     if (data == NULL) {
157         HDF_LOGE("GpioServiceUpdate: fail to obtain data!");
158         return;
159     }
160     if (!HdfSbufWriteUint16(data, gpio)) {
161         HDF_LOGE("GpioServiceUpdate: fail to write gpio number!");
162         HdfSbufRecycle(data);
163         return;
164     }
165     ret = HdfDeviceSendEvent(gpioMgr->device.hdfDev, id, data);
166     HdfSbufRecycle(data);
167     HDF_LOGD("GpioServiceUpdate: set service info done, ret = %d, id = %d!", ret, id);
168 }
169 
GpioServiceIrqFunc(uint16_t gpio,void * data)170 static int32_t GpioServiceIrqFunc(uint16_t gpio, void *data)
171 {
172     (void)data;
173     HDF_LOGD("GpioServiceIrqFunc: %d", gpio);
174     GpioServiceUpdate(gpio);
175     return HDF_SUCCESS;
176 }
177 
GpioServiceIoSetIrq(struct HdfSBuf * data,struct HdfSBuf * reply)178 static int32_t GpioServiceIoSetIrq(struct HdfSBuf *data, struct HdfSBuf *reply)
179 {
180     uint16_t gpio;
181     uint16_t mode;
182     int32_t ret;
183 
184     (void)reply;
185     if (data == NULL) {
186         HDF_LOGE("GpioServiceIoSetIrq: data is null!");
187         return HDF_ERR_INVALID_PARAM;
188     }
189 
190     if (!HdfSbufReadUint16(data, &gpio)) {
191         HDF_LOGE("GpioServiceIoSetIrq: fail to read gpio number!");
192         return HDF_ERR_IO;
193     }
194 
195     if (!HdfSbufReadUint16(data, &mode)) {
196         HDF_LOGE("GpioServiceIoSetIrq: fail to read gpio mode!");
197         return HDF_ERR_IO;
198     }
199 
200     ret = GpioSetIrq(gpio, mode, GpioServiceIrqFunc, NULL);
201     if (ret != HDF_SUCCESS) {
202         HDF_LOGE("GpioServiceIoSetIrq: fail to set gpio irq, ret: %d!", ret);
203         return ret;
204     }
205     return HDF_SUCCESS;
206 }
207 
GpioServiceIoUnsetIrq(struct HdfSBuf * data,struct HdfSBuf * reply)208 static int32_t GpioServiceIoUnsetIrq(struct HdfSBuf *data, struct HdfSBuf *reply)
209 {
210     uint16_t gpio;
211 
212     (void)reply;
213     if (data == NULL) {
214         HDF_LOGE("GpioServiceIoUnsetIrq: data is null!");
215         return HDF_ERR_INVALID_PARAM;
216     }
217 
218     if (!HdfSbufReadUint16(data, &gpio)) {
219         HDF_LOGE("GpioServiceIoUnsetIrq: fail to read gpio number!");
220         return HDF_ERR_IO;
221     }
222 
223     if (GpioUnsetIrq(gpio, NULL) != HDF_SUCCESS) {
224         HDF_LOGE("GpioServiceIoUnsetIrq: fail to unset gpio irq!");
225         return HDF_ERR_IO;
226     }
227 
228     return HDF_SUCCESS;
229 }
230 
GpioServiceIoEnableIrq(struct HdfSBuf * data,struct HdfSBuf * reply)231 static int32_t GpioServiceIoEnableIrq(struct HdfSBuf *data, struct HdfSBuf *reply)
232 {
233     int32_t ret;
234     uint16_t gpio;
235 
236     (void)reply;
237     if (data == NULL) {
238         HDF_LOGE("GpioServiceIoEnableIrq: data is null!");
239         return HDF_ERR_INVALID_PARAM;
240     }
241 
242     if (!HdfSbufReadUint16(data, &gpio)) {
243         HDF_LOGE("GpioServiceIoEnableIrq: fail to read gpio number!");
244         return HDF_ERR_IO;
245     }
246 
247     ret = GpioEnableIrq(gpio);
248     if (ret != HDF_SUCCESS) {
249         HDF_LOGE("GpioServiceIoEnableIrq: fail to enable gpio irq, ret: %d!", ret);
250         return ret;
251     }
252 
253     return ret;
254 }
255 
GpioServiceIoDisableIrq(struct HdfSBuf * data,struct HdfSBuf * reply)256 static int32_t GpioServiceIoDisableIrq(struct HdfSBuf *data, struct HdfSBuf *reply)
257 {
258     int32_t ret;
259     uint16_t gpio;
260 
261     (void)reply;
262     if (data == NULL) {
263         HDF_LOGE("GpioServiceIoDisableIrq: data is null!");
264         return HDF_ERR_INVALID_PARAM;
265     }
266 
267     if (!HdfSbufReadUint16(data, &gpio)) {
268         HDF_LOGE("GpioServiceIoDisableIrq: fail to read gpio number!");
269         return HDF_ERR_IO;
270     }
271 
272     ret = GpioDisableIrq(gpio);
273     if (ret != HDF_SUCCESS) {
274         HDF_LOGE("GpioServiceIoDisableIrq: fail to disable gpio irq, ret: %d!", ret);
275         return ret;
276     }
277 
278     return ret;
279 }
280 
GpioServiceIoGetNumByName(struct HdfSBuf * data,struct HdfSBuf * reply)281 static int32_t GpioServiceIoGetNumByName(struct HdfSBuf *data, struct HdfSBuf *reply)
282 {
283     int32_t ret;
284     const char *gpioNameData = NULL;
285 
286     if (data == NULL || reply == NULL) {
287         HDF_LOGE("GpioServiceIoGetNumByName: data or reply is null!");
288         return HDF_ERR_INVALID_PARAM;
289     }
290 
291     gpioNameData = HdfSbufReadString(data);
292     if (gpioNameData == NULL) {
293         HDF_LOGE("GpioServiceIoGetNumByName: gpioNameData is null!");
294         return HDF_ERR_IO;
295     }
296 
297     ret = GpioGetByName(gpioNameData);
298     if (ret < 0) {
299         HDF_LOGE("GpioServiceIoGetNumByName: fail to get gpio global number by gpioName!");
300         return ret;
301     }
302 
303     if (!HdfSbufWriteInt32(reply, ret)) {
304         HDF_LOGE("GpioServiceIoGetNumByName: fail to write gpio global number!");
305         return HDF_ERR_IO;
306     }
307 
308     return HDF_SUCCESS;
309 }
310 
GpioServiceDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)311 static int32_t GpioServiceDispatch(
312     struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
313 {
314     int32_t ret;
315 
316     (void)client;
317     switch (cmd) {
318         case GPIO_IO_READ:
319             return GpioServiceIoRead(data, reply);
320         case GPIO_IO_WRITE:
321             return GpioServiceIoWrite(data, reply);
322         case GPIO_IO_GETDIR:
323             return GpioServiceIoGetDir(data, reply);
324         case GPIO_IO_SETDIR:
325             return GpioServiceIoSetDir(data, reply);
326         case GPIO_IO_SETIRQ:
327             return GpioServiceIoSetIrq(data, reply);
328         case GPIO_IO_UNSETIRQ:
329             return GpioServiceIoUnsetIrq(data, reply);
330         case GPIO_IO_ENABLEIRQ:
331             return GpioServiceIoEnableIrq(data, reply);
332         case GPIO_IO_DISABLEIRQ:
333             return GpioServiceIoDisableIrq(data, reply);
334         case GPIO_IO_GET_NUM_BY_NAME:
335             return GpioServiceIoGetNumByName(data, reply);
336         default:
337             HDF_LOGE("GpioServiceDispatch: cmd %d is not support!", cmd);
338             ret = HDF_ERR_NOT_SUPPORT;
339             break;
340     }
341     return ret;
342 }
343 
GpioServiceBind(struct HdfDeviceObject * device)344 static int32_t GpioServiceBind(struct HdfDeviceObject *device)
345 {
346     int32_t ret;
347     struct PlatformManager *gpioMgr = NULL;
348 
349     HDF_LOGI("GpioServiceBind: enter!");
350     if (device == NULL) {
351         HDF_LOGE("GpioServiceBind: device is null!");
352         return HDF_ERR_INVALID_OBJECT;
353     }
354 
355     gpioMgr = GpioManagerGet();
356     if (gpioMgr == NULL) {
357         HDF_LOGE("GpioServiceBind: fail to get gpio manager!");
358         return HDF_PLT_ERR_DEV_GET;
359     }
360 
361     ret = PlatformDeviceCreateService(&gpioMgr->device, GpioServiceDispatch);
362     if (ret != HDF_SUCCESS) {
363         HDF_LOGE("GpioServiceBind: fail to create gpio service, ret: %d!", ret);
364         return ret;
365     }
366 
367     ret = PlatformDeviceBind(&gpioMgr->device, device);
368     if (ret != HDF_SUCCESS) {
369         HDF_LOGE("GpioServiceBind: fail to bind gpio device, ret: %d!", ret);
370         (void)PlatformDeviceDestroyService(&gpioMgr->device);
371         return ret;
372     }
373 
374     HDF_LOGI("GpioServiceBind: success!");
375     return HDF_SUCCESS;
376 }
377 
GpioServiceInit(struct HdfDeviceObject * device)378 static int32_t GpioServiceInit(struct HdfDeviceObject *device)
379 {
380     (void)device;
381     return HDF_SUCCESS;
382 }
383 
GpioServiceRelease(struct HdfDeviceObject * device)384 static void GpioServiceRelease(struct HdfDeviceObject *device)
385 {
386     struct PlatformManager *gpioMgr = NULL;
387 
388     HDF_LOGI("GpioServiceRelease: enter!");
389     if (device == NULL) {
390         HDF_LOGI("GpioServiceRelease: device is null!");
391         return;
392     }
393 
394     gpioMgr = GpioManagerGet();
395     if (gpioMgr == NULL) {
396         HDF_LOGE("GpioServiceRelease: fail to get gpio manager!");
397         return;
398     }
399 
400     (void)PlatformDeviceUnbind(&gpioMgr->device, device);
401     (void)PlatformDeviceDestroyService(&gpioMgr->device);
402     HDF_LOGI("GpioServiceRelease: done!");
403 }
404 
405 struct HdfDriverEntry g_gpioServiceEntry = {
406     .moduleVersion = 1,
407     .Bind = GpioServiceBind,
408     .Init = GpioServiceInit,
409     .Release = GpioServiceRelease,
410     .moduleName = "HDF_PLATFORM_GPIO_MANAGER",
411 };
412 HDF_INIT(g_gpioServiceEntry);
413