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