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