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);