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