• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "light_driver.h"
10 #include <securec.h>
11 #include "device_resource_if.h"
12 #include "hdf_device_desc.h"
13 #include "osal_mem.h"
14 #include "osal_mutex.h"
15 
16 #define HDF_LOG_TAG    hdf_light_driver
17 
18 #define LIGHT_WORK_QUEUE_NAME    "light_queue"
19 
20 struct LightDriverData *g_lightDrvData = NULL;
21 
GetLightDrvData(void)22 static struct LightDriverData *GetLightDrvData(void)
23 {
24     return g_lightDrvData;
25 }
26 
GetAllLightInfo(struct HdfSBuf * data,struct HdfSBuf * reply)27 static int32_t GetAllLightInfo(struct HdfSBuf *data, struct HdfSBuf *reply)
28 {
29     (void)data;
30     uint32_t i;
31     struct LightInfo lightInfo;
32     struct LightDriverData *drvData = NULL;
33 
34     drvData = GetLightDrvData();
35     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
36     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM);
37 
38     if (!HdfSbufWriteUint32(reply, drvData->lightNum)) {
39         HDF_LOGE("%s: write sbuf failed", __func__);
40         return HDF_FAILURE;
41     }
42 
43     for (i = 0; i < LIGHT_ID_BUTT; ++i) {
44         if (drvData->info[i] == NULL) {
45             continue;
46         }
47         lightInfo.lightId = i;
48         lightInfo.reserved = 0;
49 
50         if (!HdfSbufWriteBuffer(reply, &lightInfo, sizeof(lightInfo))) {
51             HDF_LOGE("%s: write sbuf failed", __func__);
52             return HDF_FAILURE;
53         }
54     }
55 
56     return HDF_SUCCESS;
57 }
58 
StartLight(uint32_t lightId)59 int32_t StartLight(uint32_t lightId)
60 {
61     struct LightDriverData *drvData = NULL;
62 
63     drvData = GetLightDrvData();
64     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
65 
66     if (GpioWrite(drvData->info[lightId]->busNum, GPIO_VAL_HIGH) != HDF_SUCCESS) {
67         HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, drvData->info[lightId]->busNum, GPIO_VAL_LOW);
68         return HDF_FAILURE;
69     }
70 
71     return HDF_SUCCESS;
72 }
73 
StopLight(uint32_t lightId)74 int32_t StopLight(uint32_t lightId)
75 {
76     struct LightDriverData *drvData = NULL;
77 
78     drvData = GetLightDrvData();
79     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
80 
81     if (GpioWrite(drvData->info[lightId]->busNum, GPIO_VAL_LOW) != HDF_SUCCESS) {
82         HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, drvData->info[lightId]->busNum, GPIO_VAL_LOW);
83         return HDF_FAILURE;
84     }
85 
86     return HDF_SUCCESS;
87 }
88 
LightTimerEntry(uintptr_t para)89 void LightTimerEntry(uintptr_t para)
90 {
91     uint32_t duration;
92     uint32_t lightId;
93     struct LightDriverData *drvData = NULL;
94 
95     drvData = GetLightDrvData();
96     if (drvData == NULL) {
97         HDF_LOGE("%s: drvData is null", __func__);
98         return;
99     }
100 
101     lightId = (uint32_t)para;
102     drvData->lightId = lightId;
103 
104     if (drvData->info[lightId]->lightState == LIGHT_STATE_START) {
105         duration = drvData->info[lightId]->offTime;
106     }
107     if (drvData->info[lightId]->lightState == LIGHT_STATE_STOP) {
108         duration = drvData->info[lightId]->onTime;
109     }
110 
111     HdfAddWork(&drvData->workQueue, &drvData->work);
112 
113     if ((OsalTimerSetTimeout(&drvData->timer, duration) == HDF_SUCCESS)) {
114         return;
115     }
116 
117     if (drvData->timer.realTimer != NULL) {
118         if (OsalTimerDelete(&drvData->timer) != HDF_SUCCESS) {
119             HDF_LOGE("%s: delete light timer fail!", __func__);
120         }
121     }
122 
123     return;
124 }
125 
Enable(uint32_t lightId,struct HdfSBuf * data,struct HdfSBuf * reply)126 static int32_t Enable(uint32_t lightId, struct HdfSBuf *data, struct HdfSBuf *reply)
127 {
128     (void)reply;
129     uint32_t len;
130     struct LightEffect *buf = NULL;
131     struct LightDriverData *drvData = NULL;
132 
133     drvData = GetLightDrvData();
134     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
135 
136     if (drvData->info[lightId] == NULL) {
137         HDF_LOGE("%s: light id info is null", __func__);
138         return HDF_FAILURE;
139     }
140 
141     if (!HdfSbufReadBuffer(data, (const void **)&buf, &len)) {
142         HDF_LOGE("%s: light read data failed", __func__);
143         return HDF_FAILURE;
144     }
145 
146     drvData->info[lightId]->lightBrightness = (buf->lightBrightness == 0) ?
147         drvData->info[lightId]->lightBrightness : buf->lightBrightness;
148 
149     if ((drvData->info[lightId]->lightBrightness & LIGHT_MAKE_R_BIT) != 0) {
150         drvData->info[lightId]->busNum = drvData->info[lightId]->busRNum;
151     } else if ((drvData->info[lightId]->lightBrightness & LIGHT_MAKE_G_BIT) != 0) {
152         drvData->info[lightId]->busNum = drvData->info[lightId]->busGNum;
153     } else if ((drvData->info[lightId]->lightBrightness & LIGHT_MAKE_B_BIT) != 0) {
154         drvData->info[lightId]->busNum = drvData->info[lightId]->busBNum;
155     }
156 
157     if (buf->flashEffect.flashMode == LIGHT_FLASH_NONE) {
158         if (GpioWrite(drvData->info[lightId]->busNum, GPIO_VAL_HIGH) != HDF_SUCCESS) {
159             HDF_LOGE("%s: gpio busNum %d write failed", __func__, drvData->info[lightId]->busNum);
160             return HDF_FAILURE;
161         }
162     }
163 
164     if (buf->flashEffect.flashMode == LIGHT_FLASH_TIMED) {
165         drvData->info[lightId]->onTime = (buf->flashEffect.onTime < drvData->info[lightId]->onTime) ?
166         drvData->info[lightId]->onTime : buf->flashEffect.onTime;
167         drvData->info[lightId]->offTime = (buf->flashEffect.offTime < drvData->info[lightId]->offTime) ?
168         drvData->info[lightId]->offTime : buf->flashEffect.offTime;
169 
170         if (OsalTimerCreate(&drvData->timer, LIGHT_WAIT_TIME, LightTimerEntry, (uintptr_t)lightId) != HDF_SUCCESS) {
171             HDF_LOGE("%s: create light timer fail!", __func__);
172             return HDF_FAILURE;
173         }
174 
175         if (OsalTimerStartLoop(&drvData->timer) != HDF_SUCCESS) {
176             HDF_LOGE("%s: start light timer fail!", __func__);
177             return HDF_FAILURE;
178         }
179     }
180 
181     return HDF_SUCCESS;
182 }
183 
Disable(uint32_t lightId,struct HdfSBuf * data,struct HdfSBuf * reply)184 static int32_t Disable(uint32_t lightId, struct HdfSBuf *data, struct HdfSBuf *reply)
185 {
186     (void)data;
187     (void)reply;
188     struct LightDriverData *drvData = NULL;
189 
190     drvData = GetLightDrvData();
191     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
192 
193     if (drvData->info[lightId] == NULL) {
194         HDF_LOGE("%s: light id info is null", __func__);
195         return HDF_FAILURE;
196     }
197 
198     if (drvData->timer.realTimer != NULL) {
199         if (OsalTimerDelete(&drvData->timer) != HDF_SUCCESS) {
200             HDF_LOGE("%s: delete light timer fail!", __func__);
201             return HDF_FAILURE;
202         }
203     }
204 
205     if (GpioWrite(drvData->info[lightId]->busRNum, GPIO_VAL_LOW) != HDF_SUCCESS) {
206         HDF_LOGE("%s: gpio write failed", __func__);
207         return HDF_FAILURE;
208     }
209 
210     drvData->info[lightId]->lightState = LIGHT_STATE_STOP;
211 
212     return HDF_SUCCESS;
213 }
214 
215 static struct LightCmdHandleList g_lightCmdHandle[] = {
216     {LIGHT_OPS_IO_CMD_ENABLE, Enable},
217     {LIGHT_OPS_IO_CMD_DISABLE, Disable},
218 };
219 
DispatchCmdHandle(uint32_t lightId,struct HdfSBuf * data,struct HdfSBuf * reply)220 static int32_t DispatchCmdHandle(uint32_t lightId, struct HdfSBuf *data, struct HdfSBuf *reply)
221 {
222     int32_t opsCmd;
223     int32_t loop;
224     int32_t count;
225 
226     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
227 
228     if (!HdfSbufReadInt32(data, &opsCmd)) {
229         HDF_LOGE("%s: sbuf read opsCmd failed", __func__);
230         return HDF_FAILURE;
231     }
232 
233     if ((opsCmd >= LIGHT_OPS_IO_CMD_END) || (opsCmd < LIGHT_OPS_IO_CMD_ENABLE)) {
234         HDF_LOGE("%s: invalid cmd = %d", __func__, opsCmd);
235         return HDF_FAILURE;
236     }
237 
238     count = sizeof(g_lightCmdHandle) / sizeof(g_lightCmdHandle[0]);
239     for (loop = 0; loop < count; ++loop) {
240         if ((opsCmd == g_lightCmdHandle[loop].cmd) && (g_lightCmdHandle[loop].func != NULL)) {
241             return g_lightCmdHandle[loop].func(lightId, data, reply);
242         }
243     }
244 
245     return HDF_FAILURE;
246 }
247 
DispatchLight(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)248 static int32_t DispatchLight(struct HdfDeviceIoClient *client,
249     int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
250 {
251     int32_t ret;
252     uint32_t lightId;
253     struct LightDriverData *drvData = NULL;
254 
255     drvData = GetLightDrvData();
256     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
257     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(client, HDF_ERR_INVALID_PARAM);
258 
259     if (cmd >= LIGHT_IO_CMD_END) {
260         HDF_LOGE("%s: light cmd invalid para", __func__);
261         return HDF_ERR_INVALID_PARAM;
262     }
263 
264     if (cmd == LIGHT_IO_CMD_GET_INFO_LIST) {
265         CHECK_LIGHT_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM);
266         return GetAllLightInfo(data, reply);
267     }
268 
269     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
270     (void)OsalMutexLock(&drvData->mutex);
271     if (!HdfSbufReadUint32(data, &lightId)) {
272         HDF_LOGE("%s: sbuf read lightId failed", __func__);
273         (void)OsalMutexUnlock(&drvData->mutex);
274         return HDF_ERR_INVALID_PARAM;
275     }
276 
277     if (lightId >= LIGHT_ID_BUTT) {
278         HDF_LOGE("%s: light id invalid para", __func__);
279         (void)OsalMutexUnlock(&drvData->mutex);
280         return HDF_FAILURE;
281     }
282 
283     ret = DispatchCmdHandle(lightId, data, reply);
284     (void)OsalMutexUnlock(&drvData->mutex);
285 
286     return ret;
287 }
288 
ParseLightInfo(const struct DeviceResourceNode * node,const struct DeviceResourceIface * parser)289 static int32_t ParseLightInfo(const struct DeviceResourceNode *node, const struct DeviceResourceIface *parser)
290 {
291     int32_t ret;
292     uint32_t i;
293     uint32_t temp;
294     uint32_t *lightBrightness = NULL;
295     struct LightDriverData *drvData = NULL;
296 
297     drvData = GetLightDrvData();
298     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
299     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
300     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
301 
302     drvData->lightNum = (uint32_t)parser->GetElemNum(node, "lightId");
303     if (drvData->lightNum > LIGHT_ID_NUM) {
304         HDF_LOGE("%s: lightNum cross the border", __func__);
305         return HDF_FAILURE;
306     }
307 
308     ret = memset_s(drvData->info, sizeof(drvData->info[LIGHT_ID_NONE]) * LIGHT_ID_BUTT, 0,
309         sizeof(drvData->info[LIGHT_ID_NONE]) * LIGHT_ID_BUTT);
310     CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "memset_s");
311 
312     for (i = 0; i < drvData->lightNum; ++i) {
313         ret = parser->GetUint32ArrayElem(node, "lightId", i, &temp, 0);
314         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "lightId");
315 
316         if (temp >= LIGHT_ID_BUTT) {
317             HDF_LOGE("%s: light id invalid para", __func__);
318             return HDF_FAILURE;
319         }
320 
321         drvData->info[temp] = (struct LightDeviceInfo *)OsalMemCalloc(sizeof(struct LightDeviceInfo));
322         if (drvData->info[temp] == NULL) {
323             HDF_LOGE("%s: malloc fail", __func__);
324             return HDF_FAILURE;
325         }
326 
327         ret = parser->GetUint32(node, "busRNum", &drvData->info[temp]->busRNum, 0);
328         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busRNum");
329         ret = parser->GetUint32(node, "busGNum", &drvData->info[temp]->busGNum, 0);
330         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busGNum");
331         ret = parser->GetUint32(node, "busBNum", &drvData->info[temp]->busBNum, 0);
332         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busBNum");
333         lightBrightness = (uint32_t *)&drvData->info[temp]->lightBrightness;
334         ret = parser->GetUint32(node, "lightBrightness", lightBrightness, 0);
335         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "lightBrightness");
336         ret = parser->GetUint32(node, "onTime", &drvData->info[temp]->onTime, 0);
337         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "onTime");
338         ret = parser->GetUint32(node, "offTime", &drvData->info[temp]->offTime, 0);
339         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "offTime");
340 
341         drvData->info[temp]->lightState = LIGHT_STATE_STOP;
342     }
343 
344     return HDF_SUCCESS;
345 }
346 
GetLightConfigData(const struct DeviceResourceNode * node)347 static int32_t GetLightConfigData(const struct DeviceResourceNode *node)
348 {
349     struct DeviceResourceIface *parser = NULL;
350     const struct DeviceResourceNode *light = NULL;
351     const struct DeviceResourceNode *childNode = NULL;
352 
353     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
354 
355     parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
356     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
357     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(parser->GetChildNode, HDF_ERR_INVALID_PARAM);
358 
359     childNode = parser->GetChildNode(node, "lightAttr");
360     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(childNode, HDF_ERR_INVALID_PARAM);
361     light = parser->GetChildNode(childNode, "light01");
362     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(light, HDF_ERR_INVALID_PARAM);
363 
364     if (ParseLightInfo(light, parser) != HDF_SUCCESS) {
365         HDF_LOGE("%s: ParseLightInfo  is failed!", __func__);
366         return HDF_FAILURE;
367     }
368 
369     return HDF_SUCCESS;
370 }
371 
BindLightDriver(struct HdfDeviceObject * device)372 int32_t BindLightDriver(struct HdfDeviceObject *device)
373 {
374     struct LightDriverData *drvData = NULL;
375 
376     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
377 
378     drvData = (struct LightDriverData *)OsalMemCalloc(sizeof(*drvData));
379     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL);
380 
381     drvData->ioService.Dispatch = DispatchLight;
382     drvData->device = device;
383     device->service = &drvData->ioService;
384     g_lightDrvData = drvData;
385 
386     return HDF_SUCCESS;
387 }
388 
LightWorkEntry(void * para)389 static void LightWorkEntry(void *para)
390 {
391     uint32_t lightId;
392     struct LightDriverData *drvData = (struct LightDriverData *)para;
393     CHECK_LIGHT_NULL_PTR_RETURN(drvData);
394     lightId = drvData->lightId;
395 
396     if (drvData->info[lightId] == NULL) {
397         HDF_LOGE("%s: lightId info is NULL!", __func__);
398         return;
399     }
400 
401     if (drvData->info[lightId]->lightState == LIGHT_STATE_START) {
402         if (StopLight(lightId) != HDF_SUCCESS) {
403         HDF_LOGE("%s: add light work fail! device state[%d]!", __func__, drvData->info[lightId]->lightState);
404         }
405         drvData->info[lightId]->lightState = LIGHT_STATE_STOP;
406         return;
407     }
408 
409     if (drvData->info[lightId]->lightState == LIGHT_STATE_STOP) {
410         if (StartLight(lightId) != HDF_SUCCESS) {
411         HDF_LOGE("%s: add light work fail! device state[%d]!", __func__, drvData->info[lightId]->lightState);
412         }
413         drvData->info[lightId]->lightState = LIGHT_STATE_START;
414         return;
415     }
416 }
417 
InitLightDriver(struct HdfDeviceObject * device)418 int32_t InitLightDriver(struct HdfDeviceObject *device)
419 {
420     struct LightDriverData *drvData = NULL;
421 
422     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
423     drvData = (struct LightDriverData *)device->service;
424     CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
425 
426     if (OsalMutexInit(&drvData->mutex) != HDF_SUCCESS) {
427         HDF_LOGE("%s: init mutex fail!", __func__);
428         return HDF_FAILURE;
429     }
430 
431     if (HdfWorkQueueInit(&drvData->workQueue, LIGHT_WORK_QUEUE_NAME) != HDF_SUCCESS) {
432         HDF_LOGE("%s: init workQueue fail!", __func__);
433         return HDF_FAILURE;
434     }
435 
436     if (HdfWorkInit(&drvData->work, LightWorkEntry, (void*)drvData) != HDF_SUCCESS) {
437         HDF_LOGE("%s: init work fail!", __func__);
438         return HDF_FAILURE;
439     }
440 
441     if (GetLightConfigData(device->property) != HDF_SUCCESS) {
442         HDF_LOGE("%s: get light config fail!", __func__);
443         return HDF_FAILURE;
444     }
445 
446     return HDF_SUCCESS;
447 }
448 
ReleaseLightDriver(struct HdfDeviceObject * device)449 void ReleaseLightDriver(struct HdfDeviceObject *device)
450 {
451     int32_t i;
452     struct LightDriverData *drvData = NULL;
453 
454     if (device == NULL) {
455         HDF_LOGE("%s: device is null", __func__);
456         return;
457     }
458 
459     drvData = (struct LightDriverData *)device->service;
460     if (drvData == NULL) {
461         HDF_LOGE("%s: drvData is null", __func__);
462         return;
463     }
464 
465     for (i = LIGHT_ID_NONE; i < LIGHT_ID_BUTT; ++i) {
466         if (drvData->info[i] != NULL) {
467             OsalMemFree(drvData->info[i]);
468             drvData->info[i] = NULL;
469         }
470     }
471 
472     HdfWorkDestroy(&drvData->work);
473     HdfWorkQueueDestroy(&drvData->workQueue);
474     (void)OsalMutexDestroy(&drvData->mutex);
475     OsalMemFree(drvData);
476     g_lightDrvData = NULL;
477 }
478 
479 struct HdfDriverEntry g_lightDriverEntry = {
480     .moduleVersion = 1,
481     .moduleName = "HDF_LIGHT",
482     .Bind = BindLightDriver,
483     .Init = InitLightDriver,
484     .Release = ReleaseLightDriver,
485 };
486 
487 HDF_INIT(g_lightDriverEntry);
488