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 "humidity_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_humidity_driver.h"
16
17 #define HDF_LOG_TAG hdf_sensor_humidity_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 HumidityData * rawData,uint64_t * timestamp)26 static int32_t ReadAht20RawData(struct SensorCfgData *data, struct HumidityData *rawData, uint64_t *timestamp)
27 {
28 OsalTimespec time;
29 int32_t cnt;
30 uint64_t humidityValue;
31 int32_t ret = HDF_SUCCESS;
32 uint8_t value[AHT20_HUM_DATA_BUF_LEN] = {0};
33 uint8_t measureCmdValue[] = {AHT20_HUM_MEASURE_ADDR, AHT20_HUM_MEASURE_ARG0, AHT20_HUM_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_HUM_DELAY_MS);
50
51 ret = ReadSensor(&data->busCfg, AHT20_HUM_STATUS_ADDR, value, sizeof(value));
52 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
53
54 for (cnt = 0; AHT20_HUM_IS_BUSY(value[AHT20_HUM_VALUE_IDX_ZERO]) && (cnt < AHT20_HUM_RETRY_TIMES); cnt++) {
55 OsalMDelay(AHT20_HUM_DELAY_MS);
56 ret = ReadSensor(&data->busCfg, AHT20_HUM_STATUS_ADDR, value, sizeof(value));
57 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
58 }
59
60 if (cnt >= AHT20_HUM_RETRY_TIMES) {
61 HDF_LOGE("%s:line %d aht20 device status busy!", __func__, __LINE__);
62 return HDF_FAILURE;
63 }
64
65 humidityValue = value[AHT20_HUM_VALUE_IDX_ONE];
66 humidityValue = (humidityValue << AHT20_HUM_SHFIT_EIGHT_BITS) | value[AHT20_HUM_VALUE_IDX_TWO];
67 humidityValue = (humidityValue << AHT20_HUM_SHFIT_FOUR_BITS) | \
68 ((value[AHT20_HUM_VALUE_IDX_THREE] & AHT20_HUM_MASK) >> AHT20_HUM_SHFIT_FOUR_BITS);
69
70 rawData->humidity = ((humidityValue * AHT20_HUM_SLOPE) / AHT20_HUM_RESOLUTION);
71
72 return HDF_SUCCESS;
73 }
74
ReadAht20Data(struct SensorCfgData * data)75 static int32_t ReadAht20Data(struct SensorCfgData *data)
76 {
77 int32_t ret;
78 static int32_t humidity;
79 struct HumidityData rawData = { 0 };
80 OsalTimespec time;
81 struct SensorReportEvent event;
82
83 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
84 (void)memset_s(&event, sizeof(event), 0, sizeof(event));
85
86 if (OsalGetTime(&time) != HDF_SUCCESS) {
87 HDF_LOGE("%s: Get time failed", __func__);
88 return HDF_FAILURE;
89 }
90
91 event.timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT;
92
93 ret = ReadAht20RawData(data, &rawData, &event.timestamp);
94 if (ret != HDF_SUCCESS) {
95 HDF_LOGE("%s: AHT20 read raw data failed", __func__);
96 return HDF_FAILURE;
97 }
98
99 humidity = rawData.humidity;
100
101 event.sensorId = SENSOR_TAG_HUMIDITY;
102 event.mode = SENSOR_WORK_MODE_REALTIME;
103 event.dataLen = sizeof(humidity);
104 event.data = (uint8_t *)&humidity;
105 ret = ReportSensorEvent(&event);
106 if (ret != HDF_SUCCESS) {
107 HDF_LOGE("%s: report data failed", __func__);
108 }
109
110 return ret;
111 }
112
InitAht20(struct SensorCfgData * data)113 static int32_t InitAht20(struct SensorCfgData *data)
114 {
115 int32_t ret;
116 uint8_t value[AHT20_HUM_DATA_BUF_LEN];
117 uint8_t resetCmd = AHT20_HUM_RESET_ADDR;
118 uint8_t calibrationCmd[] = {AHT20_HUM_CALIBRATION_ADDR, AHT20_HUM_CALIBRATION_ARG0, AHT20_HUM_CALIBRATION_ARG1};
119
120 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
121 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
122 if (ret != HDF_SUCCESS) {
123 HDF_LOGE("%s: sensor init config failed", __func__);
124 return HDF_FAILURE;
125 }
126
127 ret = ReadSensor(&data->busCfg, AHT20_HUM_STATUS_ADDR, value, sizeof(value));
128 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
129
130 if (AHT20_HUM_IS_BUSY(value[AHT20_HUM_VALUE_IDX_ZERO]) || !AHT20_HUM_IS_CALI(value[AHT20_HUM_VALUE_IDX_ZERO])) {
131 ret = WriteSensor(&data->busCfg, &resetCmd, sizeof(resetCmd));
132 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "write data");
133
134 OsalMDelay(AHT20_HUM_STARTUP_MS);
135
136 ret = WriteSensor(&data->busCfg, calibrationCmd, sizeof(calibrationCmd));
137 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "write data");
138
139 OsalMDelay(AHT20_HUM_CALIBRATION_MS);
140 }
141
142 return HDF_SUCCESS;
143 }
144
DispatchAht20(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)145 static int32_t DispatchAht20(struct HdfDeviceIoClient *client,
146 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
147 {
148 (void)client;
149 (void)cmd;
150 (void)data;
151 (void)reply;
152
153 return HDF_SUCCESS;
154 }
155
Aht20BindDriver(struct HdfDeviceObject * device)156 static int32_t Aht20BindDriver(struct HdfDeviceObject *device)
157 {
158 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
159
160 struct Aht20DrvData *drvData = (struct Aht20DrvData *)OsalMemCalloc(sizeof(*drvData));
161 if (drvData == NULL) {
162 HDF_LOGE("%s: malloc drv data fail", __func__);
163 return HDF_ERR_MALLOC_FAIL;
164 }
165
166 drvData->ioService.Dispatch = DispatchAht20;
167 drvData->device = device;
168 device->service = &drvData->ioService;
169 g_aht20DrvData = drvData;
170
171 return HDF_SUCCESS;
172 }
173
Aht20InitDriver(struct HdfDeviceObject * device)174 static int32_t Aht20InitDriver(struct HdfDeviceObject *device)
175 {
176 int32_t ret;
177 struct HumidityOpsCall ops;
178
179 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
180 struct Aht20DrvData *drvData = (struct Aht20DrvData *)device->service;
181 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
182
183 drvData->sensorCfg = HumidityCreateCfgData(device->property);
184 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
185 HDF_LOGE("%s: Creating humidity cfg failed because detection failed", __func__);
186 return HDF_ERR_NOT_SUPPORT;
187 }
188
189 ops.Init = NULL;
190 ops.ReadData = ReadAht20Data;
191 ret = HumidityRegisterChipOps(&ops);
192 if (ret != HDF_SUCCESS) {
193 HDF_LOGE("%s: Register humidity failed", __func__);
194 return HDF_FAILURE;
195 }
196
197 ret = InitAht20(drvData->sensorCfg);
198 if (ret != HDF_SUCCESS) {
199 HDF_LOGE("%s: Init AHT20 humidity sensor failed", __func__);
200 return HDF_FAILURE;
201 }
202
203 return HDF_SUCCESS;
204 }
205
Aht20ReleaseDriver(struct HdfDeviceObject * device)206 static void Aht20ReleaseDriver(struct HdfDeviceObject *device)
207 {
208 CHECK_NULL_PTR_RETURN(device);
209
210 struct Aht20DrvData *drvData = (struct Aht20DrvData *)device->service;
211 CHECK_NULL_PTR_RETURN(drvData);
212
213 if (drvData->sensorCfg != NULL) {
214 HumidityReleaseCfgData(drvData->sensorCfg);
215 drvData->sensorCfg = NULL;
216 }
217 OsalMemFree(drvData);
218 }
219
220 struct HdfDriverEntry g_humidityAht20DevEntry = {
221 .moduleVersion = 1,
222 .moduleName = "HDF_SENSOR_HUMIDITY_AHT20",
223 .Bind = Aht20BindDriver,
224 .Init = Aht20InitDriver,
225 .Release = Aht20ReleaseDriver,
226 };
227
228 HDF_INIT(g_humidityAht20DevEntry);
229