1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "sensor_als_driver.h"
10 #include <securec.h>
11 #include "als_bh1745.h"
12 #include "osal_math.h"
13 #include "osal_mem.h"
14 #include "sensor_config_controller.h"
15 #include "sensor_device_manager.h"
16 #include "sensor_platform_if.h"
17
18 #define HDF_LOG_TAG hdf_sensor_als_driver
19
20 #define HDF_ALS_WORK_QUEUE_NAME "hdf_als_work_queue"
21
22 static struct AlsDrvData *g_alsDrvData = NULL;
23
AlsGetDrvData(void)24 static struct AlsDrvData *AlsGetDrvData(void)
25 {
26 return g_alsDrvData;
27 }
28
29 static struct SensorRegCfgGroupNode *g_regCfgGroup[SENSOR_GROUP_MAX] = { NULL };
30 static struct SensorRegCfgGroupNode *g_extendAlsRegCfgGroup[EXTENDED_ALS_GROUP_MAX] = { NULL };
31 static char *g_extendedAlsGroupName[EXTENDED_ALS_GROUP_MAX] = {
32 "time",
33 "gain",
34 };
35
GetTimeByRegValue(uint8_t regValue,struct TimeRegAddrValueMap * map,int32_t itemNum)36 int32_t GetTimeByRegValue(uint8_t regValue, struct TimeRegAddrValueMap *map, int32_t itemNum)
37 {
38 int32_t i;
39
40 CHECK_NULL_PTR_RETURN_VALUE(map, INVALID_VALUE);
41
42 for (i = 0; i < itemNum; i++) {
43 if (regValue == map[i].timeRegKey) {
44 return map[i].timeValue;
45 }
46 }
47
48 return INVALID_VALUE;
49 }
50
GetRegGroupIndexByTime(uint32_t timeValue,struct TimeRegAddrValueMap * map,int32_t itemNum)51 int32_t GetRegGroupIndexByTime(uint32_t timeValue, struct TimeRegAddrValueMap *map, int32_t itemNum)
52 {
53 int32_t i;
54
55 CHECK_NULL_PTR_RETURN_VALUE(map, INVALID_VALUE);
56
57 for (i = 0; i < itemNum; i++) {
58 if (timeValue == map[i].timeValue) {
59 return i;
60 }
61 }
62
63 return INVALID_VALUE;
64 }
65
GetGainByRegValue(uint8_t regValue,struct GainRegAddrValueMap * map,int32_t itemNum)66 int32_t GetGainByRegValue(uint8_t regValue, struct GainRegAddrValueMap *map, int32_t itemNum)
67 {
68 int32_t i;
69
70 CHECK_NULL_PTR_RETURN_VALUE(map, INVALID_VALUE);
71
72 for (i = 0; i < itemNum; i++) {
73 if (regValue == map[i].gainRegKey) {
74 return map[i].gainValue;
75 }
76 }
77
78 return INVALID_VALUE;
79 }
80
GetExtendedAlsRegGroupNameIndex(const char * name)81 static int32_t GetExtendedAlsRegGroupNameIndex(const char *name)
82 {
83 int32_t index;
84
85 CHECK_NULL_PTR_RETURN_VALUE(name, EXTENDED_ALS_GROUP_MAX);
86
87 for (index = 0; index < EXTENDED_ALS_GROUP_MAX; ++index) {
88 if ((g_extendedAlsGroupName[index] != NULL) && (strcmp(name, g_extendedAlsGroupName[index]) == 0)) {
89 break;
90 }
91 }
92
93 return index;
94 }
95
ReleaseExtendedAlsRegConfig(struct SensorCfgData * config)96 void ReleaseExtendedAlsRegConfig(struct SensorCfgData *config)
97 {
98 int32_t index;
99
100 CHECK_NULL_PTR_RETURN(config);
101 CHECK_NULL_PTR_RETURN(config->extendedRegCfgGroup);
102
103 for (index = 0; index < EXTENDED_ALS_GROUP_MAX; ++index) {
104 if (config->extendedRegCfgGroup[index] != NULL) {
105 if (config->extendedRegCfgGroup[index]->regCfgItem != NULL) {
106 OsalMemFree(config->extendedRegCfgGroup[index]->regCfgItem);
107 config->extendedRegCfgGroup[index]->regCfgItem = NULL;
108 }
109
110 OsalMemFree(config->extendedRegCfgGroup[index]);
111 config->extendedRegCfgGroup[index] = NULL;
112 }
113 }
114 }
115
ParseExtendedAlsRegConfig(struct SensorCfgData * config)116 int32_t ParseExtendedAlsRegConfig(struct SensorCfgData *config)
117 {
118 int32_t index;
119 struct DeviceResourceIface *parser = NULL;
120 const struct DeviceResourceNode *extendedRegCfgNode = NULL;
121 const struct DeviceResourceAttr *extendedRegAttr = NULL;
122
123 CHECK_NULL_PTR_RETURN_VALUE(config->root, HDF_ERR_INVALID_PARAM);
124 parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
125 CHECK_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
126
127 extendedRegCfgNode = parser->GetChildNode(config->root, "extendAlsRegConfig");
128 CHECK_NULL_PTR_RETURN_VALUE(extendedRegCfgNode, HDF_ERR_INVALID_PARAM);
129
130 DEV_RES_NODE_FOR_EACH_ATTR(extendedRegCfgNode, extendedRegAttr) {
131 if (extendedRegAttr == NULL || extendedRegAttr->name == NULL) {
132 HDF_LOGE("%s:sensor reg node attr is null", __func__);
133 break;
134 }
135
136 index = GetExtendedAlsRegGroupNameIndex(extendedRegAttr->name);
137 if (index >= EXTENDED_ALS_GROUP_MAX) {
138 HDF_LOGE("%s: get sensor register group index failed", __func__);
139 goto ERROR;
140 }
141
142 if (ParseSensorRegGroup(parser, extendedRegCfgNode, extendedRegAttr->name,
143 &config->extendedRegCfgGroup[index]) != HDF_SUCCESS) {
144 HDF_LOGE("%s: parse sensor register group failed", __func__);
145 goto ERROR;
146 }
147 }
148
149 return HDF_SUCCESS;
150
151 ERROR:
152 ReleaseExtendedAlsRegConfig(config);
153 HDF_LOGE("%s: parse sensor extend register config failed", __func__);
154
155 return HDF_FAILURE;
156 }
157
AlsRegisterChipOps(const struct AlsOpsCall * ops)158 int32_t AlsRegisterChipOps(const struct AlsOpsCall *ops)
159 {
160 struct AlsDrvData *drvData = AlsGetDrvData();
161
162 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
163 CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM);
164
165 drvData->ops.Init = ops->Init;
166 drvData->ops.ReadData = ops->ReadData;
167 return HDF_SUCCESS;
168 }
169
AlsDataWorkEntry(void * arg)170 static void AlsDataWorkEntry(void *arg)
171 {
172 struct AlsDrvData *drvData = NULL;
173
174 drvData = (struct AlsDrvData *)arg;
175 CHECK_NULL_PTR_RETURN(drvData);
176
177 if (drvData->ops.ReadData == NULL) {
178 HDF_LOGI("%s: Als ReadData function NULl", __func__);
179 return;
180 }
181 if (drvData->ops.ReadData(drvData->alsCfg) != HDF_SUCCESS) {
182 HDF_LOGE("%s: Als read data failed", __func__);
183 }
184 }
185
AlsTimerEntry(uintptr_t arg)186 static void AlsTimerEntry(uintptr_t arg)
187 {
188 int64_t interval;
189 int32_t ret;
190 struct AlsDrvData *drvData = (struct AlsDrvData *)arg;
191 CHECK_NULL_PTR_RETURN(drvData);
192
193 if (!HdfAddWork(&drvData->alsWorkQueue, &drvData->alsWork)) {
194 HDF_LOGE("%s: Als add work queue failed", __func__);
195 }
196
197 interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT));
198 interval = (interval < SENSOR_TIMER_MIN_TIME) ? SENSOR_TIMER_MIN_TIME : interval;
199 ret = OsalTimerSetTimeout(&drvData->alsTimer, interval);
200 if (ret != HDF_SUCCESS) {
201 HDF_LOGE("%s: Als modify time failed", __func__);
202 }
203 }
204
InitAlsData(struct AlsDrvData * drvData)205 static int32_t InitAlsData(struct AlsDrvData *drvData)
206 {
207 if (HdfWorkQueueInit(&drvData->alsWorkQueue, HDF_ALS_WORK_QUEUE_NAME) != HDF_SUCCESS) {
208 HDF_LOGE("%s: Als init work queue failed", __func__);
209 return HDF_FAILURE;
210 }
211
212 if (HdfWorkInit(&drvData->alsWork, AlsDataWorkEntry, drvData) != HDF_SUCCESS) {
213 HDF_LOGE("%s: Als create thread failed", __func__);
214 return HDF_FAILURE;
215 }
216
217 drvData->interval = SENSOR_TIMER_MIN_TIME;
218 drvData->enable = false;
219 drvData->detectFlag = false;
220
221 return HDF_SUCCESS;
222 }
223
SetAlsEnable(void)224 static int32_t SetAlsEnable(void)
225 {
226 int32_t ret;
227 struct AlsDrvData *drvData = AlsGetDrvData();
228
229 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
230 CHECK_NULL_PTR_RETURN_VALUE(drvData->alsCfg, HDF_ERR_INVALID_PARAM);
231
232 if (drvData->enable) {
233 HDF_LOGE("%s: Als sensor is enabled", __func__);
234 return HDF_SUCCESS;
235 }
236
237 ret = SetSensorRegCfgArray(&drvData->alsCfg->busCfg, drvData->alsCfg->regCfgGroup[SENSOR_ENABLE_GROUP]);
238 if (ret != HDF_SUCCESS) {
239 HDF_LOGE("%s: Als sensor enable config failed", __func__);
240 return ret;
241 }
242
243 ret = OsalTimerCreate(&drvData->alsTimer, SENSOR_TIMER_MIN_TIME, AlsTimerEntry, (uintptr_t)drvData);
244 if (ret != HDF_SUCCESS) {
245 HDF_LOGE("%s: Als create timer failed[%d]", __func__, ret);
246 return ret;
247 }
248
249 ret = OsalTimerStartLoop(&drvData->alsTimer);
250 if (ret != HDF_SUCCESS) {
251 HDF_LOGE("%s: Als start timer failed[%d]", __func__, ret);
252 return ret;
253 }
254 drvData->enable = true;
255
256 return HDF_SUCCESS;
257 }
258
SetAlsDisable(void)259 static int32_t SetAlsDisable(void)
260 {
261 int32_t ret;
262 struct AlsDrvData *drvData = AlsGetDrvData();
263
264 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
265 CHECK_NULL_PTR_RETURN_VALUE(drvData->alsCfg, HDF_ERR_INVALID_PARAM);
266
267 if (!drvData->enable) {
268 HDF_LOGE("%s: Als sensor had disable", __func__);
269 return HDF_SUCCESS;
270 }
271
272 ret = SetSensorRegCfgArray(&drvData->alsCfg->busCfg, drvData->alsCfg->regCfgGroup[SENSOR_DISABLE_GROUP]);
273 if (ret != HDF_SUCCESS) {
274 HDF_LOGE("%s: Als sensor disable config failed", __func__);
275 return ret;
276 }
277
278 ret = OsalTimerDelete(&drvData->alsTimer);
279 if (ret != HDF_SUCCESS) {
280 HDF_LOGE("%s: Als delete timer failed", __func__);
281 return ret;
282 }
283 drvData->enable = false;
284
285 return HDF_SUCCESS;
286 }
287
SetAlsBatch(int64_t samplingInterval,int64_t interval)288 static int32_t SetAlsBatch(int64_t samplingInterval, int64_t interval)
289 {
290 (void)interval;
291
292 struct AlsDrvData *drvData = NULL;
293
294 drvData = AlsGetDrvData();
295 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
296
297 drvData->interval = samplingInterval;
298
299 return HDF_SUCCESS;
300 }
301
SetAlsMode(int32_t mode)302 static int32_t SetAlsMode(int32_t mode)
303 {
304 if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
305 HDF_LOGE("%s: The current mode is not supported", __func__);
306 return HDF_FAILURE;
307 }
308
309 return HDF_SUCCESS;
310 }
311
SetAlsOption(uint32_t option)312 static int32_t SetAlsOption(uint32_t option)
313 {
314 (void)option;
315 return HDF_SUCCESS;
316 }
317
DispatchAls(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)318 static int32_t DispatchAls(struct HdfDeviceIoClient *client,
319 int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
320 {
321 (void)client;
322 (void)cmd;
323 (void)data;
324 (void)reply;
325
326 return HDF_SUCCESS;
327 }
328
AlsBindDriver(struct HdfDeviceObject * device)329 int32_t AlsBindDriver(struct HdfDeviceObject *device)
330 {
331 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
332
333 struct AlsDrvData *drvData = (struct AlsDrvData *)OsalMemCalloc(sizeof(*drvData));
334 if (drvData == NULL) {
335 HDF_LOGE("%s: Malloc als drv data fail!", __func__);
336 return HDF_ERR_MALLOC_FAIL;
337 }
338
339 drvData->ioService.Dispatch = DispatchAls;
340 drvData->device = device;
341 device->service = &drvData->ioService;
342 g_alsDrvData = drvData;
343 return HDF_SUCCESS;
344 }
345
InitAlsOps(struct SensorCfgData * config,struct SensorDeviceInfo * deviceInfo)346 static int32_t InitAlsOps(struct SensorCfgData *config, struct SensorDeviceInfo *deviceInfo)
347 {
348 CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
349
350 deviceInfo->ops.Enable = SetAlsEnable;
351 deviceInfo->ops.Disable = SetAlsDisable;
352 deviceInfo->ops.SetBatch = SetAlsBatch;
353 deviceInfo->ops.SetMode = SetAlsMode;
354 deviceInfo->ops.SetOption = SetAlsOption;
355
356 if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo),
357 &config->sensorInfo, sizeof(config->sensorInfo)) != EOK) {
358 HDF_LOGE("%s: Copy sensor info failed", __func__);
359 return HDF_FAILURE;
360 }
361
362 return HDF_SUCCESS;
363 }
364
InitAlsAfterDetected(struct SensorCfgData * config)365 static int32_t InitAlsAfterDetected(struct SensorCfgData *config)
366 {
367 struct SensorDeviceInfo deviceInfo;
368 CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
369
370 if (InitAlsOps(config, &deviceInfo) != HDF_SUCCESS) {
371 HDF_LOGE("%s: Init als ops failed", __func__);
372 return HDF_FAILURE;
373 }
374
375 if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
376 HDF_LOGE("%s: Add als device failed", __func__);
377 return HDF_FAILURE;
378 }
379
380 if (ParseSensorRegConfig(config) != HDF_SUCCESS) {
381 HDF_LOGE("%s: Parse sensor register failed", __func__);
382 goto SENSOR_REG_CONFIG_EXIT;
383 }
384
385 if (ParseExtendedAlsRegConfig(config) != HDF_SUCCESS) {
386 HDF_LOGE("%s: Parse sensor extendedRegCfgGroup register failed", __func__);
387 goto EXTENDED_ALS_REG_CONFIG_EXIT;
388 }
389
390 return HDF_SUCCESS;
391
392 EXTENDED_ALS_REG_CONFIG_EXIT:
393 ReleaseSensorAllRegConfig(config);
394 SENSOR_REG_CONFIG_EXIT:
395 (void)DeleteSensorDevice(&config->sensorInfo);
396
397 return HDF_FAILURE;
398 }
399
AlsCreateCfgData(const struct DeviceResourceNode * node)400 struct SensorCfgData *AlsCreateCfgData(const struct DeviceResourceNode *node)
401 {
402 struct AlsDrvData *drvData = AlsGetDrvData();
403
404 if (drvData == NULL || node == NULL) {
405 HDF_LOGE("%s: Als node pointer NULL", __func__);
406 return NULL;
407 }
408
409 if (drvData->detectFlag) {
410 HDF_LOGE("%s: Als sensor have detected", __func__);
411 return NULL;
412 }
413
414 if (drvData->alsCfg == NULL) {
415 HDF_LOGE("%s: Als alsCfg pointer NULL", __func__);
416 return NULL;
417 }
418
419 if (GetSensorBaseConfigData(node, drvData->alsCfg) != HDF_SUCCESS) {
420 HDF_LOGE("%s: Get sensor base config failed", __func__);
421 goto BASE_CONFIG_EXIT;
422 }
423
424 if (DetectSensorDevice(drvData->alsCfg) != HDF_SUCCESS) {
425 HDF_LOGI("%s: Als sensor detect device no exist", __func__);
426 drvData->detectFlag = false;
427 goto BASE_CONFIG_EXIT;
428 }
429
430 drvData->detectFlag = true;
431 if (InitAlsAfterDetected(drvData->alsCfg) != HDF_SUCCESS) {
432 HDF_LOGE("%s: Als sensor detect device no exist", __func__);
433 goto INIT_EXIT;
434 }
435
436 return drvData->alsCfg;
437
438 INIT_EXIT:
439 (void)ReleaseSensorBusHandle(&drvData->alsCfg->busCfg);
440 BASE_CONFIG_EXIT:
441 drvData->alsCfg->root = NULL;
442 (void)memset_s(&drvData->alsCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
443 (void)memset_s(&drvData->alsCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
444 (void)memset_s(&drvData->alsCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
445 return drvData->alsCfg;
446 }
447
AlsReleaseCfgData(struct SensorCfgData * alsCfg)448 void AlsReleaseCfgData(struct SensorCfgData *alsCfg)
449 {
450 CHECK_NULL_PTR_RETURN(alsCfg);
451
452 (void)DeleteSensorDevice(&alsCfg->sensorInfo);
453 ReleaseSensorAllRegConfig(alsCfg);
454 ReleaseExtendedAlsRegConfig(alsCfg);
455 (void)ReleaseSensorBusHandle(&alsCfg->busCfg);
456
457 alsCfg->root = NULL;
458 (void)memset_s(&alsCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
459 (void)memset_s(&alsCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
460 (void)memset_s(&alsCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
461 }
462
AlsInitDriver(struct HdfDeviceObject * device)463 int32_t AlsInitDriver(struct HdfDeviceObject *device)
464 {
465 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
466 struct AlsDrvData *drvData = (struct AlsDrvData *)device->service;
467 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
468
469 if (InitAlsData(drvData) != HDF_SUCCESS) {
470 HDF_LOGE("%s: Init als config failed", __func__);
471 return HDF_FAILURE;
472 }
473
474 drvData->alsCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*drvData->alsCfg));
475 if (drvData->alsCfg == NULL) {
476 HDF_LOGE("%s: Malloc als config data failed", __func__);
477 return HDF_FAILURE;
478 }
479
480 drvData->alsCfg->regCfgGroup = &g_regCfgGroup[0];
481 drvData->alsCfg->extendedRegCfgGroup = &g_extendAlsRegCfgGroup[0];
482
483 return HDF_SUCCESS;
484 }
485
AlsReleaseDriver(struct HdfDeviceObject * device)486 void AlsReleaseDriver(struct HdfDeviceObject *device)
487 {
488 CHECK_NULL_PTR_RETURN(device);
489
490 struct AlsDrvData *drvData = (struct AlsDrvData *)device->service;
491 CHECK_NULL_PTR_RETURN(drvData);
492
493 if (drvData->detectFlag && drvData->alsCfg != NULL) {
494 AlsReleaseCfgData(drvData->alsCfg);
495 }
496
497 OsalMemFree(drvData->alsCfg);
498 drvData->alsCfg = NULL;
499
500 HdfWorkDestroy(&drvData->alsWork);
501 HdfWorkQueueDestroy(&drvData->alsWorkQueue);
502 OsalMemFree(drvData);
503 }
504
505 struct HdfDriverEntry g_sensorAlsDevEntry = {
506 .moduleVersion = 1,
507 .moduleName = "HDF_SENSOR_ALS",
508 .Bind = AlsBindDriver,
509 .Init = AlsInitDriver,
510 .Release = AlsReleaseDriver,
511 };
512
513 HDF_INIT(g_sensorAlsDevEntry);
514