1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "light_controller.h"
17 #include <fcntl.h>
18 #include <securec.h>
19 #include <stdio.h>
20 #include "osal_mem.h"
21 #include "hdf_base.h"
22 #include "hdf_dlist.h"
23 #include "hdf_io_service_if.h"
24 #include "hdf_log.h"
25 #include "light_dump.h"
26 #include "light_if.h"
27 #include "light_type.h"
28
29 #define HDF_LOG_TAG uhdf_light_service
30 #define LIGHT_SERVICE_NAME "hdf_light"
31
32 #define MULTI_LIGHT_MAX_NUMBER 48
33 #define LIGHT_ON 1
34 #define LIGHT_OFF 0
35
36 struct LightEffect g_lightEffect;
37 uint8_t g_lightState[LIGHT_ID_BUTT] = {0};
38
GetLightDevicePriv(void)39 struct LightDevice *GetLightDevicePriv(void)
40 {
41 static struct LightDevice lightDeviceData = {
42 .initState = false,
43 .lightNum = 0,
44 .ioService = NULL,
45 .lightInfoEntry = NULL,
46 };
47
48 return &lightDeviceData;
49 }
50
GetLightEffect(void)51 struct LightEffect *GetLightEffect(void)
52 {
53 return &g_lightEffect;
54 }
55
GetLightState(void)56 uint8_t *GetLightState(void)
57 {
58 return g_lightState;
59 }
60
SendLightMsg(uint32_t cmd,struct HdfSBuf * msg,struct HdfSBuf * reply)61 static int32_t SendLightMsg(uint32_t cmd, struct HdfSBuf *msg, struct HdfSBuf *reply)
62 {
63 struct LightDevice *priv = GetLightDevicePriv();
64
65 if (priv->ioService == NULL || priv->ioService->dispatcher == NULL ||
66 priv->ioService->dispatcher->Dispatch == NULL) {
67 HDF_LOGE("%s: para invalid", __func__);
68 return HDF_FAILURE;
69 }
70
71 int32_t ret = priv->ioService->dispatcher->Dispatch(&priv->ioService->object, cmd, msg, reply);
72 if (ret != HDF_SUCCESS) {
73 HDF_LOGE("%{public}s: Light dispatch failed", __func__);
74 return ret;
75 }
76
77 return HDF_SUCCESS;
78 }
79
ReadLightInfo(struct HdfSBuf * reply,struct LightDevice * priv)80 static int32_t ReadLightInfo(struct HdfSBuf *reply, struct LightDevice *priv)
81 {
82 struct LightInfo *pos = NULL;
83 const char *name = NULL;
84
85 if (!HdfSbufReadUint32(reply, &priv->lightNum)) {
86 HDF_LOGE("%s: sbuf read lightNum failed", __func__);
87 return HDF_FAILURE;
88 }
89
90 if (priv->lightInfoEntry != NULL) {
91 OsalMemFree(priv->lightInfoEntry);
92 priv->lightInfoEntry = NULL;
93 }
94
95 priv->lightInfoEntry = (struct LightInfo *)OsalMemCalloc(sizeof(*priv->lightInfoEntry) * priv->lightNum);
96 if (priv->lightInfoEntry == NULL) {
97 HDF_LOGE("%s: malloc fail", __func__);
98 return HDF_FAILURE;
99 }
100
101 pos = priv->lightInfoEntry;
102
103 for (uint32_t i = 0; i < priv->lightNum; ++i) {
104 if (!HdfSbufReadUint32(reply, &pos->lightId)) {
105 HDF_LOGE("%{public}s:read lightId failed!", __func__);
106 return HDF_FAILURE;
107 }
108
109 name = HdfSbufReadString(reply);
110 if (strcpy_s(pos->lightName, NAME_MAX_LEN, name) != EOK) {
111 HDF_LOGE("%{public}s:copy lightName failed!", __func__);
112 return HDF_FAILURE;
113 }
114
115 if (!HdfSbufReadUint32(reply, &pos->lightNumber)) {
116 HDF_LOGE("%{public}s:read lightNumber failed!", __func__);
117 return HDF_FAILURE;
118 }
119
120 if (!HdfSbufReadInt32(reply, &pos->lightType)) {
121 HDF_LOGE("%{public}s:read lightType failed!", __func__);
122 return HDF_FAILURE;
123 }
124 pos++;
125 }
126
127 return HDF_SUCCESS;
128 }
129
GetLightInfo(struct LightInfo ** lightInfo,uint32_t * count)130 static int32_t GetLightInfo(struct LightInfo **lightInfo, uint32_t *count)
131 {
132 if ((lightInfo == NULL) || (count == NULL)) {
133 HDF_LOGE("%s:line:%{public}d pointer is null and return ret", __func__, __LINE__);
134 return HDF_FAILURE;
135 }
136
137 struct LightDevice *priv = GetLightDevicePriv();
138
139 if (priv->lightNum > 0) {
140 *count = priv->lightNum;
141 *lightInfo = priv->lightInfoEntry;
142 return HDF_SUCCESS;
143 }
144
145 (void)OsalMutexLock(&priv->mutex);
146 struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
147 if (reply == NULL) {
148 HDF_LOGE("%s: get sbuf failed", __func__);
149 (void)OsalMutexUnlock(&priv->mutex);
150 return HDF_FAILURE;
151 }
152
153 int32_t ret = SendLightMsg(LIGHT_IO_CMD_GET_INFO_LIST, NULL, reply);
154 if (ret != HDF_SUCCESS) {
155 HDF_LOGE("%{public}s: Light send cmd failed, ret[%{public}d]", __func__, ret);
156 HdfSbufRecycle(reply);
157 (void)OsalMutexUnlock(&priv->mutex);
158 return ret;
159 }
160
161 if (ReadLightInfo(reply, priv) != HDF_SUCCESS) {
162 HdfSbufRecycle(reply);
163 (void)OsalMutexUnlock(&priv->mutex);
164 return HDF_FAILURE;
165 }
166
167 HdfSbufRecycle(reply);
168 (void)OsalMutexUnlock(&priv->mutex);
169
170 *count = priv->lightNum;
171 *lightInfo = priv->lightInfoEntry;
172
173 return HDF_SUCCESS;
174 }
175
OnLightValidityJudgment(uint32_t lightId,struct LightEffect * effect)176 static int32_t OnLightValidityJudgment(uint32_t lightId, struct LightEffect *effect)
177 {
178 if (lightId >= LIGHT_ID_BUTT) {
179 HDF_LOGE("%{public}s: id not supported", __func__);
180 return LIGHT_NOT_SUPPORT;
181 }
182
183 if (effect->flashEffect.flashMode < LIGHT_FLASH_NONE || effect->flashEffect.flashMode > LIGHT_FLASH_BLINK) {
184 HDF_LOGE("%{public}s: flashMode not supported", __func__);
185 return LIGHT_NOT_FLASH;
186 }
187
188 if ((effect->flashEffect.flashMode == LIGHT_FLASH_BLINK) && (effect->flashEffect.onTime == 0 ||
189 effect->flashEffect.offTime == 0)) {
190 HDF_LOGE("%{public}s: flashMode not supported", __func__);
191 return LIGHT_NOT_FLASH;
192 }
193
194 return LIGHT_SUCCESS;
195 }
196
OnLight(uint32_t lightId,struct LightEffect * effect)197 static int32_t OnLight(uint32_t lightId, struct LightEffect *effect)
198 {
199 int32_t ret;
200
201 if (effect == NULL) {
202 HDF_LOGE("%{public}s: effect is NULL", __func__);
203 return HDF_FAILURE;
204 }
205
206 ret = OnLightValidityJudgment(lightId, effect);
207 if (ret != HDF_SUCCESS) {
208 HDF_LOGE("%{public}s: effect is false", __func__);
209 return ret;
210 }
211
212 struct LightDevice *priv = GetLightDevicePriv();
213 (void)OsalMutexLock(&priv->mutex);
214
215 struct HdfSBuf *msg = HdfSbufObtainDefaultSize();
216 if (msg == NULL) {
217 HDF_LOGE("%{public}s: Failed to obtain sBuf size", __func__);
218 (void)OsalMutexUnlock(&priv->mutex);
219 return HDF_FAILURE;
220 }
221
222 if (!HdfSbufWriteInt32(msg, lightId)) {
223 HDF_LOGE("%{public}s: Light write id failed", __func__);
224 HdfSbufRecycle(msg);
225 (void)OsalMutexUnlock(&priv->mutex);
226 return HDF_FAILURE;
227 }
228
229 if (!HdfSbufWriteInt32(msg, LIGHT_OPS_IO_CMD_ENABLE)) {
230 HDF_LOGE("%{public}s: Light write enable failed", __func__);
231 HdfSbufRecycle(msg);
232 (void)OsalMutexUnlock(&priv->mutex);
233 return HDF_FAILURE;
234 }
235
236 if (!HdfSbufWriteBuffer(msg, effect, sizeof(*effect))) {
237 HDF_LOGE("%{public}s: Light write enable failed", __func__);
238 HdfSbufRecycle(msg);
239 (void)OsalMutexUnlock(&priv->mutex);
240 return HDF_FAILURE;
241 }
242
243 ret = SendLightMsg(LIGHT_IO_CMD_OPS, msg, NULL);
244 if (ret != HDF_SUCCESS) {
245 HDF_LOGE("%{public}s: Light enable failed, ret[%{public}d]", __func__, ret);
246 }
247 HdfSbufRecycle(msg);
248 (void)OsalMutexUnlock(&priv->mutex);
249
250 if (memcpy_s(&g_lightEffect, sizeof(g_lightEffect), effect, sizeof(*effect)) != EOK) {
251 HDF_LOGE("%{public}s: Light effect cpy faild", __func__);
252 return HDF_FAILURE;
253 }
254
255 g_lightState[lightId] = LIGHT_ON;
256
257 return ret;
258 }
259
OnMultiLightsValidityJudgment(uint32_t lightId,const struct LightColor * colors,const uint32_t count)260 static int32_t OnMultiLightsValidityJudgment(uint32_t lightId, const struct LightColor *colors, const uint32_t count)
261 {
262 if (lightId >= LIGHT_ID_BUTT) {
263 HDF_LOGE("%{public}s: id not supported", __func__);
264 return HDF_ERR_NOT_SUPPORT;
265 }
266
267 if (colors == NULL) {
268 HDF_LOGE("%{public}s: colors is nullptr", __func__);
269 return HDF_ERR_INVALID_PARAM;
270 }
271
272 if (count == 0 || count > MULTI_LIGHT_MAX_NUMBER) {
273 HDF_LOGE("%{public}s: count out of range", __func__);
274 return HDF_ERR_INVALID_PARAM;
275 }
276
277 return HDF_SUCCESS;
278 }
279
OnMultiLights(uint32_t lightId,const struct LightColor * colors,const uint32_t count)280 static int32_t OnMultiLights(uint32_t lightId, const struct LightColor *colors, const uint32_t count)
281 {
282 int32_t ret;
283 struct HdfSBuf *sbuf = NULL;
284
285 ret = OnMultiLightsValidityJudgment(lightId, colors, count);
286 if (ret != HDF_SUCCESS) {
287 HDF_LOGE("%{public}s: effect is false", __func__);
288 return ret;
289 }
290
291 struct LightDevice *priv = GetLightDevicePriv();
292 (void)OsalMutexLock(&priv->mutex);
293
294 sbuf = HdfSbufObtain(sizeof(struct LightColor) * count);
295 if (sbuf == NULL) {
296 HDF_LOGE("%{public}s: sbuf malloc failed", __func__);
297 return HDF_DEV_ERR_NO_MEMORY;
298 }
299
300 if (!HdfSbufWriteInt32(sbuf, lightId)) {
301 HDF_LOGE("%{public}s: light write id failed", __func__);
302 ret = HDF_FAILURE;
303 goto EXIT;
304 }
305
306 if (!HdfSbufWriteInt32(sbuf, LIGHT_OPS_IO_CMD_ENABLE_MULTI_LIGHTS)) {
307 HDF_LOGE("%{public}s: light write cmd failed", __func__);
308 ret = HDF_FAILURE;
309 goto EXIT;
310 }
311
312 if (!HdfSbufWriteBuffer(sbuf, colors, sizeof(*colors))) {
313 HDF_LOGE("%{public}s: light write buf failed", __func__);
314 ret = HDF_FAILURE;
315 goto EXIT;
316 }
317
318 if (!HdfSbufWriteInt32(sbuf, count)) {
319 HDF_LOGE("%{public}s: light write count failed", __func__);
320 ret = HDF_FAILURE;
321 goto EXIT;
322 }
323
324 ret = SendLightMsg(LIGHT_IO_CMD_OPS, sbuf, NULL);
325 if (ret != HDF_SUCCESS) {
326 HDF_LOGE("%{public}s: light enable failed, ret[%{public}d]", __func__, ret);
327 }
328
329 EXIT:
330 HdfSbufRecycle(sbuf);
331 (void)OsalMutexUnlock(&priv->mutex);
332
333 if (memcpy_s(&(g_lightEffect.lightColor), sizeof(g_lightEffect.lightColor),
334 colors, sizeof(*colors)) != EOK) {
335 HDF_LOGE("%{public}s: Light colors cpy faild", __func__);
336 return HDF_FAILURE;
337 }
338
339 g_lightState[lightId] = LIGHT_ON;
340
341 return ret;
342 }
343
OffLight(uint32_t lightId)344 static int32_t OffLight(uint32_t lightId)
345 {
346 if (lightId >= LIGHT_ID_BUTT) {
347 HDF_LOGE("%{public}s: id not supported", __func__);
348 return HDF_FAILURE;
349 }
350
351 struct LightDevice *priv = GetLightDevicePriv();
352 (void)OsalMutexLock(&priv->mutex);
353
354 struct HdfSBuf *msg = HdfSbufObtainDefaultSize();
355 if (msg == NULL) {
356 HDF_LOGE("%{public}s: Failed to obtain sBuf", __func__);
357 (void)OsalMutexUnlock(&priv->mutex);
358 return HDF_FAILURE;
359 }
360
361 if (!HdfSbufWriteInt32(msg, lightId)) {
362 HDF_LOGE("%{public}s: Light write id failed", __func__);
363 HdfSbufRecycle(msg);
364 (void)OsalMutexUnlock(&priv->mutex);
365 return HDF_FAILURE;
366 }
367
368 if (!HdfSbufWriteInt32(msg, LIGHT_OPS_IO_CMD_DISABLE)) {
369 HDF_LOGE("%{public}s: Light write disable failed", __func__);
370 HdfSbufRecycle(msg);
371 (void)OsalMutexUnlock(&priv->mutex);
372 return HDF_FAILURE;
373 }
374
375 int32_t ret = SendLightMsg(LIGHT_IO_CMD_OPS, msg, NULL);
376 if (ret != HDF_SUCCESS) {
377 HDF_LOGE("%{public}s: Light disable failed, ret[%{public}d]", __func__, ret);
378 }
379 HdfSbufRecycle(msg);
380 (void)OsalMutexUnlock(&priv->mutex);
381
382 g_lightState[lightId] = LIGHT_OFF;
383
384 return ret;
385 }
386
NewLightInterfaceInstance(void)387 const struct LightInterface *NewLightInterfaceInstance(void)
388 {
389 static struct LightInterface lightDevInstance;
390 struct LightDevice *priv = GetLightDevicePriv();
391
392 if (priv->initState) {
393 return &lightDevInstance;
394 }
395
396 OsalMutexInit(&priv->mutex);
397 lightDevInstance.GetLightInfo = GetLightInfo;
398 lightDevInstance.TurnOnLight = OnLight;
399 lightDevInstance.TurnOffLight = OffLight;
400 lightDevInstance.TurnOnMultiLights = OnMultiLights;
401
402 priv->ioService = HdfIoServiceBind(LIGHT_SERVICE_NAME);
403 if (priv->ioService == NULL) {
404 HDF_LOGE("%s: get light ioService failed", __func__);
405 OsalMutexDestroy(&priv->mutex);
406 return NULL;
407 }
408
409 priv->initState = true;
410 HDF_LOGI("get light devInstance success");
411
412 return &lightDevInstance;
413 }
414
FreeLightInterfaceInstance(void)415 int32_t FreeLightInterfaceInstance(void)
416 {
417 struct LightDevice *priv = GetLightDevicePriv();
418
419 if (!priv->initState) {
420 HDF_LOGI("%s: light instance had released", __func__);
421 return HDF_SUCCESS;
422 }
423
424 priv->lightNum = 0;
425
426 if (priv->ioService != NULL) {
427 HdfIoServiceRecycle(priv->ioService);
428 }
429
430 if (priv->lightInfoEntry != NULL) {
431 OsalMemFree(priv->lightInfoEntry);
432 priv->lightInfoEntry = NULL;
433 }
434
435 OsalMutexDestroy(&priv->mutex);
436
437 return HDF_SUCCESS;
438 }