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![Light driver model](figures/light_driver_model.png)
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![How light driver works](figures/light_working.png)
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