1 /*
2  * Copyright (c) 2021-2022 xu
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 "proximity_apds9960.h"
10 #include <securec.h>
11 #include "osal_mem.h"
12 #include "osal_time.h"
13 #include "sensor_config_controller.h"
14 #include "sensor_device_manager.h"
15 #include "sensor_proximity_driver.h"
16 
17 #define HDF_LOG_TAG    khdf_sensor_proximity_driver
18 
19 #define PROXIMITY_STATE_FAR    5
20 #define PROXIMITY_STATE_NEAR   0
21 
22 static struct Apds9960DrvData *g_apds9960DrvData = NULL;
23 
24 /* IO config for int-pin and I2C-pin */
25 #define SENSOR_I2C6_DATA_REG_ADDR 0x114f004c
26 #define SENSOR_I2C6_CLK_REG_ADDR  0x114f0048
27 #define SENSOR_I2C_REG_CFG        0x403
28 
ReadApds9960RawData(struct SensorCfgData * data,struct ProximityData * rawData,uint64_t * timestamp)29 static int32_t ReadApds9960RawData(struct SensorCfgData *data, struct ProximityData *rawData, uint64_t *timestamp)
30 {
31     OsalTimespec time;
32 
33     (void)memset_s(&time, sizeof(time), 0, sizeof(time));
34 
35     CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
36 
37     if (OsalGetTime(&time) != HDF_SUCCESS) {
38         HDF_LOGE("%s: Get time failed", __func__);
39         return HDF_FAILURE;
40     }
41     *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
42 
43     int32_t ret = ReadSensor(&data->busCfg, APDS9960_PROXIMITY_DATA_ADDR, &rawData->stateFlag, sizeof(uint8_t));
44     CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
45 
46     return ret;
47 }
48 
ReadApds9960Data(struct SensorCfgData * data)49 static int32_t ReadApds9960Data(struct SensorCfgData *data)
50 {
51     int32_t ret;
52     int32_t tmp;
53     struct ProximityData rawData = { 5 };
54     struct SensorReportEvent event;
55 
56     (void)memset_s(&event, sizeof(event), 0, sizeof(event));
57 
58     ret = ReadApds9960RawData(data, &rawData, &event.timestamp);
59     if (ret != HDF_SUCCESS) {
60         return HDF_FAILURE;
61     }
62 
63     event.sensorId = SENSOR_TAG_PROXIMITY;
64     event.option = 0;
65     event.mode = SENSOR_WORK_MODE_ON_CHANGE;
66 
67     if (rawData.stateFlag <= APDS9960_PROXIMITY_THRESHOLD) {
68         tmp = PROXIMITY_STATE_FAR;
69     } else {
70         tmp = PROXIMITY_STATE_NEAR;
71     }
72 
73     event.dataLen = sizeof(tmp);
74     event.data = (uint8_t *)&tmp;
75     ret = ReportSensorEvent(&event);
76     if (ret != HDF_SUCCESS) {
77         HDF_LOGE("%s: APDS9960 report data failed", __func__);
78     }
79 
80     return ret;
81 }
82 
InitApda9960(struct SensorCfgData * data)83 static int32_t InitApda9960(struct SensorCfgData *data)
84 {
85     int32_t ret;
86 
87     CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
88     ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
89     if (ret != HDF_SUCCESS) {
90         HDF_LOGE("%s: APDS9960 sensor init config failed", __func__);
91         return HDF_FAILURE;
92     }
93     return HDF_SUCCESS;
94 }
95 
InitProximityPreConfig(void)96 static int32_t InitProximityPreConfig(void)
97 {
98     if (SetSensorPinMux(SENSOR_I2C6_DATA_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
99         HDF_LOGE("%s: Data write mux pin failed", __func__);
100         return HDF_FAILURE;
101     }
102     if (SetSensorPinMux(SENSOR_I2C6_CLK_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
103         HDF_LOGE("%s: Clk write mux pin failed", __func__);
104         return HDF_FAILURE;
105     }
106 
107     return HDF_SUCCESS;
108 }
109 
DispatchApds9960(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)110 static int32_t DispatchApds9960(struct HdfDeviceIoClient *client,
111     int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
112 {
113     (void)client;
114     (void)cmd;
115     (void)data;
116     (void)reply;
117 
118     return HDF_SUCCESS;
119 }
120 
Apds9960BindDriver(struct HdfDeviceObject * device)121 static int32_t Apds9960BindDriver(struct HdfDeviceObject *device)
122 {
123     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
124 
125     struct Apds9960DrvData *drvData = (struct Apds9960DrvData *)OsalMemCalloc(sizeof(*drvData));
126     if (drvData == NULL) {
127         HDF_LOGE("%s: Malloc Apds9960 drv data fail", __func__);
128         return HDF_ERR_MALLOC_FAIL;
129     }
130 
131     drvData->ioService.Dispatch = DispatchApds9960;
132     drvData->device = device;
133     device->service = &drvData->ioService;
134     g_apds9960DrvData = drvData;
135 
136     return HDF_SUCCESS;
137 }
138 
Apds996InitDriver(struct HdfDeviceObject * device)139 static int32_t Apds996InitDriver(struct HdfDeviceObject *device)
140 {
141     int32_t ret;
142     struct ProximityOpsCall ops;
143 
144     CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
145     struct Apds9960DrvData *drvData = (struct Apds9960DrvData *)device->service;
146     CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
147 
148     ret = InitProximityPreConfig();
149     if (ret != HDF_SUCCESS) {
150         HDF_LOGE("%s: Init  APDS9960 bus mux config", __func__);
151         return HDF_FAILURE;
152     }
153 
154     drvData->sensorCfg = ProximityCreateCfgData(device->property);
155     if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
156         HDF_LOGD("%s: Creating proximitycfg failed because detection failed", __func__);
157         return HDF_ERR_NOT_SUPPORT;
158     }
159 
160     ops.Init = NULL;
161     ops.ReadData = ReadApds9960Data;
162     ret = ProximityRegisterChipOps(&ops);
163     if (ret != HDF_SUCCESS) {
164         HDF_LOGE("%s: Register APDS9960 proximity failed", __func__);
165         return HDF_FAILURE;
166     }
167 
168     ret = InitApda9960(drvData->sensorCfg);
169     if (ret != HDF_SUCCESS) {
170         HDF_LOGE("%s: Init APDS9960 proximity failed", __func__);
171         return HDF_FAILURE;
172     }
173 
174     return HDF_SUCCESS;
175 }
176 
177 
Apds996ReleaseDriver(struct HdfDeviceObject * device)178 static void Apds996ReleaseDriver(struct HdfDeviceObject *device)
179 {
180     CHECK_NULL_PTR_RETURN(device);
181 
182     struct Apds9960DrvData *drvData = (struct Apds9960DrvData *)device->service;
183     CHECK_NULL_PTR_RETURN(drvData);
184 
185     if (drvData->sensorCfg != NULL) {
186         ProximityReleaseCfgData(drvData->sensorCfg);
187         drvData->sensorCfg = NULL;
188     }
189     OsalMemFree(drvData);
190 }
191 
192 struct HdfDriverEntry g_proximityApds9960DevEntry = {
193     .moduleVersion = 1,
194     .moduleName = "HDF_SENSOR_PROXIMITY_APDS9960",
195     .Bind = Apds9960BindDriver,
196     .Init = Apds996InitDriver,
197     .Release = Apds996ReleaseDriver,
198 };
199 
200 HDF_INIT(g_proximityApds9960DevEntry);