1e41f4b71Sopenharmony_ci# Light 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci 4e41f4b71Sopenharmony_ci## Overview 5e41f4b71Sopenharmony_ci 6e41f4b71Sopenharmony_ci### Introduction 7e41f4b71Sopenharmony_ci 8e41f4b71Sopenharmony_ciThe light driver model provides APIs for the upper-layer light hardware service layer to control lights, including obtaining the light type, setting the lighting mode and blinking effect, and turning on or off a light. This model implements cross-OS porting and differentiated configurations based on the Hardware Driver Foundation (HDF) to achieve the goal of "one-time development for cross-system deployment" of the light driver. 9e41f4b71Sopenharmony_ci 10e41f4b71Sopenharmony_ciThe figure below shows the light driver model. 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci**Figure 1** Light driver model 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci 16e41f4b71Sopenharmony_ci### Working Principles 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ciThe figure below shows how the light driver works. 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci**Figure 2** How light driver works 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ciThe following describes how to start and run the light module driver on an RK3568 board that runs the standard system. 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci1. The Device Manager reads the Light device management configuration from the **device_info.hcs** file. 27e41f4b71Sopenharmony_ci2. The Device Manager reads the light data configuration from the **light_config.hcs** file. 28e41f4b71Sopenharmony_ci3. The HCS Parser parses the light device management configuration, loads the Light Host, and controls the Host to load the driver. 29e41f4b71Sopenharmony_ci4. The Light Proxy obtains the light HDI service instance and calls the Light Stub over Inter-Process Communication (IPC). 30e41f4b71Sopenharmony_ci5. The Light Stub processes IPC-related service logic and calls the Light Controller after parameter deserialization. 31e41f4b71Sopenharmony_ci6. The Light Controller implements the HDI APIs and calls the Light Abstract Driver APIs to operate the light devices. 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci## Development Guidelines 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci### When to Use 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ciLight control is widely used in daily life. For example, a light is blinking when a mobile device receives an SMS message or has low battery level, and a light changes its colors based on the device charging status. These actions are implemented by calling the APIs provided by the light driver model. 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci### Available APIs 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ciThe light driver model provides APIs for obtaining information about all the lights in the system and dynamically setting the blinking mode and duration. The light hardware service calls **GetLightInfo()** to obtain the basic light information, calls **TurnOnLight()** to set the blinking effect, and calls **TurnOffLight()** to turn off lights. The following table describes the APIs of the light driver model. 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci**Table 1** APIs of the light driver model 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci**NOTE**<br>The following APIs are C interfaces. For details about the interface declaration, see [/drivers/peripheral/light/interfaces/include](https://gitee.com/openharmony/drivers_peripheral/tree/master/light/interfaces/include). 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ci| API | Description | 48e41f4b71Sopenharmony_ci| ------------------------------------------------------------ | ------------------------------------------------------------ | 49e41f4b71Sopenharmony_ci| int32_t (*GetLightInfo)(struct LightInfo **lightInfo, uint32_t *count) | Obtains information about all types of lights in the system. <br>**lightInfo** indicates the double pointer to the light information obtained. <br>**count** indicates the pointer to the number of lights.| 50e41f4b71Sopenharmony_ci| int32_t (*TurnOnLight)(uint32_t lightId, struct LightEffect *effect) | Turns on available lights in the list based on the specified light type. <br>**lightId** indicates the light type, and **effect** indicates the pointer to the light effect.| 51e41f4b71Sopenharmony_ci| int32_t (*TurnOffLight)(uint32_t lightId) | Turns off available lights in the list based on the specified light type. | 52e41f4b71Sopenharmony_ci| int32_t (*TurnOnMultiLights)(uint32_t lightId, const struct LightColor *colors, const uint32_t count); | Turns on multiple sub-lights of a light based on the specified light type ID. | 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci### How to Develop 55e41f4b71Sopenharmony_ciDevelop the light driver based on the HDF and driver entry, configure resources, and parse the HCS configuration file. 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci1. Configure the light driver in the host. 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci - Light HCS file path: **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**. 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci - The code is as follows: 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci ```c 64e41f4b71Sopenharmony_ci /* HCS of the light device. */ 65e41f4b71Sopenharmony_ci light :: host { 66e41f4b71Sopenharmony_ci hostName = "light_host"; 67e41f4b71Sopenharmony_ci device_light :: device { 68e41f4b71Sopenharmony_ci device0 :: deviceNode { 69e41f4b71Sopenharmony_ci policy = 2; // Policy for the driver to publish services. If the value is 0, the driver does not publish services. If the value is 1, the driver publishes services to the kernel space. If the value is 2, the driver publishes services to both the kernel space and user space. 70e41f4b71Sopenharmony_ci priority = 100; // Priority (0–200) for starting the light driver. A larger value indicates a lower priority. The recommended value is 100. If the priorities are the same, the device loading sequence is not ensured. 71e41f4b71Sopenharmony_ci preload = 0; // The value 0 means to load the driver by default during the startup of the system. The value 2 means the opposite. 72e41f4b71Sopenharmony_ci permission = 0664; // Permission for the device node created. 73e41f4b71Sopenharmony_ci moduleName = "HDF_LIGHT"; // Light driver name. The value must be the same as the value of moduleName in the driver entry structure. 74e41f4b71Sopenharmony_ci serviceName = "hdf_light"; // Service published by the light driver. The service name must be unique. 75e41f4b71Sopenharmony_ci deviceMatchAttr = "hdf_light_driver"; // Keyword matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver. 76e41f4b71Sopenharmony_ci } 77e41f4b71Sopenharmony_ci } 78e41f4b71Sopenharmony_ci } 79e41f4b71Sopenharmony_ci ``` 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci2. Configure the private HCS of the light driver. 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci - Code path: **vendor\hihope\rk3568\hdf_config\khdf\light\light_config.hcs**. 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci - The code is as follows: 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci ```c 88e41f4b71Sopenharmony_ci root { 89e41f4b71Sopenharmony_ci lightConfig { 90e41f4b71Sopenharmony_ci boardConfig { 91e41f4b71Sopenharmony_ci match_attr = "hdf_light_driver"; 92e41f4b71Sopenharmony_ci lightAttr { 93e41f4b71Sopenharmony_ci light01 { 94e41f4b71Sopenharmony_ci lightId = [1]; // Lightid can contain multiple logical light IDs. For example, 1 indicates the power indicator. 95e41f4b71Sopenharmony_ci lightName = "battery"; 96e41f4b71Sopenharmony_ci lightNumber = 1; 97e41f4b71Sopenharmony_ci busRNum = 147; // GPIO value corresponding to red (light effect color). 98e41f4b71Sopenharmony_ci busGNum = 146; // GPIO value corresponding to green (light effect color). 99e41f4b71Sopenharmony_ci busBNum = 149; // GPIO value corresponding to blue (light effect color). 100e41f4b71Sopenharmony_ci defaultBrightness = 0X00FFFFFF; // Default luminance value of the system. B: bits 0 to 7; R: bits 8 to 15; G: bits 16 to 23; extended bits 24 to 31. 101e41f4b71Sopenharmony_ci onTime = 50; // Minimum duration (in milliseconds) supported by the system when the flash is on. 102e41f4b71Sopenharmony_ci offTime = 50; // Minimum duration (in milliseconds) supported by the system when the flash is off. 103e41f4b71Sopenharmony_ci } 104e41f4b71Sopenharmony_ci } 105e41f4b71Sopenharmony_ci } 106e41f4b71Sopenharmony_ci } 107e41f4b71Sopenharmony_ci } 108e41f4b71Sopenharmony_ci ``` 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci3. Implement the light driver in **drivers\hdf_core\framework\model\misc\light\driver\src\light_driver.c**. 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ci - Define the **HdfDriverEntry** object of the light driver. The driver entry function is defined as follows: 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci ```c 115e41f4b71Sopenharmony_ci /* Register the light entry data structure object. */ 116e41f4b71Sopenharmony_ci struct HdfDriverEntry g_lightDriverEntry = { 117e41f4b71Sopenharmony_ci .moduleVersion = 1, // Version of the light module. 118e41f4b71Sopenharmony_ci .moduleName = "HDF_LIGHT", // Light module name, which must be the same as the value of moduleName in the device_info.hcs file. 119e41f4b71Sopenharmony_ci .Bind = BindLightDriver, // Bind() of the light driver. 120e41f4b71Sopenharmony_ci .Init = InitLightDriver, // Init() of the light driver. 121e41f4b71Sopenharmony_ci .Release = ReleaseLightDriver, // Release() of the light driver. 122e41f4b71Sopenharmony_ci }; 123e41f4b71Sopenharmony_ci /* Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls Bind() and then Init() to load the driver. If Init() fails to be called, the HDF calls Release() to release resources and exit. */ 124e41f4b71Sopenharmony_ci HDF_INIT(g_lightDriverEntry); 125e41f4b71Sopenharmony_ci ``` 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ci - Implement **Bind()** of the light driver. 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci ```c 130e41f4b71Sopenharmony_ci /* Bind the external service provided by the light driver to the HDF. */ 131e41f4b71Sopenharmony_ci int32_t BindLightDriver(struct HdfDeviceObject *device) 132e41f4b71Sopenharmony_ci { 133e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 136e41f4b71Sopenharmony_ci /* Allocate resources for private interfaces. */ 137e41f4b71Sopenharmony_ci drvData = (struct LightDriverData *)OsalMemCalloc(sizeof(*drvData)); 138e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL); 139e41f4b71Sopenharmony_ci /* Functions to be dispatched. */ 140e41f4b71Sopenharmony_ci drvData->ioService.Dispatch = DispatchLight; 141e41f4b71Sopenharmony_ci drvData->device = device; 142e41f4b71Sopenharmony_ci device->service = &drvData->ioService; 143e41f4b71Sopenharmony_ci g_lightDrvData = drvData; 144e41f4b71Sopenharmony_ci 145e41f4b71Sopenharmony_ci return HDF_SUCCESS; 146e41f4b71Sopenharmony_ci } 147e41f4b71Sopenharmony_ci ``` 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci - Implement **Init()** of the light driver. 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ci ```c 152e41f4b71Sopenharmony_ci /* Initialize the light driver. */ 153e41f4b71Sopenharmony_ci int32_t InitLightDriver(struct HdfDeviceObject *device) 154e41f4b71Sopenharmony_ci { 155e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 156e41f4b71Sopenharmony_ci 157e41f4b71Sopenharmony_ci drvData = (struct LightDriverData *)device->service; 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ci if (OsalMutexInit(&drvData->mutex) != HDF_SUCCESS) { 160e41f4b71Sopenharmony_ci return HDF_FAILURE; 161e41f4b71Sopenharmony_ci } 162e41f4b71Sopenharmony_ci /* Initialize the workqueue. */ 163e41f4b71Sopenharmony_ci if (HdfWorkQueueInit(&drvData->workQueue, LIGHT_WORK_QUEUE_NAME) != HDF_SUCCESS) { 164e41f4b71Sopenharmony_ci return HDF_FAILURE; 165e41f4b71Sopenharmony_ci } 166e41f4b71Sopenharmony_ci /* Initialize work items. */ 167e41f4b71Sopenharmony_ci if (HdfWorkInit(&drvData->work, LightWorkEntry, (void*)drvData) != HDF_SUCCESS) { 168e41f4b71Sopenharmony_ci return HDF_FAILURE; 169e41f4b71Sopenharmony_ci } 170e41f4b71Sopenharmony_ci /* Parse the HCS. */ 171e41f4b71Sopenharmony_ci if (GetLightConfigData(device->property) != HDF_SUCCESS) { 172e41f4b71Sopenharmony_ci return HDF_FAILURE; 173e41f4b71Sopenharmony_ci } 174e41f4b71Sopenharmony_ci /* Set the GPIO pin direction. */ 175e41f4b71Sopenharmony_ci if (SetLightGpioDir(drvData) != HDF_SUCCESS) { 176e41f4b71Sopenharmony_ci return HDF_FAILURE; 177e41f4b71Sopenharmony_ci } 178e41f4b71Sopenharmony_ci 179e41f4b71Sopenharmony_ci return HDF_SUCCESS; 180e41f4b71Sopenharmony_ci } 181e41f4b71Sopenharmony_ci ``` 182e41f4b71Sopenharmony_ci 183e41f4b71Sopenharmony_ci - Implement **Release()** of the light driver. When the driver is unloaded or **Init** fails to be executed, **Release()** can be used to release resources. The implementation is as follows: 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ci ```c 186e41f4b71Sopenharmony_ci /* Release the resources allocated for driver initialization. */ 187e41f4b71Sopenharmony_ci void ReleaseLightDriver(struct HdfDeviceObject *device) 188e41f4b71Sopenharmony_ci { 189e41f4b71Sopenharmony_ci int32_t i; 190e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 191e41f4b71Sopenharmony_ci /* Release the allocated resources. */ 192e41f4b71Sopenharmony_ci for (i = LIGHT_ID_NONE; i < LIGHT_ID_BUTT; ++i) { 193e41f4b71Sopenharmony_ci if (drvData->info[i] != NULL) { 194e41f4b71Sopenharmony_ci OsalMemFree(drvData->info[i]); 195e41f4b71Sopenharmony_ci drvData->info[i] = NULL; 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci } 198e41f4b71Sopenharmony_ci /* Destroy the work queue resource if the sensor is in position. */ 199e41f4b71Sopenharmony_ci HdfWorkDestroy(&drvData->work); 200e41f4b71Sopenharmony_ci HdfWorkQueueDestroy(&drvData->workQueue); 201e41f4b71Sopenharmony_ci (void)OsalMutexDestroy(&drvData->mutex); 202e41f4b71Sopenharmony_ci OsalMemFree(drvData); 203e41f4b71Sopenharmony_ci g_lightDrvData = NULL; 204e41f4b71Sopenharmony_ci } 205e41f4b71Sopenharmony_ci ``` 206e41f4b71Sopenharmony_ci 207e41f4b71Sopenharmony_ci - The light driver parses the light device management configuration information from the HCS file. 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci ```c 210e41f4b71Sopenharmony_ci /* Obtain the Light basic configuration from the HCS file. */ 211e41f4b71Sopenharmony_ci static int32_t GetLightBaseConfigData(const struct DeviceResourceNode *node, const struct DeviceResourceIface *parser, 212e41f4b71Sopenharmony_ci uint32_t lightId) 213e41f4b71Sopenharmony_ci { 214e41f4b71Sopenharmony_ci int32_t ret; 215e41f4b71Sopenharmony_ci uint32_t *defaultBrightness = NULL; 216e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 217e41f4b71Sopenharmony_ci const char *name = NULL; 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci drvData = GetLightDrvData(); 220e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 221e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); 222e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM); 223e41f4b71Sopenharmony_ci /* Types are used as subscripts to create space. */ 224e41f4b71Sopenharmony_ci drvData->info[lightId] = (struct LightDeviceInfo *)OsalMemCalloc(sizeof(struct LightDeviceInfo)); 225e41f4b71Sopenharmony_ci if (drvData->info[lightId] == NULL) { 226e41f4b71Sopenharmony_ci HDF_LOGE("%s: malloc fail", __func__); 227e41f4b71Sopenharmony_ci return HDF_FAILURE; 228e41f4b71Sopenharmony_ci } 229e41f4b71Sopenharmony_ci /* Fill in the light device information. */ 230e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "busRNum", (uint32_t *)&drvData->info[lightId]->busRNum, 0); 231e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 232e41f4b71Sopenharmony_ci drvData->info[lightId]->busRNum = LIGHT_INVALID_GPIO; 233e41f4b71Sopenharmony_ci } 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "busGNum", (uint32_t *)&drvData->info[lightId]->busGNum, 0); 236e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 237e41f4b71Sopenharmony_ci drvData->info[lightId]->busGNum = LIGHT_INVALID_GPIO; 238e41f4b71Sopenharmony_ci } 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "busBNum", (uint32_t *)&drvData->info[lightId]->busBNum, 0); 241e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 242e41f4b71Sopenharmony_ci drvData->info[lightId]->busBNum = LIGHT_INVALID_GPIO; 243e41f4b71Sopenharmony_ci } 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci ret = parser->GetString(node, "lightName", &name, NULL); 246e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 247e41f4b71Sopenharmony_ci HDF_LOGE("%s:get lightName failed!", __func__); 248e41f4b71Sopenharmony_ci return HDF_FAILURE; 249e41f4b71Sopenharmony_ci } 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci if (strcpy_s(drvData->info[lightId]->lightInfo.lightName, NAME_MAX_LEN, name) != EOK) { 252e41f4b71Sopenharmony_ci HDF_LOGE("%s:copy lightName failed!", __func__); 253e41f4b71Sopenharmony_ci return HDF_FAILURE; 254e41f4b71Sopenharmony_ci } 255e41f4b71Sopenharmony_ci 256e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "lightNumber", (uint32_t *)&drvData->info[lightId]->lightInfo.lightNumber, 0); 257e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 258e41f4b71Sopenharmony_ci HDF_LOGE("%s:get lightNumber failed!", __func__); 259e41f4b71Sopenharmony_ci return HDF_FAILURE; 260e41f4b71Sopenharmony_ci } 261e41f4b71Sopenharmony_ci 262e41f4b71Sopenharmony_ci defaultBrightness = (uint32_t *)&drvData->info[lightId]->defaultBrightness; 263e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "defaultBrightness", defaultBrightness, 0); 264e41f4b71Sopenharmony_ci CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "defaultBrightness"); 265e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "onTime", &drvData->info[lightId]->onTime, 0); 266e41f4b71Sopenharmony_ci CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "onTime"); 267e41f4b71Sopenharmony_ci ret = parser->GetUint32(node, "offTime", &drvData->info[lightId]->offTime, 0); 268e41f4b71Sopenharmony_ci CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "offTime"); 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci drvData->info[lightId]->lightBrightness = 0; 271e41f4b71Sopenharmony_ci drvData->info[lightId]->lightState = LIGHT_STATE_STOP; 272e41f4b71Sopenharmony_ci 273e41f4b71Sopenharmony_ci return HDF_SUCCESS; 274e41f4b71Sopenharmony_ci } 275e41f4b71Sopenharmony_ci ``` 276e41f4b71Sopenharmony_ci 277e41f4b71Sopenharmony_ci - Allocate resources and parse the HCS configuration information as follows: 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci ```c 280e41f4b71Sopenharmony_ci /* Allocate resources and parse the HCS. */ 281e41f4b71Sopenharmony_ci static int32_t ParseLightInfo(const struct DeviceResourceNode *node, const struct DeviceResourceIface *parser) 282e41f4b71Sopenharmony_ci { 283e41f4b71Sopenharmony_ci int32_t ret; 284e41f4b71Sopenharmony_ci uint32_t i; 285e41f4b71Sopenharmony_ci uint32_t temp; 286e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci drvData = GetLightDrvData(); 289e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 290e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM); 291e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM); 292e41f4b71Sopenharmony_ci /* Obtain the number of supported light types from the HCS. */ 293e41f4b71Sopenharmony_ci drvData->lightNum = (uint32_t)parser->GetElemNum(node, "lightId"); 294e41f4b71Sopenharmony_ci if (drvData->lightNum > LIGHT_ID_NUM) { 295e41f4b71Sopenharmony_ci HDF_LOGE("%s: lightNum cross the border", __func__); 296e41f4b71Sopenharmony_ci return HDF_FAILURE; 297e41f4b71Sopenharmony_ci } 298e41f4b71Sopenharmony_ci 299e41f4b71Sopenharmony_ci ret = memset_s(drvData->info, sizeof(drvData->info[LIGHT_ID_NONE]) * LIGHT_ID_BUTT, 0, 300e41f4b71Sopenharmony_ci sizeof(drvData->info[LIGHT_ID_NONE]) * LIGHT_ID_BUTT); 301e41f4b71Sopenharmony_ci CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "memset_s"); 302e41f4b71Sopenharmony_ci 303e41f4b71Sopenharmony_ci for (i = 0; i < drvData->lightNum; ++i) { 304e41f4b71Sopenharmony_ci /* Obtain the light type. */ 305e41f4b71Sopenharmony_ci ret = parser->GetUint32ArrayElem(node, "lightId", i, &temp, 0); 306e41f4b71Sopenharmony_ci CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "lightId"); 307e41f4b71Sopenharmony_ci 308e41f4b71Sopenharmony_ci if (temp >= LIGHT_ID_BUTT) { 309e41f4b71Sopenharmony_ci HDF_LOGE("%s: light id invalid para", __func__); 310e41f4b71Sopenharmony_ci return HDF_FAILURE; 311e41f4b71Sopenharmony_ci } 312e41f4b71Sopenharmony_ci 313e41f4b71Sopenharmony_ci ret = GetLightBaseConfigData(node, parser, temp); 314e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 315e41f4b71Sopenharmony_ci HDF_LOGE("%s: get light base config fail", __func__); 316e41f4b71Sopenharmony_ci return HDF_FAILURE; 317e41f4b71Sopenharmony_ci } 318e41f4b71Sopenharmony_ci } 319e41f4b71Sopenharmony_ci 320e41f4b71Sopenharmony_ci return HDF_SUCCESS; 321e41f4b71Sopenharmony_ci } 322e41f4b71Sopenharmony_ci ``` 323e41f4b71Sopenharmony_ci 324e41f4b71Sopenharmony_ci - Use the internal APIs of the light driver to obtain the light type information, set the blinking mode, turn on and trun off lights, and create and destroy timers based on the blinking mode. 325e41f4b71Sopenharmony_ci 326e41f4b71Sopenharmony_ci - The **GetAllLightInfo** interface is implemented as follows: 327e41f4b71Sopenharmony_ci 328e41f4b71Sopenharmony_ci ```c 329e41f4b71Sopenharmony_ci /* The light driver service calls GetAllLightInfo() to obtain the light type information. */ 330e41f4b71Sopenharmony_ci static int32_t GetAllLightInfo(struct HdfSBuf *data, struct HdfSBuf *reply) 331e41f4b71Sopenharmony_ci { 332e41f4b71Sopenharmony_ci (void)data; 333e41f4b71Sopenharmony_ci uint32_t i; 334e41f4b71Sopenharmony_ci struct LightInfo lightInfo; 335e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 336e41f4b71Sopenharmony_ci 337e41f4b71Sopenharmony_ci drvData = GetLightDrvData(); 338e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 339e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM); 340e41f4b71Sopenharmony_ci 341e41f4b71Sopenharmony_ci if (!HdfSbufWriteUint32(reply, drvData->lightNum)) { 342e41f4b71Sopenharmony_ci HDF_LOGE("%s: write sbuf failed", __func__); 343e41f4b71Sopenharmony_ci return HDF_FAILURE; 344e41f4b71Sopenharmony_ci } 345e41f4b71Sopenharmony_ci 346e41f4b71Sopenharmony_ci for (i = 0; i < LIGHT_ID_BUTT; ++i) { 347e41f4b71Sopenharmony_ci if (drvData->info[i] == NULL) { 348e41f4b71Sopenharmony_ci continue; 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci lightInfo.lightId = i; 351e41f4b71Sopenharmony_ci 352e41f4b71Sopenharmony_ci if (!HdfSbufWriteUint32(reply, lightInfo.lightId)) { 353e41f4b71Sopenharmony_ci HDF_LOGE("%s: write lightId failed", __func__); 354e41f4b71Sopenharmony_ci return HDF_FAILURE; 355e41f4b71Sopenharmony_ci } 356e41f4b71Sopenharmony_ci 357e41f4b71Sopenharmony_ci if (strcpy_s(lightInfo.lightName, NAME_MAX_LEN, drvData->info[i]->lightInfo.lightName) != EOK) { 358e41f4b71Sopenharmony_ci HDF_LOGE("%s:copy lightName failed!", __func__); 359e41f4b71Sopenharmony_ci return HDF_FAILURE; 360e41f4b71Sopenharmony_ci } 361e41f4b71Sopenharmony_ci 362e41f4b71Sopenharmony_ci if (!HdfSbufWriteString(reply, (const char *)lightInfo.lightName)) { 363e41f4b71Sopenharmony_ci HDF_LOGE("%s: write lightName failed", __func__); 364e41f4b71Sopenharmony_ci return HDF_FAILURE; 365e41f4b71Sopenharmony_ci } 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ci lightInfo.lightNumber = drvData->info[i]->lightInfo.lightNumber; 368e41f4b71Sopenharmony_ci if (!HdfSbufWriteUint32(reply, lightInfo.lightNumber)) { 369e41f4b71Sopenharmony_ci HDF_LOGE("%s: write lightNumber failed", __func__); 370e41f4b71Sopenharmony_ci return HDF_FAILURE; 371e41f4b71Sopenharmony_ci } 372e41f4b71Sopenharmony_ci 373e41f4b71Sopenharmony_ci lightInfo.lightType = HDF_LIGHT_TYPE_RGB_COLOR; 374e41f4b71Sopenharmony_ci if (!HdfSbufWriteUint32(reply, lightInfo.lightType)) { 375e41f4b71Sopenharmony_ci HDF_LOGE("%s: write lightType failed", __func__); 376e41f4b71Sopenharmony_ci return HDF_FAILURE; 377e41f4b71Sopenharmony_ci } 378e41f4b71Sopenharmony_ci } 379e41f4b71Sopenharmony_ci 380e41f4b71Sopenharmony_ci return HDF_SUCCESS; 381e41f4b71Sopenharmony_ci } 382e41f4b71Sopenharmony_ci ``` 383e41f4b71Sopenharmony_ci 384e41f4b71Sopenharmony_ci - The **TurnOnLight** interface is implemented as follows: 385e41f4b71Sopenharmony_ci 386e41f4b71Sopenharmony_ci ```c 387e41f4b71Sopenharmony_ci /* Enable lights based on the specified light type and input parameters. */ 388e41f4b71Sopenharmony_ci static int32_t TurnOnLight(uint32_t lightId, struct HdfSBuf *data, struct HdfSBuf *reply) 389e41f4b71Sopenharmony_ci { 390e41f4b71Sopenharmony_ci (void)reply; 391e41f4b71Sopenharmony_ci uint32_t len; 392e41f4b71Sopenharmony_ci struct LightEffect *buf = NULL; 393e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 394e41f4b71Sopenharmony_ci 395e41f4b71Sopenharmony_ci drvData = GetLightDrvData(); 396e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 397e41f4b71Sopenharmony_ci 398e41f4b71Sopenharmony_ci if (drvData->info[lightId] == NULL) { 399e41f4b71Sopenharmony_ci HDF_LOGE("%s: light id info is null", __func__); 400e41f4b71Sopenharmony_ci return HDF_FAILURE; 401e41f4b71Sopenharmony_ci } 402e41f4b71Sopenharmony_ci 403e41f4b71Sopenharmony_ci if (!HdfSbufReadBuffer(data, (const void **)&buf, &len)) { 404e41f4b71Sopenharmony_ci HDF_LOGE("%s: light read data failed", __func__); 405e41f4b71Sopenharmony_ci return HDF_FAILURE; 406e41f4b71Sopenharmony_ci } 407e41f4b71Sopenharmony_ci /* Receive the lightBrightness value passed in. Bits 24 to 31 indicate extension bits, bits 16 to 23 indicate red, bits 8 to 15 indicate green, and bits 0 to 7 indicate blue. If lightBrightness is not 0, enable the light in the specified color. 408e41f4b71Sopenharmony_ci Set the light brightness to a value ranging from 0 to 255 if supported. */ 409e41f4b71Sopenharmony_ci if (buf->lightColor.colorValue.rgbColor.r != 0) { 410e41f4b71Sopenharmony_ci drvData->info[lightId]->lightBrightness |= 0X00FF0000; 411e41f4b71Sopenharmony_ci } 412e41f4b71Sopenharmony_ci 413e41f4b71Sopenharmony_ci if (buf->lightColor.colorValue.rgbColor.g != 0) { 414e41f4b71Sopenharmony_ci drvData->info[lightId]->lightBrightness |= 0X0000FF00; 415e41f4b71Sopenharmony_ci } 416e41f4b71Sopenharmony_ci 417e41f4b71Sopenharmony_ci if (buf->lightColor.colorValue.rgbColor.b != 0) { 418e41f4b71Sopenharmony_ci drvData->info[lightId]->lightBrightness |= 0X000000FF; 419e41f4b71Sopenharmony_ci } 420e41f4b71Sopenharmony_ci /* The light is steady on. */ 421e41f4b71Sopenharmony_ci if (buf->flashEffect.flashMode == LIGHT_FLASH_NONE) { 422e41f4b71Sopenharmony_ci return UpdateLight(lightId, LIGHT_STATE_START); 423e41f4b71Sopenharmony_ci } 424e41f4b71Sopenharmony_ci /* The light is blinking. */ 425e41f4b71Sopenharmony_ci if (buf->flashEffect.flashMode == LIGHT_FLASH_BLINK) { 426e41f4b71Sopenharmony_ci drvData->info[lightId]->onTime = (buf->flashEffect.onTime < drvData->info[lightId]->onTime) ? 427e41f4b71Sopenharmony_ci drvData->info[lightId]->onTime : buf->flashEffect.onTime; 428e41f4b71Sopenharmony_ci drvData->info[lightId]->offTime = (buf->flashEffect.offTime < drvData->info[lightId]->offTime) ? 429e41f4b71Sopenharmony_ci drvData->info[lightId]->offTime : buf->flashEffect.offTime; 430e41f4b71Sopenharmony_ci /* Create a timer. */ 431e41f4b71Sopenharmony_ci if (OsalTimerCreate(&drvData->timer, LIGHT_WAIT_TIME, LightTimerEntry, (uintptr_t)lightId) != HDF_SUCCESS) { 432e41f4b71Sopenharmony_ci HDF_LOGE("%s: create light timer fail!", __func__); 433e41f4b71Sopenharmony_ci return HDF_FAILURE; 434e41f4b71Sopenharmony_ci } 435e41f4b71Sopenharmony_ci /* Start the timer. */ 436e41f4b71Sopenharmony_ci if (OsalTimerStartLoop(&drvData->timer) != HDF_SUCCESS) { 437e41f4b71Sopenharmony_ci HDF_LOGE("%s: start light timer fail!", __func__); 438e41f4b71Sopenharmony_ci return HDF_FAILURE; 439e41f4b71Sopenharmony_ci } 440e41f4b71Sopenharmony_ci } 441e41f4b71Sopenharmony_ci 442e41f4b71Sopenharmony_ci return HDF_SUCCESS; 443e41f4b71Sopenharmony_ci } 444e41f4b71Sopenharmony_ci ``` 445e41f4b71Sopenharmony_ci 446e41f4b71Sopenharmony_ci - The **TurnOffLight** interface is implemented as follows: 447e41f4b71Sopenharmony_ci 448e41f4b71Sopenharmony_ci ```c 449e41f4b71Sopenharmony_ci /* Turn off lights based on the specified light type. */ 450e41f4b71Sopenharmony_ci static int32_t TurnOffLight(uint32_t lightId, struct HdfSBuf *data, struct HdfSBuf *reply) 451e41f4b71Sopenharmony_ci { 452e41f4b71Sopenharmony_ci (void)data; 453e41f4b71Sopenharmony_ci (void)reply; 454e41f4b71Sopenharmony_ci struct LightDriverData *drvData = NULL; 455e41f4b71Sopenharmony_ci 456e41f4b71Sopenharmony_ci drvData = GetLightDrvData(); 457e41f4b71Sopenharmony_ci CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ci if (drvData->info[lightId] == NULL) { 460e41f4b71Sopenharmony_ci HDF_LOGE("%s: light id info is null", __func__); 461e41f4b71Sopenharmony_ci return HDF_FAILURE; 462e41f4b71Sopenharmony_ci } 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ci if (UpdateLight(lightId, LIGHT_STATE_STOP) != HDF_SUCCESS) { 465e41f4b71Sopenharmony_ci HDF_LOGE("%s: gpio write failed", __func__); 466e41f4b71Sopenharmony_ci return HDF_FAILURE; 467e41f4b71Sopenharmony_ci } 468e41f4b71Sopenharmony_ci 469e41f4b71Sopenharmony_ci drvData->info[lightId]->lightState = LIGHT_STATE_STOP; 470e41f4b71Sopenharmony_ci drvData->info[lightId]->lightBrightness = 0; 471e41f4b71Sopenharmony_ci /* Destroy the timer. */ 472e41f4b71Sopenharmony_ci if (drvData->timer.realTimer != NULL) { 473e41f4b71Sopenharmony_ci if (OsalTimerDelete(&drvData->timer) != HDF_SUCCESS) { 474e41f4b71Sopenharmony_ci HDF_LOGE("%s: delete light timer fail!", __func__); 475e41f4b71Sopenharmony_ci return HDF_FAILURE; 476e41f4b71Sopenharmony_ci } 477e41f4b71Sopenharmony_ci } 478e41f4b71Sopenharmony_ci 479e41f4b71Sopenharmony_ci return HDF_SUCCESS; 480e41f4b71Sopenharmony_ci } 481e41f4b71Sopenharmony_ci ``` 482e41f4b71Sopenharmony_ci 483e41f4b71Sopenharmony_ci5. Implement the HDIs of the light controller. 484e41f4b71Sopenharmony_ci 485e41f4b71Sopenharmony_ci - Code path: **drivers\peripheral\light\hal\src\light_controller.c**. 486e41f4b71Sopenharmony_ci 487e41f4b71Sopenharmony_ci - The **GetLightInfo** interface is implemented as follows: 488e41f4b71Sopenharmony_ci 489e41f4b71Sopenharmony_ci ```c 490e41f4b71Sopenharmony_ci /* Read the light type information from HdfSBuf in the light abstract driver to LightInfo. */ 491e41f4b71Sopenharmony_ci static int32_t ReadLightInfo(struct HdfSBuf *reply, struct LightDevice *priv) 492e41f4b71Sopenharmony_ci { 493e41f4b71Sopenharmony_ci struct LightInfo *pos = NULL; 494e41f4b71Sopenharmony_ci const char *name = NULL; 495e41f4b71Sopenharmony_ci 496e41f4b71Sopenharmony_ci if (!HdfSbufReadUint32(reply, &priv->lightNum)) { 497e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read lightNum failed", __func__); 498e41f4b71Sopenharmony_ci return HDF_FAILURE; 499e41f4b71Sopenharmony_ci } 500e41f4b71Sopenharmony_ci 501e41f4b71Sopenharmony_ci if (priv->lightInfoEntry != NULL) { 502e41f4b71Sopenharmony_ci OsalMemFree(priv->lightInfoEntry); 503e41f4b71Sopenharmony_ci priv->lightInfoEntry = NULL; 504e41f4b71Sopenharmony_ci } 505e41f4b71Sopenharmony_ci 506e41f4b71Sopenharmony_ci priv->lightInfoEntry = (struct LightInfo *)OsalMemCalloc(sizeof(*priv->lightInfoEntry) * priv->lightNum); 507e41f4b71Sopenharmony_ci if (priv->lightInfoEntry == NULL) { 508e41f4b71Sopenharmony_ci HDF_LOGE("%s: malloc fail", __func__); 509e41f4b71Sopenharmony_ci return HDF_FAILURE; 510e41f4b71Sopenharmony_ci } 511e41f4b71Sopenharmony_ci 512e41f4b71Sopenharmony_ci pos = priv->lightInfoEntry; 513e41f4b71Sopenharmony_ci 514e41f4b71Sopenharmony_ci for (uint32_t i = 0; i < priv->lightNum; ++i) { 515e41f4b71Sopenharmony_ci if (!HdfSbufReadUint32(reply, &pos->lightId)) { 516e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:read lightId failed!", __func__); 517e41f4b71Sopenharmony_ci return HDF_FAILURE; 518e41f4b71Sopenharmony_ci } 519e41f4b71Sopenharmony_ci 520e41f4b71Sopenharmony_ci name = HdfSbufReadString(reply); 521e41f4b71Sopenharmony_ci if (strcpy_s(pos->lightName, NAME_MAX_LEN, name) != EOK) { 522e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:copy lightName failed!", __func__); 523e41f4b71Sopenharmony_ci return HDF_FAILURE; 524e41f4b71Sopenharmony_ci } 525e41f4b71Sopenharmony_ci 526e41f4b71Sopenharmony_ci if (!HdfSbufReadUint32(reply, &pos->lightNumber)) { 527e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:read lightNumber failed!", __func__); 528e41f4b71Sopenharmony_ci return HDF_FAILURE; 529e41f4b71Sopenharmony_ci } 530e41f4b71Sopenharmony_ci 531e41f4b71Sopenharmony_ci if (!HdfSbufReadInt32(reply, &pos->lightType)) { 532e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:read lightType failed!", __func__); 533e41f4b71Sopenharmony_ci return HDF_FAILURE; 534e41f4b71Sopenharmony_ci } 535e41f4b71Sopenharmony_ci pos++; 536e41f4b71Sopenharmony_ci } 537e41f4b71Sopenharmony_ci 538e41f4b71Sopenharmony_ci return HDF_SUCCESS; 539e41f4b71Sopenharmony_ci } 540e41f4b71Sopenharmony_ci /* GetLightInfo interface implementation. */ 541e41f4b71Sopenharmony_ci static int32_t GetLightInfo(struct LightInfo **lightInfo, uint32_t *count) 542e41f4b71Sopenharmony_ci { 543e41f4b71Sopenharmony_ci if ((lightInfo == NULL) || (count == NULL)) { 544e41f4b71Sopenharmony_ci HDF_LOGE("%s:line:%{public}d pointer is null and return ret", __func__, __LINE__); 545e41f4b71Sopenharmony_ci return HDF_FAILURE; 546e41f4b71Sopenharmony_ci } 547e41f4b71Sopenharmony_ci 548e41f4b71Sopenharmony_ci struct LightDevice *priv = GetLightDevicePriv(); 549e41f4b71Sopenharmony_ci 550e41f4b71Sopenharmony_ci if (priv->lightNum > 0) { 551e41f4b71Sopenharmony_ci *count = priv->lightNum; 552e41f4b71Sopenharmony_ci *lightInfo = priv->lightInfoEntry; 553e41f4b71Sopenharmony_ci return HDF_SUCCESS; 554e41f4b71Sopenharmony_ci } 555e41f4b71Sopenharmony_ci 556e41f4b71Sopenharmony_ci (void)OsalMutexLock(&priv->mutex); 557e41f4b71Sopenharmony_ci struct HdfSBuf *reply = HdfSbufObtainDefaultSize(); 558e41f4b71Sopenharmony_ci if (reply == NULL) { 559e41f4b71Sopenharmony_ci HDF_LOGE("%s: get sbuf failed", __func__); 560e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 561e41f4b71Sopenharmony_ci return HDF_FAILURE; 562e41f4b71Sopenharmony_ci } 563e41f4b71Sopenharmony_ci 564e41f4b71Sopenharmony_ci int32_t ret = SendLightMsg(LIGHT_IO_CMD_GET_INFO_LIST, NULL, reply); 565e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 566e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light send cmd failed, ret[%{public}d]", __func__, ret); 567e41f4b71Sopenharmony_ci HdfSbufRecycle(reply); 568e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 569e41f4b71Sopenharmony_ci return ret; 570e41f4b71Sopenharmony_ci } 571e41f4b71Sopenharmony_ci 572e41f4b71Sopenharmony_ci if (ReadLightInfo(reply, priv) != HDF_SUCCESS) { 573e41f4b71Sopenharmony_ci HdfSbufRecycle(reply); 574e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 575e41f4b71Sopenharmony_ci return HDF_FAILURE; 576e41f4b71Sopenharmony_ci } 577e41f4b71Sopenharmony_ci 578e41f4b71Sopenharmony_ci HdfSbufRecycle(reply); 579e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 580e41f4b71Sopenharmony_ci 581e41f4b71Sopenharmony_ci *count = priv->lightNum; 582e41f4b71Sopenharmony_ci *lightInfo = priv->lightInfoEntry; 583e41f4b71Sopenharmony_ci 584e41f4b71Sopenharmony_ci return HDF_SUCCESS; 585e41f4b71Sopenharmony_ci } 586e41f4b71Sopenharmony_ci ``` 587e41f4b71Sopenharmony_ci 588e41f4b71Sopenharmony_ci - The **OnLight** interface is implemented as follows: 589e41f4b71Sopenharmony_ci 590e41f4b71Sopenharmony_ci ```c 591e41f4b71Sopenharmony_ci static int32_t OnLight(uint32_t lightId, struct LightEffect *effect) 592e41f4b71Sopenharmony_ci { 593e41f4b71Sopenharmony_ci int32_t ret; 594e41f4b71Sopenharmony_ci 595e41f4b71Sopenharmony_ci if (effect == NULL) { 596e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: effect is NULL", __func__); 597e41f4b71Sopenharmony_ci return HDF_FAILURE; 598e41f4b71Sopenharmony_ci } 599e41f4b71Sopenharmony_ci 600e41f4b71Sopenharmony_ci ret = OnLightValidityJudgment(lightId, effect); 601e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 602e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: effect is false", __func__); 603e41f4b71Sopenharmony_ci return ret; 604e41f4b71Sopenharmony_ci } 605e41f4b71Sopenharmony_ci 606e41f4b71Sopenharmony_ci struct LightDevice *priv = GetLightDevicePriv(); 607e41f4b71Sopenharmony_ci (void)OsalMutexLock(&priv->mutex); 608e41f4b71Sopenharmony_ci 609e41f4b71Sopenharmony_ci struct HdfSBuf *msg = HdfSbufObtainDefaultSize(); 610e41f4b71Sopenharmony_ci if (msg == NULL) { 611e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Failed to obtain sBuf size", __func__); 612e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 613e41f4b71Sopenharmony_ci return HDF_FAILURE; 614e41f4b71Sopenharmony_ci } 615e41f4b71Sopenharmony_ci 616e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(msg, lightId)) { 617e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light write id failed", __func__); 618e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 619e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 620e41f4b71Sopenharmony_ci return HDF_FAILURE; 621e41f4b71Sopenharmony_ci } 622e41f4b71Sopenharmony_ci 623e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(msg, LIGHT_OPS_IO_CMD_ENABLE)) { 624e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light write enable failed", __func__); 625e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 626e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 627e41f4b71Sopenharmony_ci return HDF_FAILURE; 628e41f4b71Sopenharmony_ci } 629e41f4b71Sopenharmony_ci 630e41f4b71Sopenharmony_ci if (!HdfSbufWriteBuffer(msg, effect, sizeof(*effect))) { 631e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light write enable failed", __func__); 632e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 633e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 634e41f4b71Sopenharmony_ci return HDF_FAILURE; 635e41f4b71Sopenharmony_ci } 636e41f4b71Sopenharmony_ci 637e41f4b71Sopenharmony_ci ret = SendLightMsg(LIGHT_IO_CMD_OPS, msg, NULL); 638e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 639e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light enable failed, ret[%{public}d]", __func__, ret); 640e41f4b71Sopenharmony_ci } 641e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 642e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 643e41f4b71Sopenharmony_ci 644e41f4b71Sopenharmony_ci if (memcpy_s(&g_lightEffect, sizeof(g_lightEffect), effect, sizeof(*effect)) != EOK) { 645e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light effect cpy faild", __func__); 646e41f4b71Sopenharmony_ci return HDF_FAILURE; 647e41f4b71Sopenharmony_ci } 648e41f4b71Sopenharmony_ci 649e41f4b71Sopenharmony_ci g_lightState[lightId] = LIGHT_ON; 650e41f4b71Sopenharmony_ci 651e41f4b71Sopenharmony_ci return ret; 652e41f4b71Sopenharmony_ci } 653e41f4b71Sopenharmony_ci ``` 654e41f4b71Sopenharmony_ci 655e41f4b71Sopenharmony_ci - The **OffLight** interface is implemented as follows: 656e41f4b71Sopenharmony_ci 657e41f4b71Sopenharmony_ci ```c 658e41f4b71Sopenharmony_ci static int32_t OffLight(uint32_t lightId) 659e41f4b71Sopenharmony_ci { 660e41f4b71Sopenharmony_ci if (lightId >= LIGHT_ID_BUTT) { 661e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: id not supported", __func__); 662e41f4b71Sopenharmony_ci return HDF_FAILURE; 663e41f4b71Sopenharmony_ci } 664e41f4b71Sopenharmony_ci 665e41f4b71Sopenharmony_ci struct LightDevice *priv = GetLightDevicePriv(); 666e41f4b71Sopenharmony_ci (void)OsalMutexLock(&priv->mutex); 667e41f4b71Sopenharmony_ci 668e41f4b71Sopenharmony_ci struct HdfSBuf *msg = HdfSbufObtainDefaultSize(); 669e41f4b71Sopenharmony_ci if (msg == NULL) { 670e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Failed to obtain sBuf", __func__); 671e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 672e41f4b71Sopenharmony_ci return HDF_FAILURE; 673e41f4b71Sopenharmony_ci } 674e41f4b71Sopenharmony_ci 675e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(msg, lightId)) { 676e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light write id failed", __func__); 677e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 678e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 679e41f4b71Sopenharmony_ci return HDF_FAILURE; 680e41f4b71Sopenharmony_ci } 681e41f4b71Sopenharmony_ci 682e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(msg, LIGHT_OPS_IO_CMD_DISABLE)) { 683e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light write disable failed", __func__); 684e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 685e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 686e41f4b71Sopenharmony_ci return HDF_FAILURE; 687e41f4b71Sopenharmony_ci } 688e41f4b71Sopenharmony_ci 689e41f4b71Sopenharmony_ci int32_t ret = SendLightMsg(LIGHT_IO_CMD_OPS, msg, NULL); 690e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 691e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: Light disable failed, ret[%{public}d]", __func__, ret); 692e41f4b71Sopenharmony_ci } 693e41f4b71Sopenharmony_ci HdfSbufRecycle(msg); 694e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 695e41f4b71Sopenharmony_ci 696e41f4b71Sopenharmony_ci g_lightState[lightId] = LIGHT_OFF; 697e41f4b71Sopenharmony_ci 698e41f4b71Sopenharmony_ci return ret; 699e41f4b71Sopenharmony_ci } 700e41f4b71Sopenharmony_ci ``` 701e41f4b71Sopenharmony_ci 702e41f4b71Sopenharmony_ci - The **OnMultiLights** interface is implemented as follows: 703e41f4b71Sopenharmony_ci 704e41f4b71Sopenharmony_ci ```c 705e41f4b71Sopenharmony_ci static int32_t OnMultiLights(uint32_t lightId, const struct LightColor *colors, const uint32_t count) 706e41f4b71Sopenharmony_ci { 707e41f4b71Sopenharmony_ci int32_t ret; 708e41f4b71Sopenharmony_ci struct HdfSBuf *sbuf = NULL; 709e41f4b71Sopenharmony_ci 710e41f4b71Sopenharmony_ci ret = OnMultiLightsValidityJudgment(lightId, colors, count); 711e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 712e41f4b71Sopenharmony_ci return ret; 713e41f4b71Sopenharmony_ci } 714e41f4b71Sopenharmony_ci 715e41f4b71Sopenharmony_ci struct LightDevice *priv = GetLightDevicePriv(); 716e41f4b71Sopenharmony_ci (void)OsalMutexLock(&priv->mutex); 717e41f4b71Sopenharmony_ci sbuf = HdfSbufObtain(sizeof(struct LightColor) * count); 718e41f4b71Sopenharmony_ci if (sbuf == NULL) { 719e41f4b71Sopenharmony_ci return HDF_DEV_ERR_NO_MEMORY; 720e41f4b71Sopenharmony_ci } 721e41f4b71Sopenharmony_ci 722e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(sbuf, lightId)) { 723e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 724e41f4b71Sopenharmony_ci goto EXIT; 725e41f4b71Sopenharmony_ci } 726e41f4b71Sopenharmony_ci 727e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(sbuf, LIGHT_OPS_IO_CMD_ENABLE_MULTI_LIGHTS)) { 728e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 729e41f4b71Sopenharmony_ci goto EXIT; 730e41f4b71Sopenharmony_ci } 731e41f4b71Sopenharmony_ci 732e41f4b71Sopenharmony_ci if (!HdfSbufWriteBuffer(sbuf, colors, sizeof(*colors))) { 733e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 734e41f4b71Sopenharmony_ci goto EXIT; 735e41f4b71Sopenharmony_ci } 736e41f4b71Sopenharmony_ci 737e41f4b71Sopenharmony_ci if (!HdfSbufWriteInt32(sbuf, count)) { 738e41f4b71Sopenharmony_ci ret = HDF_FAILURE; 739e41f4b71Sopenharmony_ci goto EXIT; 740e41f4b71Sopenharmony_ci } 741e41f4b71Sopenharmony_ci 742e41f4b71Sopenharmony_ci ret = SendLightMsg(LIGHT_IO_CMD_OPS, sbuf, NULL); 743e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 744e41f4b71Sopenharmony_ci } 745e41f4b71Sopenharmony_ci return ret; 746e41f4b71Sopenharmony_ci 747e41f4b71Sopenharmony_ci EXIT: 748e41f4b71Sopenharmony_ci HdfSbufRecycle(sbuf); 749e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&priv->mutex); 750e41f4b71Sopenharmony_ci } 751e41f4b71Sopenharmony_ci ``` 752e41f4b71Sopenharmony_ci 753e41f4b71Sopenharmony_ci### Verification 754e41f4b71Sopenharmony_ci 755e41f4b71Sopenharmony_ciAfter the driver is developed, develop auto-test cases in the light unit test to verify the basic functionalities of the driver. Use the developer self-test platform as the test environment. 756e41f4b71Sopenharmony_ci 757e41f4b71Sopenharmony_ci- The reference test code is as follows: 758e41f4b71Sopenharmony_ci 759e41f4b71Sopenharmony_ci ```c 760e41f4b71Sopenharmony_ci #include <cmath> 761e41f4b71Sopenharmony_ci #include <cstdio> 762e41f4b71Sopenharmony_ci #include <gtest/gtest.h> 763e41f4b71Sopenharmony_ci #include <securec.h> 764e41f4b71Sopenharmony_ci #include "hdf_base.h" 765e41f4b71Sopenharmony_ci #include "osal_time.h" 766e41f4b71Sopenharmony_ci #include "osal_mem.h" 767e41f4b71Sopenharmony_ci #include "light_if.h" 768e41f4b71Sopenharmony_ci #include "light_type.h" 769e41f4b71Sopenharmony_ci 770e41f4b71Sopenharmony_ci using namespace testing::ext; 771e41f4b71Sopenharmony_ci const struct LightInterface *g_lightDev = nullptr; 772e41f4b71Sopenharmony_ci static struct LightInfo *g_lightInfo = nullptr; 773e41f4b71Sopenharmony_ci static uint32_t g_count = 0; 774e41f4b71Sopenharmony_ci /* Initialize the LightInterfaceInstance before executing the test case. */ 775e41f4b71Sopenharmony_ci class HdfLightTest : public testing::Test { 776e41f4b71Sopenharmony_ci public: 777e41f4b71Sopenharmony_ci static void SetUpTestCase(); 778e41f4b71Sopenharmony_ci static void TearDownTestCase(); 779e41f4b71Sopenharmony_ci void SetUp(); 780e41f4b71Sopenharmony_ci void TearDown(); 781e41f4b71Sopenharmony_ci }; 782e41f4b71Sopenharmony_ci 783e41f4b71Sopenharmony_ci void HdfLightTest::SetUpTestCase() 784e41f4b71Sopenharmony_ci { 785e41f4b71Sopenharmony_ci g_lightDev = NewLightInterfaceInstance(); 786e41f4b71Sopenharmony_ci if (g_lightDev == nullptr) { 787e41f4b71Sopenharmony_ci printf("test light get Module instance fail\n\r"); 788e41f4b71Sopenharmony_ci } 789e41f4b71Sopenharmony_ci int32_t ret = g_lightDev->GetLightInfo(&g_lightInfo, &g_count); 790e41f4b71Sopenharmony_ci if (ret == -1) { 791e41f4b71Sopenharmony_ci printf("get light informations fail\n\r"); 792e41f4b71Sopenharmony_ci } 793e41f4b71Sopenharmony_ci } 794e41f4b71Sopenharmony_ci 795e41f4b71Sopenharmony_ci /* After the test case is executed, release the resources used by the test case. */ 796e41f4b71Sopenharmony_ci void HdfLightTest::TearDownTestCase() 797e41f4b71Sopenharmony_ci { 798e41f4b71Sopenharmony_ci if(g_lightDev != nullptr){ 799e41f4b71Sopenharmony_ci FreeLightInterfaceInstance(); 800e41f4b71Sopenharmony_ci g_lightDev = nullptr; 801e41f4b71Sopenharmony_ci } 802e41f4b71Sopenharmony_ci } 803e41f4b71Sopenharmony_ci 804e41f4b71Sopenharmony_ci void HdfLightTest::SetUp() 805e41f4b71Sopenharmony_ci { 806e41f4b71Sopenharmony_ci } 807e41f4b71Sopenharmony_ci 808e41f4b71Sopenharmony_ci void HdfLightTest::TearDown() 809e41f4b71Sopenharmony_ci { 810e41f4b71Sopenharmony_ci } 811e41f4b71Sopenharmony_ci 812e41f4b71Sopenharmony_ci /* Obtain the test light type. */ 813e41f4b71Sopenharmony_ci HWTEST_F(HdfLightTest, GetLightList001, TestSize.Level1) 814e41f4b71Sopenharmony_ci { 815e41f4b71Sopenharmony_ci struct LightInfo *info = nullptr; 816e41f4b71Sopenharmony_ci 817e41f4b71Sopenharmony_ci if (g_lightInfo == nullptr) { 818e41f4b71Sopenharmony_ci EXPECT_NE(nullptr, g_lightInfo); 819e41f4b71Sopenharmony_ci return; 820e41f4b71Sopenharmony_ci } 821e41f4b71Sopenharmony_ci 822e41f4b71Sopenharmony_ci printf("get light list num[%u]\n\r", g_count); 823e41f4b71Sopenharmony_ci info = g_lightInfo; 824e41f4b71Sopenharmony_ci 825e41f4b71Sopenharmony_ci for (uint32_t i = 0; i < g_count; ++i) { 826e41f4b71Sopenharmony_ci printf("get lightId[%u]\n\r", info->lightId); 827e41f4b71Sopenharmony_ci EXPECT_GE(info->lightId, 0); 828e41f4b71Sopenharmony_ci EXPECT_LE(info->lightId, 4); 829e41f4b71Sopenharmony_ci info++; 830e41f4b71Sopenharmony_ci } 831e41f4b71Sopenharmony_ci } 832e41f4b71Sopenharmony_ci 833e41f4b71Sopenharmony_ci /* Verify the steady on state of the light. */ 834e41f4b71Sopenharmony_ci HWTEST_F(HdfLightTest, EnableLight001, TestSize.Level1) 835e41f4b71Sopenharmony_ci { 836e41f4b71Sopenharmony_ci uint32_t i; 837e41f4b71Sopenharmony_ci struct LightEffect effect; 838e41f4b71Sopenharmony_ci effect.flashEffect.flashMode = 0; 839e41f4b71Sopenharmony_ci effect.flashEffect.onTime = 0; 840e41f4b71Sopenharmony_ci effect.flashEffect.offTime = 0; 841e41f4b71Sopenharmony_ci 842e41f4b71Sopenharmony_ci for (i = 0; i < g_count; ++i) { 843e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.r = 255; 844e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.g = 0; 845e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.b = 0; 846e41f4b71Sopenharmony_ci int32_t ret = g_lightDev->TurnOnLight(g_lightInfo[i].lightId, &effect); 847e41f4b71Sopenharmony_ci EXPECT_EQ(0, ret); 848e41f4b71Sopenharmony_ci 849e41f4b71Sopenharmony_ci OsalSleep(2); 850e41f4b71Sopenharmony_ci 851e41f4b71Sopenharmony_ci ret = g_lightDev->TurnOffLight(g_lightInfo[i].lightId); 852e41f4b71Sopenharmony_ci EXPECT_EQ(0, ret); 853e41f4b71Sopenharmony_ci 854e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.r = 0; 855e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.g = 255; 856e41f4b71Sopenharmony_ci effect.lightColor.colorValue.rgbColor.b = 0; 857e41f4b71Sopenharmony_ci ret = g_lightDev->TurnOnLight(g_lightInfo[i].lightId, &effect); 858e41f4b71Sopenharmony_ci EXPECT_EQ(0, ret); 859e41f4b71Sopenharmony_ci 860e41f4b71Sopenharmony_ci OsalSleep(2); 861e41f4b71Sopenharmony_ci 862e41f4b71Sopenharmony_ci ret = g_lightDev->TurnOffLight(g_lightInfo[i].lightId); 863e41f4b71Sopenharmony_ci EXPECT_EQ(0, ret); 864e41f4b71Sopenharmony_ci } 865e41f4b71Sopenharmony_ci } 866e41f4b71Sopenharmony_ci ``` 867e41f4b71Sopenharmony_ci 868e41f4b71Sopenharmony_ci- The reference code of the **BUILD.gn** file is as follows: 869e41f4b71Sopenharmony_ci 870e41f4b71Sopenharmony_ci ```c 871e41f4b71Sopenharmony_ci import("//build/test.gni") 872e41f4b71Sopenharmony_ci import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 873e41f4b71Sopenharmony_ci 874e41f4b71Sopenharmony_ci module_output_path = "drivers_peripheral_light/light" 875e41f4b71Sopenharmony_ci ohos_unittest("light_test") { 876e41f4b71Sopenharmony_ci module_out_path = module_output_path 877e41f4b71Sopenharmony_ci sources = [ "light_test.cpp" ] 878e41f4b71Sopenharmony_ci include_dirs = [ 879e41f4b71Sopenharmony_ci "//drivers/peripheral/light/interfaces/include", 880e41f4b71Sopenharmony_ci ] 881e41f4b71Sopenharmony_ci deps = [ "//drivers/peripheral/light/hal:hdi_light" ] 882e41f4b71Sopenharmony_ci 883e41f4b71Sopenharmony_ci external_deps = [ 884e41f4b71Sopenharmony_ci "c_utils:utils", 885e41f4b71Sopenharmony_ci "hdf_core:libhdf_utils", 886e41f4b71Sopenharmony_ci "hiviewdfx_hilog_native:libhilog", 887e41f4b71Sopenharmony_ci ] 888e41f4b71Sopenharmony_ci 889e41f4b71Sopenharmony_ci cflags = [ 890e41f4b71Sopenharmony_ci "-Wall", 891e41f4b71Sopenharmony_ci "-Wextra", 892e41f4b71Sopenharmony_ci "-Werror", 893e41f4b71Sopenharmony_ci "-Wno-format", 894e41f4b71Sopenharmony_ci "-Wno-format-extra-args", 895e41f4b71Sopenharmony_ci ] 896e41f4b71Sopenharmony_ci 897e41f4b71Sopenharmony_ci install_enable = true 898e41f4b71Sopenharmony_ci install_images = [ "vendor" ] 899e41f4b71Sopenharmony_ci module_install_dir = "bin" 900e41f4b71Sopenharmony_ci part_name = "unionman_products" 901e41f4b71Sopenharmony_ci } 902e41f4b71Sopenharmony_ci ``` 903