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