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 "light_uhdf_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 36struct LightEffect g_lightEffect; 37uint8_t g_lightState[LIGHT_ID_BUTT] = {0}; 38 39struct 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 51struct LightEffect *GetLightEffect(void) 52{ 53 return &g_lightEffect; 54} 55 56uint8_t *GetLightState(void) 57{ 58 return g_lightState; 59} 60 61static 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 80static 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 130static 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 176static 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 197static 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 260static 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 280static 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 (void)OsalMutexUnlock(&priv->mutex); 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 329EXIT: 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 344static 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 387const 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 415int32_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}