driver-peripherals-light-des.md 18.4 KB
Newer Older
Z
zhouyanxu 已提交
1 2 3 4 5 6 7
# LIGHT

- [概述](##概述)
  - [功能简介](###功能简介)
  - [运作机制](###运作机制)
  
- [开发指导](##开发指导)
Z
zhouyanxu 已提交
8 9 10

  - [场景介绍](###场景介绍)

Z
zhouyanxu 已提交
11 12 13 14
  - [接口说明](###接口说明)
  - [开发步骤](###开发步骤)
  - [开发实例](###开发实例)
  - [调测验证](###调测验证)
Z
zhouyanxu 已提交
15

Z
zhouyanxu 已提交
16 17 18 19 20

## 概述

### 功能简介

Z
zhouyanxu 已提交
21
​        Light驱动模型为上层Light硬件服务层提供稳定的灯控制能力接口,包括获取灯类型、配置点灯模式、配置灯闪烁效果、点灯、熄灯等。基于HDF(Hardware Driver Foundation)驱动框架开发的Light驱动模型,实现跨操作系统迁移,器件差异配置等功能。实现Light驱动“一次开发,多系统部署”的目标。Light驱动模型如[图1](#Light驱动模型图)所示:
Z
zhouyanxu 已提交
22 23 24

**图 1**  Light驱动模型图

Z
zhouyanxu 已提交
25
![Light驱动模型图](figures/Light%E9%A9%B1%E5%8A%A8%E6%A8%A1%E5%9E%8B%E5%9B%BE.png)
Z
zhouyanxu 已提交
26 27 28

### 运作机制

Z
zhouyanxu 已提交
29
通过介绍Light驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如[图2](#Lihgt驱动运行图)所示:
Z
zhouyanxu 已提交
30

Z
zhouyanxu 已提交
31
**图 2**  Light驱动运行图
Z
zhouyanxu 已提交
32

Z
zhouyanxu 已提交
33
![Light驱动运行图](figures/Light%E9%A9%B1%E5%8A%A8%E8%BF%90%E8%A1%8C%E5%9B%BE.png)
Z
zhouyanxu 已提交
34

Z
zhouyanxu 已提交
35
Light驱动模型以标准系统Hi3516DV300为例,介绍整个驱动加载及运行流程:
Z
zhouyanxu 已提交
36 37 38 39 40 41

1. 从device info HCS 的Light Host里读取Light设备管理配置信息。
2. 从light_config HCS读取Light数据配置信息。
3. 解析Light设备管理配置信息,并关联对应设备驱动。
4. 客户端下发Light Stub控制到服务端。
5. 服务端调用Light Stub控制。
Z
zhouyanxu 已提交
42
6. 启动Light抽象驱动接口。
Z
zhouyanxu 已提交
43 44 45

## 开发指导

Z
zhouyanxu 已提交
46 47 48 49
### 场景介绍

灯设备的控制,在实际生活中比比皆是,例如短信通知时闪灯、手机电量不足是预警、充电时根据充电进度变换灯的颜色等等。这些动作的实现,都需要使用 Light驱动模型提供的接口,动态配置点灯模式、配置灯闪烁效果、点灯、熄灯等。

Z
zhouyanxu 已提交
50 51
### 接口说明

Z
zhouyanxu 已提交
52
Light驱动模型支持获取系统中所有灯的信息,动态配置闪烁模式和闪烁时间的能力。Light硬件服务调用GetLightInfo获取Light设备的基本信息;调用TurnOnLight接口启动配置的闪烁效果。Light驱动模型对HDI开放的API接口能力,参考[表1](#Light驱动模型对外API接口能力介绍)
Z
zhouyanxu 已提交
53

Z
zhouyanxu 已提交
54
**表1**  Light驱动模型对外API接口能力介绍
Z
zhouyanxu 已提交
55 56 57 58 59 60 61 62

| 接口名                                                       | 功能描述                                                     |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| int32_t (*GetLightInfo)(struct LightInfo **lightInfo, uint32_t *count) | 获取系统中所有灯的信息,lightInfo表示灯设备的基本信息,count表示获取灯的个数。 |
| int32_t (*TurnOnLight)(uint32_t type, struct LightEffect *effect) | 根据指定的灯类型打开灯列表中可用的灯,type表示灯类型,effect表示要设置的效果信息。 |
| int32_t (*TurnOffLight)(uint32_t type)                       | 根据指定的灯类型关闭灯列表中可用的灯。                       |

### 开发步骤
Z
zhouyanxu 已提交
63
1.  基于HDF驱动框架,按照驱动Driver Entry程序,完成Light抽象驱动开发(主要由Bind、Init、Release、Dispatch函数接口实现),资源配置及HCS解析。完成Light驱动的设备信息配置。
Z
zhouyanxu 已提交
64
3.  调用配置解析接口,完成器件属性信息解析,器件寄存器解析,并注册到Light设备管理中。
Z
zhouyanxu 已提交
65
3.  完成Light获取类型、闪烁和停止接口开发,会根据闪烁模式创建和销毁定时器。
Z
zhouyanxu 已提交
66 67 68

### 开发实例

Z
zhouyanxu 已提交
69 70 71 72
基于HDF驱动模型,加载启动Light驱动,代码形式如下,具体原理可参考[HDF驱动开发指南](driver-hdf-development.md)。本例中Light驱动通讯接口方式选择GPIO。

灯设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。

Z
zhouyanxu 已提交
73
1. Light驱动的初始化和去初始化
Z
zhouyanxu 已提交
74

Z
zhouyanxu 已提交
75
   - 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
Z
zhouyanxu 已提交
76
     Light驱动模型使用HCS作为配置描述源码,HCS配置字段详细介绍请参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)
Z
zhouyanxu 已提交
77 78
     其Driver Entry入口函数定义如下:
     
Z
zhouyanxu 已提交
79
     ```c
Z
zhouyanxu 已提交
80
     /* 注册灯入口数据结构体对象 */
Z
zhouyanxu 已提交
81
     struct HdfDriverEntry g_lightDriverEntry = {
Z
zhouyanxu 已提交
82 83 84 85 86
         .moduleVersion = 1, // 灯模块版本号
         .moduleName = "HDF_LIGHT", // 灯模块名,要与device_info.hcs文件里灯moduleName字段值一样
         .Bind = BindLightDriver, // 灯绑定函数
         .Init = InitLightDriver, // 灯初始化函数
         .Release = ReleaseLightDriver, // 灯资源释放函数
Z
zhouyanxu 已提交
87
     };
Z
zhouyanxu 已提交
88
     /* 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release函数释放驱动资源并退出 */
Z
zhouyanxu 已提交
89 90
     HDF_INIT(g_lightDriverEntry);
     ```
Z
zhouyanxu 已提交
91 92
     
   - 基于HDF驱动框架,按照驱动Driver Entry程序,完成Light抽象驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现。
Z
zhouyanxu 已提交
93 94

     ```c
Z
zhouyanxu 已提交
95
     /* Light驱动对外发布的能力 */
Z
zhouyanxu 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
     static int32_t DispatchLight(struct HdfDeviceIoClient *client,
         int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
     {
         .....
         if (cmd == LIGHT_IO_CMD_GET_INFO_LIST) {
             CHECK_LIGHT_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM);
             return GetAllLightInfo(data, reply);
         }
     
         CHECK_LIGHT_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
         (void)OsalMutexLock(&drvData->mutex);
         if (!HdfSbufReadInt32(data, &lightType)) {
             HDF_LOGE("%s: sbuf read lightType failed", __func__);
             (void)OsalMutexUnlock(&drvData->mutex);
             return HDF_ERR_INVALID_PARAM;
         }
         .....
         ret = DispatchCmdHandle(lightType, data, reply);
         (void)OsalMutexUnlock(&drvData->mutex);
         return ret;
     }
     
Z
zhouyanxu 已提交
118
     /* Light驱动对外提供的服务绑定到HDF框架 */
Z
zhouyanxu 已提交
119 120 121 122 123
     int32_t BindLightDriver(struct HdfDeviceObject *device)
     {
         struct LightDriverData *drvData = NULL;
     
         CHECK_LIGHT_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
Z
zhouyanxu 已提交
124
         /* 私有接口分配资源 */
Z
zhouyanxu 已提交
125 126
         drvData = (struct LightDriverData *)OsalMemCalloc(sizeof(*drvData));
         CHECK_LIGHT_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL);
Z
zhouyanxu 已提交
127
         /* 需要发布的接口函数 */
Z
zhouyanxu 已提交
128 129 130 131 132 133 134
         drvData->ioService.Dispatch = DispatchLight;
         drvData->device = device;
         device->service = &drvData->ioService;
         g_lightDrvData = drvData;
         return HDF_SUCCESS;
     }
     
Z
zhouyanxu 已提交
135
     /* Light驱动初始化入口函数*/
Z
zhouyanxu 已提交
136 137 138
     int32_t InitLightDriver(struct HdfDeviceObject *device)
     { 
     	.....
Z
zhouyanxu 已提交
139
         /* 工作队列初始化 */
Z
zhouyanxu 已提交
140 141 142 143
         if (HdfWorkQueueInit(&drvData->workQueue, LIGHT_WORK_QUEUE_NAME) != HDF_SUCCESS) {
             HDF_LOGE("%s: init workQueue fail!", __func__);
             return HDF_FAILURE;
         }
Z
zhouyanxu 已提交
144
         /* 工作项初始化 */
Z
zhouyanxu 已提交
145 146 147 148
         if (HdfWorkInit(&drvData->work, LightWorkEntry, (void*)drvData) != HDF_SUCCESS) {
             HDF_LOGE("%s: init workQueue fail!", __func__);
             return HDF_FAILURE;
         }
Z
zhouyanxu 已提交
149
         /* 解析HCS配置文件 */
Z
zhouyanxu 已提交
150 151 152 153 154 155 156 157
         if (GetLightConfigData(device->property) != HDF_SUCCESS) {
             HDF_LOGE("%s: get light config fail!", __func__);
             return HDF_FAILURE;
         }
     
         return HDF_SUCCESS;
     }
     
Z
zhouyanxu 已提交
158
     /* 释放Light驱动初始化时分配的资源 */
Z
zhouyanxu 已提交
159 160 161
     void ReleaseLightDriver(struct HdfDeviceObject *device)
     { 
         .....
Z
zhouyanxu 已提交
162
         /* 释放已分配资源 */
Z
zhouyanxu 已提交
163 164 165 166 167 168 169
         for (i = LIGHT_TYPE_NONE; i < LIGHT_TYPE_BUTT; ++i) {
     
             if (drvData->info[i] != NULL) {
                 OsalMemFree(drvData->info[i]);
                 drvData->info[i] = NULL;
             }
         }
Z
zhouyanxu 已提交
170
         /* 销毁工作队列资源 */
Z
zhouyanxu 已提交
171 172 173 174 175 176 177 178 179
         HdfWorkDestroy(&drvData->work);
         HdfWorkQueueDestroy(&drvData->workQueue);
         (void)OsalMutexDestroy(&drvData->mutex);
         (void)OsalMemFree(drvData);
         g_lightDrvData = NULL;
     }
     
     ```

Z
zhouyanxu 已提交
180
   - Light设备管理模块负责系统中Light器件接口发布,在系统启动过程中,HDF框架机制通过灯Host里设备HCS配置信息,加载设备管理驱动。
Z
zhouyanxu 已提交
181 182 183 184 185

     ```hcs
     /* 灯设备HCS配置 */
     device_light :: device {
         device0 :: deviceNode {
Z
zhouyanxu 已提交
186
             policy = 2; // 驱动服务发布的策略(0:不提供服务,1:对内核态发布服务,2:对内核态和用户态都发布服务)
Z
zhouyanxu 已提交
187 188 189 190 191 192
             priority = 100; // Light驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序
             preload = 0; // 驱动按需加载字段,0表示加载,2表示不加载
             permission = 0664;  // 驱动创建设备节点权限
             moduleName = "HDF_LIGHT"; // Light驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
             serviceName = "hdf_light"; // Light驱动对外发布服务的名称,必须唯一
             deviceMatchAttr = "hdf_light_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
Z
zhouyanxu 已提交
193 194 195 196
         }
     }
     ```

Z
zhouyanxu 已提交
197
2. 分配资源,解析灯HCS配置。
Z
zhouyanxu 已提交
198

Z
zhouyanxu 已提交
199
   - 解析HCS配置文件。
Z
zhouyanxu 已提交
200 201 202 203 204 205

     ```c
     /* 分配资源,解析灯HCS配置 */
     static int32_t ParseLightInfo(const struct DeviceResourceNode *node)
     {
         .....
Z
zhouyanxu 已提交
206
         /* 从HCS获取支持灯的类型个数 */
Z
zhouyanxu 已提交
207 208 209
         drvData->lightNum = parser->GetElemNum(light, "lightType");
         ....
         for (i = 0; i < drvData->lightNum; ++i) {
Z
zhouyanxu 已提交
210
         /* 获取类型 */
Z
zhouyanxu 已提交
211 212 213 214 215 216
         ret = parser->GetUint32ArrayElem(light, "lightType", i, &temp, 0);
         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "lightType");
         }
     
         for (i = 0; i < drvData->lightNum; ++i) {
         .....
Z
zhouyanxu 已提交
217
         /* 类型作为下标开辟空间 */
Z
zhouyanxu 已提交
218 219
         drvData->info[temp] = (struct LightDeviceInfo *)OsalMemCalloc(sizeof(struct LightDeviceInfo));
         .....
Z
zhouyanxu 已提交
220
         /* 将Light设备信息进行填充 */
Z
zhouyanxu 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
         ret = parser->GetUint32(light, "busRNum", &drvData->info[temp]->busRNum, 0);
         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busRNum");
         ret = parser->GetUint32(light, "busGNum", &drvData->info[temp]->busGNum, 0);
         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busGNum");
         ret = parser->GetUint32(light, "busBNum", &drvData->info[temp]->busBNum, 0);
         CHECK_LIGHT_PARSER_RESULT_RETURN_VALUE(ret, "busBNum");
         .....
         return HDF_SUCCESS;
     
     }
     ```

   - 灯效果模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md)介绍。

     ```hcs
Z
zhouyanxu 已提交
236
     /* 灯数据配置模板(light_config.hcs) */
Z
zhouyanxu 已提交
237 238 239 240 241 242
     root {
         lightConfig {
             boardConfig {
                 match_attr = "hdf_light_driver";
                 lightAttr {
                     light01 {
Z
zhouyanxu 已提交
243 244 245 246 247
                         lightType = [1, 2];          // 灯类型
                         busRNum = 31;                // 红色对应的GPIO管脚
                         busGNum = 30;                // 绿色对应的GPIO管脚
                         busBNum = 29;                // 蓝色对应的GPIO管脚
                         lightBrightness = 0X80000000;// RGB: R:16-31bit、G:8-15bit、B:0-7bit
Z
zhouyanxu 已提交
248 249
                         onTime = 50;                 // 一个闪烁周期内亮灯时长(ms)
                         offTime = 50;                // 一个闪烁周期内熄灯时长(ms)
Z
zhouyanxu 已提交
250 251 252 253 254 255 256 257 258 259
                     }
                 }
             }
         }
     }
     ```

3. 完成获取灯类型,闪烁和停止接口开发,会根据闪烁模式创建和销毁定时器。

   ```c
Z
zhouyanxu 已提交
260
   /* Light驱动服务调用GetAllLightInfo获取灯类型,Enable接口启动闪烁模式,
Z
zhouyanxu 已提交
261 262 263 264
      调用Disable接口停止闪烁 */
   static int32_t GetAllLightInfo(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       .....
Z
zhouyanxu 已提交
265
       /* 获取Light类型个数 */
Z
zhouyanxu 已提交
266 267 268 269 270 271 272 273 274 275
       if (!HdfSbufWriteUint32(reply, drvData->lightNum)) {
           HDF_LOGE("%s: write sbuf failed", __func__);
           return HDF_FAILURE;
       }
       for (i = 0; i < LIGHT_TYPE_BUTT; ++i) {
           if (drvData->info[i] == NULL) {
               continue;
           }
           lightInfo.lightType = i;
           lightInfo.reserved = NULL;
Z
zhouyanxu 已提交
276
           /* 将Light设备信息填充进reply */
Z
zhouyanxu 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289
           if (!HdfSbufWriteBuffer(reply, &lightInfo, sizeof(lightInfo))) {
               HDF_LOGE("%s: write sbuf failed", __func__);
               return HDF_FAILURE;
           }
       }
   
       return HDF_SUCCESS;
   }
   
   /* 按照指定的类型和用户传入的参数使能灯 */
   static int32_t Enable(uint32_t lightType, struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       .....
Z
zhouyanxu 已提交
290
       /* 根据用户传的亮度值设置灯的颜色  RGB: R:16-31bit、G:8-15bit、B:0-7bit */
Z
zhouyanxu 已提交
291 292 293 294 295 296 297
       if ((drvData->info[lightType]->lightBrightness & LIGHT_MAKE_R_BIT) != 0) {
           drvData->info[lightType]->busNum = drvData->info[lightType]->busRNum;
       } else if ((drvData->info[lightType]->lightBrightness & LIGHT_MAKE_G_BIT) != 0) {
           drvData->info[lightType]->busNum = drvData->info[lightType]->busGNum;
       } else if ((drvData->info[lightType]->lightBrightness & LIGHT_MAKE_B_BIT) != 0) {
           drvData->info[lightType]->busNum = drvData->info[lightType]->busBNum;
       }
Z
zhouyanxu 已提交
298
       /* 常亮模式 */
Z
zhouyanxu 已提交
299 300 301 302 303 304
       if (buf->flashEffect.flashMode == LIGHT_FLASH_NONE) {
   
           if (GpioWrite(drvData->info[lightType]->busNum, GPIO_VAL_HIGH) != HDF_SUCCESS) {
               return HDF_FAILURE;
           }
       }
Z
zhouyanxu 已提交
305
       /* 闪烁模式 */
Z
zhouyanxu 已提交
306 307
       if (buf->flashEffect.flashMode == LIGHT_FLASH_TIMED) {
           drvData->info[lightType]->lightState = LIGHT_STATE_START;
Z
zhouyanxu 已提交
308
           /* 用户设置的闪烁时间小于系统支持的最短时间,采用系统配置的时间(HCS配置) */
Z
zhouyanxu 已提交
309 310 311 312
           drvData->info[lightType]->onTime = buf->flashEffect.onTime < drvData->info[lightType]->onTime ?
           drvData->info[lightType]->onTime : buf->flashEffect.onTime;
           drvData->info[lightType]->offTime = buf->flashEffect.offTime < drvData->info[lightType]->offTime ?
           drvData->info[lightType]->offTime : buf->flashEffect.offTime;
Z
zhouyanxu 已提交
313
           /* 创建定时器 */
Z
zhouyanxu 已提交
314 315 316 317 318
           if (OsalTimerCreate(&drvData->timer, drvData->info[lightType]->onTime,
               LightTimerEntry, (uintptr_t)lightType) != HDF_SUCCESS) {
           HDF_LOGE("%s: create light timer fail!", __func__);
           return HDF_FAILURE;
           }
Z
zhouyanxu 已提交
319
           /* 启动周期定时器 */
Z
zhouyanxu 已提交
320 321 322 323 324 325 326 327 328 329 330
           if (OsalTimerStartLoop(&drvData->timer) != HDF_SUCCESS) {
           HDF_LOGE("%s: start light timer fail!", __func__);
           return HDF_FAILURE;
           }
       }
       return HDF_SUCCESS;
   }
   
   /* 按照指定的类型关闭灯 */
   static int32_t Disable(uint32_t lightType, struct HdfSBuf *data, struct HdfSBuf *reply)
   {
Z
zhouyanxu 已提交
331
       /* 删除定时器 */
Z
zhouyanxu 已提交
332 333 334 335 336 337
       if (drvData->timer.realTimer != NULL) {
   
           if (OsalTimerDelete(&drvData->timer) != HDF_SUCCESS) {
               HDF_LOGE("%s: delete haptic timer fail!", __func__);
           }
       }
Z
zhouyanxu 已提交
338
       /* 对应的GPIO下电 */
Z
zhouyanxu 已提交
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
       if (GpioWrite(drvData->info[lightType]->busRNum, GPIO_VAL_LOW) != HDF_SUCCESS){
           HDF_LOGE("%s: gpio write failed", __func__);
           return HDF_FAILURE;
       }
   
       return HDF_SUCCESS;
   }
   ```

### 调测验证

驱动开发完成后,在灯单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。

```c++
/* 用例执行前,初始化灯接口实例 */
void HdfLightTest::SetUpTestCase()
{
    g_lightDev = NewLightInterfaceInstance();
    if (g_lightDev == nullptr) {
        printf("test light get Module instance failed\n\r");
    }
    int32_t ret = g_lightDev->GetLightInfo(&g_lightInfo, &g_count);
    if (ret == -1) {
        printf("get light informations failed\n\r");
    }
}

/* 用例执行后,释放用例资源 */
void HdfLightTest::TearDownTestCase()
{
    if(g_lightDev != nullptr){
        FreeLightInterfaceInstance();
        g_lightDev = nullptr;
    }
}

/* 测试灯获取类型 */
HWTEST_F(HdfLightTest, GetLightList001, TestSize.Level1)
{
    struct LightInfo *info = nullptr;

    if (g_lightInfo == nullptr) {
        EXPECT_NE(nullptr, g_lightInfo);
        return;
    }

    printf("get light list num[%d]\n\r", g_count);
    info = g_lightInfo;

    for (int i = 0; i < g_count; ++i) {
        printf("get lightId[%d]\n\r", info->lightType);
        EXPECT_GE(info->lightType, g_minLightType);
        EXPECT_LE(info->lightType, g_maxLightType);
        info++;
    }
}

/* 测试灯常亮模式 */
HWTEST_F(HdfLightTest, EnableLight001, TestSize.Level1)
{
    int32_t i;
    int32_t ret;
    struct LightEffect effect;
    effect->lightBrightness = 0x80000000;
    effect->flashEffect.flashMode = LIGHT_FLASH_NONE;
    effect->flashEffect.onTime = 0;
    effect->flashEffect.offTime = 0;

    for (i = 0; i < g_count; ++i) {

        ret = g_lightDev->TurnOnLight(g_lightInfo[i]->lightType, effect);
        EXPECT_EQ(0, ret);

        OsalSleep(LIGHT_WAIT_TIME);

        ret = g_lightDev->TurnOffLight(type);
        EXPECT_EQ(0, ret);
    }
}

/* 测试灯闪烁模式 */
HWTEST_F(HdfLightTest, EnableLight002, TestSize.Level1)
{
    int32_t i;
    int32_t ret;
    struct LightEffect effect;
    effect->lightBrightness = 0x80000000;
    effect->flashEffect.flashMode = LIGHT_FLASH_TIMED;
    effect->flashEffect.onTime = g_onTime;
    effect->flashEffect.offTime = g_offTime;

    for (i = 0; i < g_count; ++i) {

        ret = g_lightDev->TurnOnLight(g_lightInfo[i]->lightType, effect);
        EXPECT_EQ(0, ret);

        OsalSleep(LIGHT_WAIT_TIME);

        ret = g_lightDev->TurnOffLight(type);
        EXPECT_EQ(0, ret);
    }
}
```