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_proximity_driver.h"
10 #include <securec.h>
11 #include "hdf_base.h"
12 #include "hdf_device_desc.h"
13 #include "osal_math.h"
14 #include "osal_mem.h"
15 #include "sensor_config_controller.h"
16 #include "sensor_device_manager.h"
17 #include "sensor_platform_if.h"
18
19 #define HDF_LOG_TAG khdf_sensor_proximity_driver
20
21 #define HDF_PROXIMITY_WORK_QUEUE_NAME "hdf_proximity_work_queue"
22
23 static struct ProximityDrvData *g_proximityDrvData = NULL;
24
ProximityGetDrvData(void)25 static struct ProximityDrvData *ProximityGetDrvData(void)
26 {
27 return g_proximityDrvData;
28 }
29
30 static struct SensorRegCfgGroupNode *g_regCfgGroup[SENSOR_GROUP_MAX] = { NULL };
31
ProximityRegisterChipOps(const struct ProximityOpsCall * ops)32 int32_t ProximityRegisterChipOps(const struct ProximityOpsCall *ops)
33 {
34 struct ProximityDrvData *drvData = NULL;
35
36 CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM);
37
38 drvData = ProximityGetDrvData();
39 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
40 drvData->ops.Init = ops->Init;
41 drvData->ops.ReadData = ops->ReadData;
42 return HDF_SUCCESS;
43 }
44
ProximityDataWorkEntry(void * arg)45 static void ProximityDataWorkEntry(void *arg)
46 {
47 int32_t ret;
48 struct ProximityDrvData *drvData = (struct ProximityDrvData *)arg;
49 CHECK_NULL_PTR_RETURN(drvData);
50 CHECK_NULL_PTR_RETURN(drvData->ops.ReadData);
51
52 ret = drvData->ops.ReadData(drvData->proximityCfg);
53 if (ret != HDF_SUCCESS) {
54 HDF_LOGE("%s: proximity read data failed", __func__);
55 return;
56 }
57 }
58
ProximityTimerEntry(uintptr_t arg)59 static void ProximityTimerEntry(uintptr_t arg)
60 {
61 int64_t interval;
62 int32_t ret;
63 struct ProximityDrvData *drvData = (struct ProximityDrvData *)arg;
64 CHECK_NULL_PTR_RETURN(drvData);
65
66 if (!HdfAddWork(&drvData->proximityWorkQueue, &drvData->proximityWork)) {
67 HDF_LOGE("%s: proximity add work queue failed", __func__);
68 }
69
70 interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT));
71 interval = (interval < SENSOR_TIMER_MIN_TIME) ? SENSOR_TIMER_MIN_TIME : interval;
72 ret = OsalTimerSetTimeout(&drvData->proximityTimer, interval);
73 if (ret != HDF_SUCCESS) {
74 HDF_LOGE("%s: proximity modify time failed", __func__);
75 }
76 }
77
InitProximityData(struct ProximityDrvData * drvData)78 static int32_t InitProximityData(struct ProximityDrvData *drvData)
79 {
80 if (HdfWorkQueueInit(&drvData->proximityWorkQueue, HDF_PROXIMITY_WORK_QUEUE_NAME) != HDF_SUCCESS) {
81 HDF_LOGE("%s: proximity init work queue failed", __func__);
82 return HDF_FAILURE;
83 }
84
85 if (HdfWorkInit(&drvData->proximityWork, ProximityDataWorkEntry, drvData) != HDF_SUCCESS) {
86 HDF_LOGE("%s: proximity create thread failed", __func__);
87 return HDF_FAILURE;
88 }
89
90 drvData->interval = SENSOR_TIMER_MIN_TIME;
91 drvData->enable = false;
92 drvData->detectFlag = false;
93
94 return HDF_SUCCESS;
95 }
96
SetProximityEnable(void)97 static int32_t SetProximityEnable(void)
98 {
99 int32_t ret;
100 struct ProximityDrvData *drvData = ProximityGetDrvData();
101
102 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
103 CHECK_NULL_PTR_RETURN_VALUE(drvData->proximityCfg, HDF_ERR_INVALID_PARAM);
104
105 if (drvData->enable) {
106 HDF_LOGE("%s: proximity sensor is enabled", __func__);
107 return HDF_SUCCESS;
108 }
109
110 ret = SetSensorRegCfgArray(&drvData->proximityCfg->busCfg, drvData->proximityCfg->regCfgGroup[SENSOR_ENABLE_GROUP]);
111 if (ret != HDF_SUCCESS) {
112 HDF_LOGE("%s: proximity sensor enable config failed", __func__);
113 return ret;
114 }
115
116 ret = OsalTimerCreate(&drvData->proximityTimer, SENSOR_TIMER_MIN_TIME, ProximityTimerEntry, (uintptr_t)drvData);
117 if (ret != HDF_SUCCESS) {
118 HDF_LOGE("%s: proximity create timer failed[%d]", __func__, ret);
119 return ret;
120 }
121
122 ret = OsalTimerStartLoop(&drvData->proximityTimer);
123 if (ret != HDF_SUCCESS) {
124 HDF_LOGE("%s: proximity start timer failed[%d]", __func__, ret);
125 return ret;
126 }
127 drvData->enable = true;
128
129 return HDF_SUCCESS;
130 }
131
SetProximityDisable(void)132 static int32_t SetProximityDisable(void)
133 {
134 int32_t ret;
135 struct ProximityDrvData *drvData = ProximityGetDrvData();
136
137 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
138 CHECK_NULL_PTR_RETURN_VALUE(drvData->proximityCfg, HDF_ERR_INVALID_PARAM);
139
140 if (!drvData->enable) {
141 HDF_LOGE("%s: proximity sensor had disable", __func__);
142 return HDF_SUCCESS;
143 }
144
145 ret = SetSensorRegCfgArray(&drvData->proximityCfg->busCfg,
146 drvData->proximityCfg->regCfgGroup[SENSOR_DISABLE_GROUP]);
147 if (ret != HDF_SUCCESS) {
148 HDF_LOGE("%s: proximity sensor disable config failed", __func__);
149 return ret;
150 }
151
152 ret = OsalTimerDelete(&drvData->proximityTimer);
153 if (ret != HDF_SUCCESS) {
154 HDF_LOGE("%s: proximity delete timer failed", __func__);
155 return ret;
156 }
157 drvData->enable = false;
158 return HDF_SUCCESS;
159 }
160
SetProximityBatch(int64_t samplingInterval,int64_t interval)161 static int32_t SetProximityBatch(int64_t samplingInterval, int64_t interval)
162 {
163 (void)interval;
164
165 struct ProximityDrvData *drvData = NULL;
166
167 drvData = ProximityGetDrvData();
168 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
169
170 drvData->interval = samplingInterval;
171
172 return HDF_SUCCESS;
173 }
174
SetProximityMode(int32_t mode)175 static int32_t SetProximityMode(int32_t mode)
176 {
177 if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
178 HDF_LOGE("%s: The current mode is not supported", __func__);
179 return HDF_FAILURE;
180 }
181
182 return HDF_SUCCESS;
183 }
184
SetProximityOption(uint32_t option)185 static int32_t SetProximityOption(uint32_t option)
186 {
187 (void)option;
188 return HDF_SUCCESS;
189 }
190
DispatchProximity(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)191 static int32_t DispatchProximity(struct HdfDeviceIoClient *client,
192 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
193 {
194 (void)client;
195 (void)cmd;
196 (void)data;
197 (void)reply;
198
199 return HDF_SUCCESS;
200 }
201
ProximityBindDriver(struct HdfDeviceObject * device)202 int32_t ProximityBindDriver(struct HdfDeviceObject *device)
203 {
204 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
205
206 HDF_LOGI("%s: enter", __func__);
207 struct ProximityDrvData *drvData = (struct ProximityDrvData *)OsalMemCalloc(sizeof(*drvData));
208 if (drvData == NULL) {
209 HDF_LOGI("%s: malloc proximity drv data fail!", __func__);
210 return HDF_ERR_MALLOC_FAIL;
211 }
212
213 drvData->ioService.Dispatch = DispatchProximity;
214 drvData->device = device;
215 device->service = &drvData->ioService;
216 g_proximityDrvData = drvData;
217 HDF_LOGI("%s: success", __func__);
218 return HDF_SUCCESS;
219 }
220
InitProximityOps(struct SensorCfgData * config,struct SensorDeviceInfo * deviceInfo)221 static int32_t InitProximityOps(struct SensorCfgData *config, struct SensorDeviceInfo *deviceInfo)
222 {
223 struct ProximityDrvData *drvData = ProximityGetDrvData();
224
225 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
226
227 deviceInfo->ops.Enable = SetProximityEnable;
228 deviceInfo->ops.Disable = SetProximityDisable;
229 deviceInfo->ops.SetBatch = SetProximityBatch;
230 deviceInfo->ops.SetMode = SetProximityMode;
231 deviceInfo->ops.SetOption = SetProximityOption;
232
233 if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo),
234 &config->sensorInfo, sizeof(config->sensorInfo)) != EOK) {
235 HDF_LOGE("%s: Copy sensor info failed", __func__);
236 return HDF_FAILURE;
237 }
238
239 return HDF_SUCCESS;
240 }
241
InitProximityAfterDetected(struct SensorCfgData * config)242 static int32_t InitProximityAfterDetected(struct SensorCfgData *config)
243 {
244 struct SensorDeviceInfo deviceInfo;
245 CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
246
247 if (InitProximityOps(config, &deviceInfo) != HDF_SUCCESS) {
248 HDF_LOGE("%s: Init proximity ops failed", __func__);
249 return HDF_FAILURE;
250 }
251
252 if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
253 HDF_LOGE("%s: Add proximity device failed", __func__);
254 return HDF_FAILURE;
255 }
256
257 if (ParseSensorRegConfig(config) != HDF_SUCCESS) {
258 HDF_LOGE("%s: Parse sensor register failed", __func__);
259 (void)DeleteSensorDevice(&config->sensorInfo);
260 ReleaseSensorAllRegConfig(config);
261 return HDF_FAILURE;
262 }
263 return HDF_SUCCESS;
264 }
265
ProximityCreateCfgData(const struct DeviceResourceNode * node)266 struct SensorCfgData *ProximityCreateCfgData(const struct DeviceResourceNode *node)
267 {
268 struct ProximityDrvData *drvData = ProximityGetDrvData();
269
270 if (drvData == NULL || node == NULL) {
271 HDF_LOGE("%s: Proximity node pointer NULL", __func__);
272 return NULL;
273 }
274
275 if (drvData->detectFlag) {
276 HDF_LOGE("%s: Proximity sensor have detected", __func__);
277 return NULL;
278 }
279
280 if (drvData->proximityCfg == NULL) {
281 HDF_LOGE("%s: Proximity proximityCfg pointer NULL", __func__);
282 return NULL;
283 }
284
285 if (GetSensorBaseConfigData(node, drvData->proximityCfg) != HDF_SUCCESS) {
286 HDF_LOGE("%s: Get sensor base config failed", __func__);
287 goto BASE_CONFIG_EXIT;
288 }
289
290 if (DetectSensorDevice(drvData->proximityCfg) != HDF_SUCCESS) {
291 HDF_LOGI("%s: Proximity sensor detect device no exist", __func__);
292 drvData->detectFlag = false;
293 goto BASE_CONFIG_EXIT;
294 }
295
296 drvData->detectFlag = true;
297 if (InitProximityAfterDetected(drvData->proximityCfg) != HDF_SUCCESS) {
298 HDF_LOGE("%s: Proximity sensor detect device no exist", __func__);
299 goto INIT_EXIT;
300 }
301 return drvData->proximityCfg;
302
303 INIT_EXIT:
304 (void)ReleaseSensorBusHandle(&drvData->proximityCfg->busCfg);
305 BASE_CONFIG_EXIT:
306 drvData->proximityCfg->root = NULL;
307 (void)memset_s(&drvData->proximityCfg->sensorInfo, sizeof(struct SensorBasicInfo),
308 0, sizeof(struct SensorBasicInfo));
309 (void)memset_s(&drvData->proximityCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
310 (void)memset_s(&drvData->proximityCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
311 return drvData->proximityCfg;
312 }
313
ProximityReleaseCfgData(struct SensorCfgData * proximityCfg)314 void ProximityReleaseCfgData(struct SensorCfgData *proximityCfg)
315 {
316 CHECK_NULL_PTR_RETURN(proximityCfg);
317
318 (void)DeleteSensorDevice(&proximityCfg->sensorInfo);
319 ReleaseSensorAllRegConfig(proximityCfg);
320 (void)ReleaseSensorBusHandle(&proximityCfg->busCfg);
321
322 proximityCfg->root = NULL;
323 (void)memset_s(&proximityCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
324 (void)memset_s(&proximityCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
325 (void)memset_s(&proximityCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
326 }
327
ProximityInitDriver(struct HdfDeviceObject * device)328 int32_t ProximityInitDriver(struct HdfDeviceObject *device)
329 {
330 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
331 struct ProximityDrvData *drvData = (struct ProximityDrvData *)device->service;
332 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
333
334 if (InitProximityData(drvData) != HDF_SUCCESS) {
335 HDF_LOGE("%s: Init accel config failed", __func__);
336 return HDF_FAILURE;
337 }
338
339 drvData->proximityCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*drvData->proximityCfg));
340 if (drvData->proximityCfg == NULL) {
341 HDF_LOGE("%s: Malloc proximity config data failed", __func__);
342 return HDF_FAILURE;
343 }
344
345 drvData->proximityCfg->regCfgGroup = &g_regCfgGroup[0];
346
347 HDF_LOGI("%s: Init proximity driver success", __func__);
348 return HDF_SUCCESS;
349 }
350
ProximityReleaseDriver(struct HdfDeviceObject * device)351 void ProximityReleaseDriver(struct HdfDeviceObject *device)
352 {
353 HDF_LOGI("%s: enter", __func__);
354 CHECK_NULL_PTR_RETURN(device);
355
356 struct ProximityDrvData *drvData = (struct ProximityDrvData *)device->service;
357 CHECK_NULL_PTR_RETURN(drvData);
358
359 if (drvData->detectFlag && drvData->proximityCfg != NULL) {
360 ProximityReleaseCfgData(drvData->proximityCfg);
361 }
362
363 OsalMemFree(drvData->proximityCfg);
364 drvData->proximityCfg = NULL;
365
366 HdfWorkDestroy(&drvData->proximityWork);
367 HdfWorkQueueDestroy(&drvData->proximityWorkQueue);
368 OsalMemFree(drvData);
369 }
370
371 struct HdfDriverEntry g_sensorProximityDevEntry = {
372 .moduleVersion = 1,
373 .moduleName = "HDF_SENSOR_PROXIMITY",
374 .Bind = ProximityBindDriver,
375 .Init = ProximityInitDriver,
376 .Release = ProximityReleaseDriver,
377 };
378
379 HDF_INIT(g_sensorProximityDevEntry);