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_hall_driver.h"
10 #include <securec.h>
11 #include "gpio_if.h"
12 #include "hdf_base.h"
13 #include "hdf_device_desc.h"
14 #include "osal_irq.h"
15 #include "osal_mem.h"
16 #include "osal_time.h"
17 #include "sensor_config_controller.h"
18 #include "sensor_device_manager.h"
19 #include "sensor_platform_if.h"
20
21 #define HDF_LOG_TAG khdf_sensor_hall_driver
22 #define HDF_HALL_WORK_QUEUE_NAME "hdf_hall_work_queue"
23
24 static struct HallDrvData *g_hallDrvData = NULL;
25
HallGetDrvData(void)26 static struct HallDrvData *HallGetDrvData(void)
27 {
28 return g_hallDrvData;
29 }
30
HallRegisterChipOps(const struct HallOpsCall * ops)31 int32_t HallRegisterChipOps(const struct HallOpsCall *ops)
32 {
33 struct HallDrvData *drvData = HallGetDrvData();
34
35 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
36 CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM);
37
38 drvData->ops.Init = ops->Init;
39 drvData->ops.ReadData = ops->ReadData;
40 return HDF_SUCCESS;
41 }
42
ReadGpioData(void)43 void ReadGpioData(void)
44 {
45 int32_t ret;
46 uint16_t tmp;
47 OsalTimespec time;
48 struct SensorReportEvent event;
49
50 struct HallDrvData *drvData = HallGetDrvData();
51 CHECK_NULL_PTR_RETURN(drvData);
52
53 (void)memset_s(&event, sizeof(event), 0, sizeof(event));
54 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
55 if (OsalGetTime(&time) != HDF_SUCCESS) {
56 HDF_LOGE("%s: Get time failed", __func__);
57 return;
58 }
59
60 tmp = drvData->status;
61 event.timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec *
62 SENSOR_CONVERT_UNIT; /* unit nanosecond */
63 event.sensorId = SENSOR_TAG_HALL;
64 event.version = 0;
65 event.option = 0;
66 event.mode = SENSOR_WORK_MODE_ON_CHANGE;
67 event.dataLen = sizeof(tmp);
68 event.data = (uint8_t *)&tmp;
69 ret = ReportSensorEvent(&event);
70 if (ret != HDF_SUCCESS) {
71 HDF_LOGE("%s: AK8789 report data failed", __func__);
72 }
73 }
74
HallDataWorkEntry(void * arg)75 static void HallDataWorkEntry(void *arg)
76 {
77 struct HallDrvData *drvData = NULL;
78
79 drvData = (struct HallDrvData *)arg;
80 CHECK_NULL_PTR_RETURN(drvData);
81
82 if (drvData->ops.ReadData == NULL) {
83 ReadGpioData();
84 HDF_LOGI("%s: Hall ReadData function NULL", __func__);
85 } else if (drvData->ops.ReadData(drvData->hallCfg) != HDF_SUCCESS) {
86 HDF_LOGE("%s: Hall read data failed", __func__);
87 }
88 }
89
ParserHallDelayedConfigData(const struct DeviceResourceNode * node,struct HallDrvData * drvData)90 static int32_t ParserHallDelayedConfigData(const struct DeviceResourceNode *node, struct HallDrvData *drvData)
91 {
92 int32_t ret;
93 struct DeviceResourceIface *parser = NULL;
94
95 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
96 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
97
98 parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
99 CHECK_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
100
101 CHECK_NULL_PTR_RETURN_VALUE(parser->GetChildNode, HDF_ERR_INVALID_PARAM);
102
103 const struct DeviceResourceNode *delayedNode = parser->GetChildNode(node, "hallDelayedConfig");
104 CHECK_NULL_PTR_RETURN_VALUE(delayedNode, HDF_ERR_INVALID_PARAM);
105
106 ret = parser->GetUint32(delayedNode, "delayedTime", (uint32_t *)&drvData->delayTime, 0);
107 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "delayedTime");
108
109 return HDF_SUCCESS;
110 }
111
HallNorthPolarityIrqFunc(uint16_t gpio,void * data)112 static int32_t HallNorthPolarityIrqFunc(uint16_t gpio, void *data)
113 {
114 (void)gpio;
115 int32_t ret;
116 uint16_t valRead;
117
118 struct HallDrvData *drvData = (struct HallDrvData *)data;
119 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
120
121 ret = GpioRead(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1], (uint16_t *)&valRead);
122 if (ret != 0) {
123 HDF_LOGE("%s: Read hall gpio value failed", __func__);
124 }
125 if (valRead == GPIO_VAL_LOW) {
126 drvData->status = 1;
127 } else if (valRead == GPIO_VAL_HIGH) {
128 drvData->status = 0;
129 }
130
131 if (!HdfAddDelayedWork(&drvData->hallWorkQueue, &drvData->hallWork, drvData->delayTime)) {
132 HDF_LOGE("%s: Hall north add delay work queue failed", __func__);
133 }
134
135 return HDF_SUCCESS;
136 }
137
HallSouthPolarityIrqFunc(uint16_t gpio,void * data)138 static int32_t HallSouthPolarityIrqFunc(uint16_t gpio, void *data)
139 {
140 (void)gpio;
141 int32_t ret;
142 uint16_t valRead;
143
144 struct HallDrvData *drvData = (struct HallDrvData *)data;
145 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
146
147 ret = GpioRead(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2], (uint16_t *)&valRead);
148 if (ret != 0) {
149 HDF_LOGE("%s: Read hall gpio value failed", __func__);
150 }
151 if (valRead == GPIO_VAL_LOW) {
152 drvData->status = 1;
153 } else if (valRead == GPIO_VAL_HIGH) {
154 drvData->status = 0;
155 }
156
157 if (!HdfAddDelayedWork(&drvData->hallWorkQueue, &drvData->hallWork, drvData->delayTime)) {
158 HDF_LOGE("%s: Hall south add delay work queue failed", __func__);
159 }
160
161 return HDF_SUCCESS;
162 }
163
InitHallData(struct HallDrvData * drvData)164 static int32_t InitHallData(struct HallDrvData *drvData)
165 {
166 if (HdfWorkQueueInit(&drvData->hallWorkQueue, HDF_HALL_WORK_QUEUE_NAME) != HDF_SUCCESS) {
167 HDF_LOGE("%s: Hall init work queue failed", __func__);
168 return HDF_FAILURE;
169 }
170
171 if (HdfDelayedWorkInit(&drvData->hallWork, HallDataWorkEntry, drvData) != HDF_SUCCESS) {
172 HDF_LOGE("%s: Hall create thread failed", __func__);
173 return HDF_FAILURE;
174 }
175
176 drvData->interval = SENSOR_TIMER_MIN_TIME;
177 drvData->enable = false;
178 drvData->detectFlag = false;
179
180 return HDF_SUCCESS;
181 }
182
SetHallEnable(void)183 static int32_t SetHallEnable(void)
184 {
185 int32_t ret;
186 uint16_t mode;
187 struct HallDrvData *drvData = HallGetDrvData();
188 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
189
190 if (drvData->enable) {
191 HDF_LOGE("%s: Hall sensor is enabled", __func__);
192 return HDF_SUCCESS;
193 }
194
195 mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING;
196 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1] >= 0) {
197 ret = GpioSetIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1], mode,
198 HallNorthPolarityIrqFunc, drvData);
199 if (ret != 0) {
200 HDF_LOGE("Gpio set north irq failed: %d", ret);
201 }
202 ret = GpioEnableIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1]);
203 if (ret != 0) {
204 HDF_LOGE("Gpio enable north irq failed: %d", ret);
205 }
206 }
207
208 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2] >= 0) {
209 ret = GpioSetIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2], mode,
210 HallSouthPolarityIrqFunc, drvData);
211 if (ret != 0) {
212 HDF_LOGE("%s: Gpio set south irq failed", __func__);
213 }
214 ret = GpioEnableIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2]);
215 if (ret != 0) {
216 HDF_LOGE("%s: Gpio enable south irq failed", __func__);
217 }
218 }
219
220 drvData->enable = true;
221 return HDF_SUCCESS;
222 }
223
SetHallDisable(void)224 static int32_t SetHallDisable(void)
225 {
226 int32_t ret;
227 struct HallDrvData *drvData = HallGetDrvData();
228 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
229
230 if (!drvData->enable) {
231 HDF_LOGE("%s: Hall sensor had disable", __func__);
232 return HDF_SUCCESS;
233 }
234
235 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1] >= 0) {
236 ret = GpioUnsetIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1], drvData);
237 if (ret != 0) {
238 HDF_LOGE("%s: Gpio unset north irq failed", __func__);
239 }
240
241 ret = GpioDisableIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1]);
242 if (ret != 0) {
243 HDF_LOGE("%s: Gpio disable north irq failed", __func__);
244 }
245 }
246
247 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2] >= 0) {
248 ret = GpioUnsetIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2], drvData);
249 if (ret != 0) {
250 HDF_LOGE("%s: Gpio unset south irq failed", __func__);
251 }
252
253 ret = GpioDisableIrq(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2]);
254 if (ret != 0) {
255 HDF_LOGE("%s: Gpio disable south irq failed", __func__);
256 }
257 }
258 drvData->enable = false;
259
260 return HDF_SUCCESS;
261 }
262
SetHallBatch(int64_t samplingInterval,int64_t interval)263 static int32_t SetHallBatch(int64_t samplingInterval, int64_t interval)
264 {
265 (void)samplingInterval;
266 (void)interval;
267
268 return HDF_SUCCESS;
269 }
270
SetHallMode(int32_t mode)271 static int32_t SetHallMode(int32_t mode)
272 {
273 if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
274 HDF_LOGE("%s: The current mode is not supported", __func__);
275 return HDF_FAILURE;
276 }
277
278 return HDF_SUCCESS;
279 }
280
SetHallOption(uint32_t option)281 static int32_t SetHallOption(uint32_t option)
282 {
283 (void)option;
284 return HDF_SUCCESS;
285 }
286
DispatchHall(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)287 static int32_t DispatchHall(struct HdfDeviceIoClient *client,
288 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
289 {
290 (void)client;
291 (void)cmd;
292 (void)data;
293 (void)reply;
294
295 return HDF_SUCCESS;
296 }
297
HallBindDriver(struct HdfDeviceObject * device)298 int32_t HallBindDriver(struct HdfDeviceObject *device)
299 {
300 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
301
302 struct HallDrvData *drvData = (struct HallDrvData *)OsalMemCalloc(sizeof(*drvData));
303 if (drvData == NULL) {
304 HDF_LOGE("%s: Malloc hall drv data fail!", __func__);
305 return HDF_ERR_MALLOC_FAIL;
306 }
307
308 drvData->ioService.Dispatch = DispatchHall;
309 drvData->device = device;
310 device->service = &drvData->ioService;
311 g_hallDrvData = drvData;
312 return HDF_SUCCESS;
313 }
314
InitHallOps(struct SensorCfgData * config,struct SensorDeviceInfo * deviceInfo)315 static int32_t InitHallOps(struct SensorCfgData *config, struct SensorDeviceInfo *deviceInfo)
316 {
317 CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
318
319 deviceInfo->ops.Enable = SetHallEnable;
320 deviceInfo->ops.Disable = SetHallDisable;
321 deviceInfo->ops.SetBatch = SetHallBatch;
322 deviceInfo->ops.SetMode = SetHallMode;
323 deviceInfo->ops.SetOption = SetHallOption;
324
325 if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo),
326 &config->sensorInfo, sizeof(config->sensorInfo)) != EOK) {
327 HDF_LOGE("%s: Copy sensor info failed", __func__);
328 return HDF_FAILURE;
329 }
330
331 return HDF_SUCCESS;
332 }
333
InitHallAfterDetected(const struct DeviceResourceNode * node,struct HallDrvData * drvData)334 static int32_t InitHallAfterDetected(const struct DeviceResourceNode *node, struct HallDrvData *drvData)
335 {
336 struct SensorDeviceInfo deviceInfo;
337 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
338 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
339
340 if (InitHallOps(drvData->hallCfg, &deviceInfo) != HDF_SUCCESS) {
341 HDF_LOGE("%s: Init hall ops failed", __func__);
342 return HDF_FAILURE;
343 }
344
345 if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
346 HDF_LOGE("%s: Add hall device failed", __func__);
347 return HDF_FAILURE;
348 }
349
350 if (ParserHallDelayedConfigData(node, drvData) != HDF_SUCCESS) {
351 HDF_LOGE("%s: get hall delayed config failed", __func__);
352 (void)DeleteSensorDevice(&drvData->hallCfg->sensorInfo);
353 return HDF_FAILURE;
354 }
355
356 return HDF_SUCCESS;
357 }
358
SetHallGpioPin(struct HallDrvData * drvData)359 static int32_t SetHallGpioPin(struct HallDrvData *drvData)
360 {
361 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1] >= 0) {
362 int ret = GpioSetDir(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM1], GPIO_DIR_IN);
363 if (ret != 0) {
364 HDF_LOGE("%s:%d Set north gpio dir failed", __func__, __LINE__);
365 return HDF_FAILURE;
366 }
367 }
368
369 if (drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2] >= 0) {
370 int ret = GpioSetDir(drvData->hallCfg->busCfg.GpioNum[SENSOR_GPIO_NUM2], GPIO_DIR_IN);
371 if (ret != 0) {
372 HDF_LOGE("%s:%d Set south gpio dir failed", __func__, __LINE__);
373 return HDF_FAILURE;
374 }
375 }
376
377 return HDF_SUCCESS;
378 }
379
HallCreateCfgData(const struct DeviceResourceNode * node)380 struct SensorCfgData *HallCreateCfgData(const struct DeviceResourceNode *node)
381 {
382 struct HallDrvData *drvData = HallGetDrvData();
383
384 if (drvData == NULL || node == NULL) {
385 HDF_LOGE("%s: Hall node pointer NULL", __func__);
386 return NULL;
387 }
388
389 if (drvData->detectFlag) {
390 HDF_LOGE("%s: Hall sensor have detected", __func__);
391 return NULL;
392 }
393
394 if (drvData->hallCfg == NULL) {
395 HDF_LOGE("%s: Hall hallCfg pointer NULL", __func__);
396 return NULL;
397 }
398
399 if (GetSensorBaseConfigData(node, drvData->hallCfg) != HDF_SUCCESS) {
400 HDF_LOGE("%s: Get sensor base config failed", __func__);
401 goto BASE_CONFIG_EXIT;
402 }
403
404 if (SetHallGpioPin(drvData) != HDF_SUCCESS) {
405 HDF_LOGE("%s: set hall gpio pin failed", __func__);
406 goto BASE_CONFIG_EXIT;
407 }
408
409 if (DetectSensorDevice(drvData->hallCfg) != HDF_SUCCESS) {
410 HDF_LOGI("%s: Hall sensor detect device no exist", __func__);
411 drvData->detectFlag = false;
412 goto BASE_CONFIG_EXIT;
413 }
414
415 drvData->detectFlag = true;
416 if (InitHallAfterDetected(node, drvData) != HDF_SUCCESS) {
417 HDF_LOGE("%s: Hall sensor detect device no exist", __func__);
418 goto BASE_CONFIG_EXIT;
419 }
420
421 return drvData->hallCfg;
422
423 BASE_CONFIG_EXIT:
424 drvData->hallCfg->root = NULL;
425 (void)memset_s(&drvData->hallCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
426 (void)memset_s(&drvData->hallCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
427 return NULL;
428 }
429
HallReleaseCfgData(struct SensorCfgData * hallCfg)430 void HallReleaseCfgData(struct SensorCfgData *hallCfg)
431 {
432 CHECK_NULL_PTR_RETURN(hallCfg);
433
434 (void)DeleteSensorDevice(&hallCfg->sensorInfo);
435
436 hallCfg->root = NULL;
437 (void)memset_s(&hallCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
438 (void)memset_s(&hallCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
439 }
440
HallInitDriver(struct HdfDeviceObject * device)441 int32_t HallInitDriver(struct HdfDeviceObject *device)
442 {
443 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
444
445 struct HallDrvData *drvData = (struct HallDrvData *)device->service;
446 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
447
448 if (InitHallData(drvData) != HDF_SUCCESS) {
449 HDF_LOGE("%s: Init hall config failed", __func__);
450 return HDF_FAILURE;
451 }
452
453 drvData->hallCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*drvData->hallCfg));
454 if (drvData->hallCfg == NULL) {
455 HDF_LOGE("%s: Malloc hall config data failed", __func__);
456 return HDF_FAILURE;
457 }
458
459 HDF_LOGI("%s: Init hall driver success", __func__);
460 return HDF_SUCCESS;
461 }
462
HallReleaseDriver(struct HdfDeviceObject * device)463 void HallReleaseDriver(struct HdfDeviceObject *device)
464 {
465 struct HallDrvData *drvData = NULL;
466 CHECK_NULL_PTR_RETURN(device);
467
468 drvData = (struct HallDrvData *)device->service;
469 CHECK_NULL_PTR_RETURN(drvData);
470
471 if (drvData->detectFlag) {
472 HallReleaseCfgData(drvData->hallCfg);
473 }
474
475 OsalMemFree(drvData->hallCfg);
476 drvData->hallCfg = NULL;
477
478 HdfWorkDestroy(&drvData->hallWork);
479 HdfWorkQueueDestroy(&drvData->hallWorkQueue);
480 OsalMemFree(drvData);
481 }
482
483 struct HdfDriverEntry g_sensorHallDevEntry = {
484 .moduleVersion = 1,
485 .moduleName = "HDF_SENSOR_HALL",
486 .Bind = HallBindDriver,
487 .Init = HallInitDriver,
488 .Release = HallReleaseDriver,
489 };
490
491 HDF_INIT(g_sensorHallDevEntry);
492