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 22static 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 29static 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 49static 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 83static 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 96static 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 110static 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 121static 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 139static 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 178static 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 192struct HdfDriverEntry g_proximityApds9960DevEntry = { 193 .moduleVersion = 1, 194 .moduleName = "HDF_SENSOR_PROXIMITY_APDS9960", 195 .Bind = Apds9960BindDriver, 196 .Init = Apds996InitDriver, 197 .Release = Apds996ReleaseDriver, 198}; 199 200HDF_INIT(g_proximityApds9960DevEntry);