• 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_math.h"
17 #include "osal_mem.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 
HallDataWorkEntry(void * arg)44 static void HallDataWorkEntry(void *arg)
45 {
46     struct HallDrvData *drvData = NULL;
47 
48     drvData = (struct HallDrvData *)arg;
49     CHECK_NULL_PTR_RETURN(drvData);
50 
51     if (drvData->ops.ReadData == NULL) {
52         HDF_LOGI("%s: Hall ReadData function NULL", __func__);
53         return;
54     }
55     if (drvData->ops.ReadData(drvData->hallCfg) != HDF_SUCCESS) {
56         HDF_LOGE("%s: Hall read data failed", __func__);
57     }
58 }
59 
HallNorthPolarityIrqFunc(uint16_t gpio,void * data)60 static int32_t HallNorthPolarityIrqFunc(uint16_t gpio, void *data)
61 {
62     (void)gpio;
63 
64     struct HallDrvData *drvData = (struct HallDrvData *)data;
65     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
66 
67     if (!HdfAddWork(&drvData->hallWorkQueue, &drvData->hallWork)) {
68         HDF_LOGE("%s: Hall add work queue failed", __func__);
69     }
70 
71     return HDF_SUCCESS;
72 }
73 
HallSouthPolarityIrqFunc(uint16_t gpio,void * data)74 static int32_t HallSouthPolarityIrqFunc(uint16_t gpio, void *data)
75 {
76     (void)gpio;
77 
78     struct HallDrvData *drvData = (struct HallDrvData *)data;
79     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
80 
81     if (!HdfAddWork(&drvData->hallWorkQueue, &drvData->hallWork)) {
82         HDF_LOGE("%s: Hall add work queue failed", __func__);
83     }
84 
85     return HDF_SUCCESS;
86 }
87 
InitHallData(struct HallDrvData * drvData)88 static int32_t InitHallData(struct HallDrvData *drvData)
89 {
90     if (HdfWorkQueueInit(&drvData->hallWorkQueue, HDF_HALL_WORK_QUEUE_NAME) != HDF_SUCCESS) {
91         HDF_LOGE("%s: Hall init work queue failed", __func__);
92         return HDF_FAILURE;
93     }
94 
95     if (HdfWorkInit(&drvData->hallWork, HallDataWorkEntry, drvData) != HDF_SUCCESS) {
96         HDF_LOGE("%s: Hall create thread failed", __func__);
97         return HDF_FAILURE;
98     }
99 
100     drvData->interval = SENSOR_TIMER_MIN_TIME;
101     drvData->enable = false;
102     drvData->detectFlag = false;
103 
104     return HDF_SUCCESS;
105 }
106 
SetHallEnable(void)107 static int32_t SetHallEnable(void)
108 {
109     int32_t ret;
110     struct HallDrvData *drvData = HallGetDrvData();
111     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
112 
113     if (drvData->enable) {
114         HDF_LOGE("%s: Hall sensor is enabled", __func__);
115         return HDF_SUCCESS;
116     }
117 
118     if (drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO] >= 0) {
119         ret = GpioSetIrq(drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO], OSAL_IRQF_TRIGGER_FALLING,
120             HallNorthPolarityIrqFunc, drvData);
121         if (ret != 0) {
122             HDF_LOGE("Gpio set north irq failed: %d", ret);
123         }
124         ret = GpioEnableIrq(drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO]);
125         if (ret != 0) {
126             HDF_LOGE("Gpio enable north irq failed: %d", ret);
127         }
128     }
129 
130     if (drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO] >= 0) {
131         ret = GpioSetIrq(drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO], OSAL_IRQF_TRIGGER_FALLING,
132             HallSouthPolarityIrqFunc, drvData);
133         if (ret != 0) {
134             HDF_LOGE("%s: Gpio set south irq failed", __func__);
135         }
136         ret = GpioEnableIrq(drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO]);
137         if (ret != 0) {
138             HDF_LOGE("%s: Gpio enable south irq failed", __func__);
139         }
140     }
141 
142     drvData->enable = true;
143     return HDF_SUCCESS;
144 }
145 
SetHallDisable(void)146 static int32_t SetHallDisable(void)
147 {
148     int32_t ret;
149     struct HallDrvData *drvData = HallGetDrvData();
150     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
151 
152     if (!drvData->enable) {
153         HDF_LOGE("%s: Hall sensor had disable", __func__);
154         return HDF_SUCCESS;
155     }
156 
157     if (drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO] >= 0) {
158         ret = GpioUnSetIrq(drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO]);
159         if (ret != 0) {
160             HDF_LOGE("%s: Gpio unset north irq failed", __func__);
161         }
162 
163         ret = GpioDisableIrq(drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO]);
164         if (ret != 0) {
165             HDF_LOGE("%s: Gpio disable north irq failed", __func__);
166         }
167     }
168 
169     if (drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO] >= 0) {
170         ret = GpioUnSetIrq(drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO]);
171         if (ret != 0) {
172             HDF_LOGE("%s: Gpio unset south irq failed", __func__);
173         }
174 
175         ret = GpioDisableIrq(drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO]);
176         if (ret != 0) {
177             HDF_LOGE("%s: Gpio disable south irq failed", __func__);
178         }
179     }
180     drvData->enable = false;
181 
182     return HDF_SUCCESS;
183 }
184 
SetHallBatch(int64_t samplingInterval,int64_t interval)185 static int32_t SetHallBatch(int64_t samplingInterval, int64_t interval)
186 {
187     return HDF_SUCCESS;
188 }
189 
SetHallMode(int32_t mode)190 static int32_t SetHallMode(int32_t mode)
191 {
192     return (mode == SENSOR_WORK_MODE_ON_CHANGE) ? HDF_SUCCESS : HDF_FAILURE;
193 }
194 
SetHallOption(uint32_t option)195 static int32_t SetHallOption(uint32_t option)
196 {
197     (void)option;
198     return HDF_SUCCESS;
199 }
200 
DispatchHall(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)201 static int32_t DispatchHall(struct HdfDeviceIoClient *client,
202     int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
203 {
204     (void)client;
205     (void)cmd;
206     (void)data;
207     (void)reply;
208 
209     return HDF_SUCCESS;
210 }
211 
HallBindDriver(struct HdfDeviceObject * device)212 int32_t HallBindDriver(struct HdfDeviceObject *device)
213 {
214     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
215 
216     struct HallDrvData *drvData = (struct HallDrvData *)OsalMemCalloc(sizeof(*drvData));
217     if (drvData == NULL) {
218         HDF_LOGE("%s: Malloc hall drv data fail!", __func__);
219         return HDF_ERR_MALLOC_FAIL;
220     }
221 
222     drvData->ioService.Dispatch = DispatchHall;
223     drvData->device = device;
224     device->service = &drvData->ioService;
225     g_hallDrvData = drvData;
226     return HDF_SUCCESS;
227 }
228 
InitHallOps(struct SensorCfgData * config,struct SensorDeviceInfo * deviceInfo)229 static int32_t InitHallOps(struct SensorCfgData *config, struct SensorDeviceInfo *deviceInfo)
230 {
231     CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
232 
233     deviceInfo->ops.Enable = SetHallEnable;
234     deviceInfo->ops.Disable = SetHallDisable;
235     deviceInfo->ops.SetBatch = SetHallBatch;
236     deviceInfo->ops.SetMode = SetHallMode;
237     deviceInfo->ops.SetOption = SetHallOption;
238 
239     if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo),
240         &config->sensorInfo, sizeof(config->sensorInfo)) != EOK) {
241         HDF_LOGE("%s: Copy sensor info failed", __func__);
242         return HDF_FAILURE;
243     }
244 
245     return HDF_SUCCESS;
246 }
247 
ParserHallPinConfigData(const struct DeviceResourceNode * node,struct HallDrvData * drvData)248 static int32_t ParserHallPinConfigData(const struct DeviceResourceNode *node, struct HallDrvData *drvData)
249 {
250     int32_t ret;
251     struct DeviceResourceIface *parser = NULL;
252 
253     CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
254     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
255 
256     parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
257     CHECK_NULL_PTR_RETURN_VALUE(parser, HDF_ERR_INVALID_PARAM);
258 
259     CHECK_NULL_PTR_RETURN_VALUE(parser->GetChildNode, HDF_ERR_INVALID_PARAM);
260 
261     const struct DeviceResourceNode *pinNode = parser->GetChildNode(node, "hallPinConfig");
262     CHECK_NULL_PTR_RETURN_VALUE(pinNode, HDF_ERR_INVALID_PARAM);
263 
264     ret = parser->GetUint32(pinNode, "NorthPolarityGpio", (uint32_t *)&drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO], 0);
265     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "NorthPolarityGpio");
266     ret = parser->GetUint32(pinNode, "SouthPolarityGpio", (uint32_t *)&drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO], 0);
267     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "SouthPolarityGpio");
268 
269     return HDF_SUCCESS;
270 }
271 
InitHallAfterDetected(const struct DeviceResourceNode * node,struct HallDrvData * drvData)272 static int32_t InitHallAfterDetected(const struct DeviceResourceNode *node, struct HallDrvData *drvData)
273 {
274     struct SensorDeviceInfo deviceInfo;
275     CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
276     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
277 
278     if (InitHallOps(drvData->hallCfg, &deviceInfo) != HDF_SUCCESS) {
279         HDF_LOGE("%s: Init hall ops failed", __func__);
280         return HDF_FAILURE;
281     }
282 
283     if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
284         HDF_LOGE("%s: Add hall device failed", __func__);
285         return HDF_FAILURE;
286     }
287 
288     if (ParserHallPinConfigData(node, drvData) != HDF_SUCCESS) {
289         HDF_LOGE("%s: get hall pin config failed", __func__);
290         (void)DeleteSensorDevice(&drvData->hallCfg->sensorInfo);
291         return HDF_FAILURE;
292     }
293     return HDF_SUCCESS;
294 }
295 
SetHallGpioPin(struct HallDrvData * drvData)296 static int32_t SetHallGpioPin(struct HallDrvData *drvData)
297 {
298     if (drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO] >= 0) {
299         int ret = GpioSetDir(drvData->GpioIrq[HALL_NORTH_POLARITY_GPIO], GPIO_DIR_IN);
300         if (ret != 0) {
301             HDF_LOGE("%s:%d set north gpio dir failed", __func__, __LINE__);
302             return HDF_FAILURE;
303         }
304     }
305 
306     if (drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO] >= 0) {
307         int ret = GpioSetDir(drvData->GpioIrq[HALL_SOUTH_POLARITY_GPIO], GPIO_DIR_IN);
308         if (ret != 0) {
309             HDF_LOGE("%s:%d south south gpio dir failed", __func__, __LINE__);
310             return HDF_FAILURE;
311         }
312     }
313 
314     return HDF_SUCCESS;
315 }
316 
HallCreateCfgData(const struct DeviceResourceNode * node)317 struct SensorCfgData *HallCreateCfgData(const struct DeviceResourceNode *node)
318 {
319     struct HallDrvData *drvData = HallGetDrvData();
320 
321     if (drvData == NULL || node == NULL) {
322         HDF_LOGE("%s: Hall node pointer NULL", __func__);
323         return NULL;
324     }
325 
326     if (drvData->detectFlag) {
327         HDF_LOGE("%s: Hall sensor have detected", __func__);
328         return NULL;
329     }
330 
331     if (drvData->hallCfg == NULL) {
332         HDF_LOGE("%s: Hall hallCfg pointer NULL", __func__);
333         return NULL;
334     }
335 
336     if (GetSensorBaseConfigData(node, drvData->hallCfg) != HDF_SUCCESS) {
337         HDF_LOGE("%s: Get sensor base config failed", __func__);
338         goto BASE_CONFIG_EXIT;
339     }
340 
341     if (SetHallGpioPin(drvData) != HDF_SUCCESS) {
342         HDF_LOGE("%s: set hall gpio pin failed", __func__);
343         goto BASE_CONFIG_EXIT;
344     }
345 
346     if (DetectSensorDevice(drvData->hallCfg) != HDF_SUCCESS) {
347         HDF_LOGI("%s: Hall sensor detect device no exist", __func__);
348         drvData->detectFlag = false;
349         goto BASE_CONFIG_EXIT;
350     }
351 
352     drvData->detectFlag = true;
353     if (InitHallAfterDetected(node, drvData) != HDF_SUCCESS) {
354         HDF_LOGE("%s: Hall sensor detect device no exist", __func__);
355         goto BASE_CONFIG_EXIT;
356     }
357 
358     return drvData->hallCfg;
359 
360 BASE_CONFIG_EXIT:
361     drvData->hallCfg->root = NULL;
362     (void)memset_s(&drvData->hallCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
363     (void)memset_s(&drvData->hallCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
364     return NULL;
365 }
366 
HallReleaseCfgData(struct SensorCfgData * hallCfg)367 void HallReleaseCfgData(struct SensorCfgData *hallCfg)
368 {
369     CHECK_NULL_PTR_RETURN(hallCfg);
370 
371     (void)DeleteSensorDevice(&hallCfg->sensorInfo);
372 
373     hallCfg->root = NULL;
374     (void)memset_s(&hallCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
375     (void)memset_s(&hallCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
376 }
377 
HallInitDriver(struct HdfDeviceObject * device)378 int32_t HallInitDriver(struct HdfDeviceObject *device)
379 {
380     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
381 
382     struct HallDrvData *drvData = (struct HallDrvData *)device->service;
383     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
384 
385     if (InitHallData(drvData) != HDF_SUCCESS) {
386         HDF_LOGE("%s: Init hall config failed", __func__);
387         return HDF_FAILURE;
388     }
389 
390     drvData->hallCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*drvData->hallCfg));
391     if (drvData->hallCfg == NULL) {
392         HDF_LOGE("%s: Malloc hall config data failed", __func__);
393         return HDF_FAILURE;
394     }
395 
396     HDF_LOGI("%s: Init hall driver success", __func__);
397     return HDF_SUCCESS;
398 }
399 
HallReleaseDriver(struct HdfDeviceObject * device)400 void HallReleaseDriver(struct HdfDeviceObject *device)
401 {
402     struct HallDrvData *drvData = NULL;
403     CHECK_NULL_PTR_RETURN(device);
404 
405     drvData = (struct HallDrvData *)device->service;
406     CHECK_NULL_PTR_RETURN(drvData);
407 
408     if (drvData->detectFlag) {
409         HallReleaseCfgData(drvData->hallCfg);
410     }
411 
412     OsalMemFree(drvData->hallCfg);
413     drvData->hallCfg = NULL;
414 
415     HdfWorkDestroy(&drvData->hallWork);
416     HdfWorkQueueDestroy(&drvData->hallWorkQueue);
417     OsalMemFree(drvData);
418 }
419 
420 struct HdfDriverEntry g_sensorHallDevEntry = {
421     .moduleVersion = 1,
422     .moduleName = "HDF_SENSOR_HALL",
423     .Bind = HallBindDriver,
424     .Init = HallInitDriver,
425     .Release = HallReleaseDriver,
426 };
427 
428 HDF_INIT(g_sensorHallDevEntry);