• 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 "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