• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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