1 /*
2 * Copyright (c) 2023 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 "temperature_aht20.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_temperature_driver.h"
16
17 #define HDF_LOG_TAG hdf_sensor_temperature_driver
18
19 static struct Aht20DrvData *g_aht20DrvData = NULL;
20
Aht20GetDrvData(void)21 static struct Aht20DrvData *Aht20GetDrvData(void)
22 {
23 return g_aht20DrvData;
24 }
25
ReadAht20RawData(struct SensorCfgData * data,struct TemperatureData * rawData,uint64_t * timestamp)26 static int32_t ReadAht20RawData(struct SensorCfgData *data, struct TemperatureData *rawData, uint64_t *timestamp)
27 {
28 OsalTimespec time;
29 int32_t count;
30 int32_t ret = HDF_SUCCESS;
31 uint8_t value[AHT20_TEMP_DATA_BUF_LEN];
32 uint64_t tempValue;
33 uint8_t measureCmdValue[] = {AHT20_TEMP_MEASURE_ADDR, AHT20_TEMP_MEASURE_ARG0, AHT20_TEMP_MEASURE_ARG1};
34
35 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
36
37 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
38
39 if (OsalGetTime(&time) != HDF_SUCCESS) {
40 HDF_LOGE("%s: Get time failed", __func__);
41 return HDF_FAILURE;
42 }
43
44 *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
45
46 ret = WriteSensor(&data->busCfg, measureCmdValue, sizeof(measureCmdValue));
47 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "write data");
48
49 OsalMDelay(AHT20_TEMP_DELAY_MS);
50
51 ret = ReadSensor(&data->busCfg, AHT20_TEMP_STATUS_ADDR, value, sizeof(value));
52 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
53
54 for (count = 0; AHT20_TEMP_IS_BUSY(value[AHT20_TEMP_VALUE_IDX_ZERO]) && (count < AHT20_TEMP_RETRY_TIMES); count++) {
55 OsalMDelay(AHT20_TEMP_DELAY_MS);
56 ret = ReadSensor(&data->busCfg, AHT20_TEMP_STATUS_ADDR, value, sizeof(value));
57 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
58 }
59
60 if (count >= AHT20_TEMP_RETRY_TIMES) {
61 HDF_LOGE("%s:line %d aht20 device status busy!", __func__, __LINE__);
62 return HDF_FAILURE;
63 }
64
65 tempValue = value[AHT20_TEMP_VALUE_IDX_THREE] & AHT20_TEMP_MASK;
66 tempValue = (tempValue << AHT20_TEMP_SHFIT_BITS) | value[AHT20_TEMP_VALUE_IDX_FOUR];
67 tempValue = (tempValue << AHT20_TEMP_SHFIT_BITS) | value[AHT20_TEMP_VALUE_IDX_FIVE];
68
69 rawData->temperature = ((tempValue * AHT20_TEMP_SLOPE) / AHT20_TEMP_RESOLUTION) - AHT20_TEMP_CONSATNT;
70
71 return HDF_SUCCESS;
72 }
73
ReadAht20Data(struct SensorCfgData * data)74 static int32_t ReadAht20Data(struct SensorCfgData *data)
75 {
76 int32_t ret;
77 static int32_t temperature;
78 struct TemperatureData rawData = { 0 };
79 OsalTimespec time;
80 struct SensorReportEvent event;
81
82 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
83 (void)memset_s(&event, sizeof(event), 0, sizeof(event));
84
85 if (OsalGetTime(&time) != HDF_SUCCESS) {
86 HDF_LOGE("%s: Get time failed", __func__);
87 return HDF_FAILURE;
88 }
89
90 event.timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT;
91
92 ret = ReadAht20RawData(data, &rawData, &event.timestamp);
93 if (ret != HDF_SUCCESS) {
94 HDF_LOGE("%s: AHT20 read raw data failed", __func__);
95 return HDF_FAILURE;
96 }
97
98 temperature = rawData.temperature;
99
100 event.sensorId = SENSOR_TAG_TEMPERATURE;
101 event.mode = SENSOR_WORK_MODE_REALTIME;
102 event.dataLen = sizeof(temperature);
103 event.data = (uint8_t *)&temperature;
104 ret = ReportSensorEvent(&event);
105 if (ret != HDF_SUCCESS) {
106 HDF_LOGE("%s: report data failed", __func__);
107 }
108
109 return ret;
110 }
111
InitAht20(struct SensorCfgData * data)112 static int32_t InitAht20(struct SensorCfgData *data)
113 {
114 int32_t ret;
115 uint8_t value[AHT20_TEMP_DATA_BUF_LEN];
116 uint8_t resetCmd = AHT20_TEMP_RESET_ADDR;
117 uint8_t calibrationCmd[] = {AHT20_TEMP_CALIBRATION_ADDR, AHT20_TEMP_CALIBRATION_ARG0, AHT20_TEMP_CALIBRATION_ARG1};
118
119 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
120 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
121 if (ret != HDF_SUCCESS) {
122 HDF_LOGE("%s: sensor init config failed", __func__);
123 return HDF_FAILURE;
124 }
125
126 ret = ReadSensor(&data->busCfg, AHT20_TEMP_STATUS_ADDR, value, sizeof(value));
127 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
128
129 if (AHT20_TEMP_IS_BUSY(value[AHT20_TEMP_VALUE_IDX_ZERO]) || !AHT20_TEMP_IS_CALI(value[AHT20_TEMP_VALUE_IDX_ZERO])) {
130 ret = WriteSensor(&data->busCfg, &resetCmd, sizeof(resetCmd));
131 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "write data");
132
133 OsalMDelay(AHT20_TEMP_STARTUP_MS);
134
135 ret = WriteSensor(&data->busCfg, calibrationCmd, sizeof(calibrationCmd));
136 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "write data");
137
138 OsalMDelay(AHT20_TEMP_CALIBRATION_MS);
139 }
140
141 return HDF_SUCCESS;
142 }
143
DispatchAht20(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)144 static int32_t DispatchAht20(struct HdfDeviceIoClient *client,
145 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
146 {
147 (void)client;
148 (void)cmd;
149 (void)data;
150 (void)reply;
151
152 return HDF_SUCCESS;
153 }
154
Aht20BindDriver(struct HdfDeviceObject * device)155 static int32_t Aht20BindDriver(struct HdfDeviceObject *device)
156 {
157 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
158
159 struct Aht20DrvData *drvData = (struct Aht20DrvData *)OsalMemCalloc(sizeof(*drvData));
160 if (drvData == NULL) {
161 HDF_LOGE("%s: malloc drv data fail", __func__);
162 return HDF_ERR_MALLOC_FAIL;
163 }
164
165 drvData->ioService.Dispatch = DispatchAht20;
166 drvData->device = device;
167 device->service = &drvData->ioService;
168 g_aht20DrvData = drvData;
169
170 return HDF_SUCCESS;
171 }
172
Aht20InitDriver(struct HdfDeviceObject * device)173 static int32_t Aht20InitDriver(struct HdfDeviceObject *device)
174 {
175 int32_t ret;
176 struct TemperatureOpsCall ops;
177
178 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
179 struct Aht20DrvData *drvData = (struct Aht20DrvData *)device->service;
180 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
181
182 drvData->sensorCfg = TemperatureCreateCfgData(device->property);
183 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
184 HDF_LOGE("%s: Creating temperature cfg failed because detection failed", __func__);
185 return HDF_ERR_NOT_SUPPORT;
186 }
187
188 ops.Init = NULL;
189 ops.ReadData = ReadAht20Data;
190 ret = TemperatureRegisterChipOps(&ops);
191 if (ret != HDF_SUCCESS) {
192 HDF_LOGE("%s: Register temperature failed", __func__);
193 return HDF_FAILURE;
194 }
195
196 ret = InitAht20(drvData->sensorCfg);
197 if (ret != HDF_SUCCESS) {
198 HDF_LOGE("%s: Init AHT20 temperature sensor failed", __func__);
199 return HDF_FAILURE;
200 }
201
202 return HDF_SUCCESS;
203 }
204
Aht20ReleaseDriver(struct HdfDeviceObject * device)205 static void Aht20ReleaseDriver(struct HdfDeviceObject *device)
206 {
207 CHECK_NULL_PTR_RETURN(device);
208
209 struct Aht20DrvData *drvData = (struct Aht20DrvData *)device->service;
210 CHECK_NULL_PTR_RETURN(drvData);
211
212 if (drvData->sensorCfg != NULL) {
213 TemperatureReleaseCfgData(drvData->sensorCfg);
214 drvData->sensorCfg = NULL;
215 }
216 OsalMemFree(drvData);
217 }
218
219 struct HdfDriverEntry g_temperatureAht20DevEntry = {
220 .moduleVersion = 1,
221 .moduleName = "HDF_SENSOR_TEMPERATURE_AHT20",
222 .Bind = Aht20BindDriver,
223 .Init = Aht20InitDriver,
224 .Release = Aht20ReleaseDriver,
225 };
226
227 HDF_INIT(g_temperatureAht20DevEntry);
228