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_sht30.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 Sht30DrvData *g_sht30DrvData = NULL;
20
Sht30GetDrvData(void)21 static struct Sht30DrvData *Sht30GetDrvData(void)
22 {
23 return g_sht30DrvData;
24 }
25
Sht30CalcCrc8(const uint8_t * data,uint32_t dataLen)26 static uint8_t Sht30CalcCrc8(const uint8_t *data, uint32_t dataLen)
27 {
28 uint8_t value = SHT30_HUM_CRC8_BASE;
29
30 for (uint32_t i = dataLen; i; --i) {
31 value ^= *data++;
32 for (uint32_t j = SENSOR_DATA_WIDTH_8_BIT; j; --j) {
33 value = (value & SHT30_HUM_CRC8_MASK) ? ((value << SHT30_HUM_SHFIT_1_BIT) ^ SHT30_HUM_CRC8_POLYNOMIAL) : \
34 (value << SHT30_HUM_SHFIT_1_BIT);
35 }
36 }
37
38 return value;
39 }
40
ReadSht30RawData(struct SensorCfgData * data,struct HumidityData * rawData,uint64_t * timestamp)41 static int32_t ReadSht30RawData(struct SensorCfgData *data, struct HumidityData *rawData, uint64_t *timestamp)
42 {
43 OsalTimespec time;
44 uint8_t value[SHT30_HUM_DATA_BUF_LEN];
45 uint16_t tempValue;
46
47 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
48
49 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
50
51 if (OsalGetTime(&time) != HDF_SUCCESS) {
52 HDF_LOGE("%s: Get time failed", __func__);
53 return HDF_FAILURE;
54 }
55
56 *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
57
58 int32_t ret = ReadSensor(&data->busCfg, SHT30_HUM_DATA_ADDR, value, sizeof(value));
59 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
60
61 tempValue = value[SHT30_HUM_VALUE_INDEX_THREE];
62 tempValue <<= SENSOR_DATA_WIDTH_8_BIT;
63 tempValue |= value[SHT30_HUM_VALUE_INDEX_FOUR];
64
65 rawData->humidity = ((SHT30_HUM_SLOPE * tempValue) / SHT30_HUM_RESOLUTION);
66
67 if (value[SHT30_HUM_VALUE_INDEX_FIVE] != \
68 Sht30CalcCrc8(value + SHT30_HUM_VALUE_INDEX_THREE, SHT30_HUM_CRC8_LEN)) {
69 HDF_LOGE("%s: Calc humidity crc8 failed!", __func__);
70 return HDF_FAILURE;
71 }
72
73 return HDF_SUCCESS;
74 }
75
ReadSht30Data(struct SensorCfgData * data)76 static int32_t ReadSht30Data(struct SensorCfgData *data)
77 {
78 int32_t ret;
79 static int32_t humidity;
80 struct HumidityData rawData = { 0 };
81 OsalTimespec time;
82 struct SensorReportEvent event;
83
84 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
85 (void)memset_s(&event, sizeof(event), 0, sizeof(event));
86
87 if (OsalGetTime(&time) != HDF_SUCCESS) {
88 HDF_LOGE("%s: Get time failed", __func__);
89 return HDF_FAILURE;
90 }
91
92 event.timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT;
93
94 ret = ReadSht30RawData(data, &rawData, &event.timestamp);
95 if (ret != HDF_SUCCESS) {
96 HDF_LOGE("%s: SHT30 read raw data failed", __func__);
97 return HDF_FAILURE;
98 }
99
100 humidity = rawData.humidity;
101
102 event.sensorId = SENSOR_TAG_HUMIDITY;
103 event.mode = SENSOR_WORK_MODE_REALTIME;
104 event.dataLen = sizeof(humidity);
105 event.data = (uint8_t *)&humidity;
106 ret = ReportSensorEvent(&event);
107 if (ret != HDF_SUCCESS) {
108 HDF_LOGE("%s: report data failed", __func__);
109 }
110
111 return ret;
112 }
113
InitSht30(struct SensorCfgData * data)114 static int32_t InitSht30(struct SensorCfgData *data)
115 {
116 int32_t ret;
117
118 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
119 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
120 if (ret != HDF_SUCCESS) {
121 HDF_LOGE("%s: sensor init config failed", __func__);
122 return HDF_FAILURE;
123 }
124
125 return HDF_SUCCESS;
126 }
127
DispatchSht30(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)128 static int32_t DispatchSht30(struct HdfDeviceIoClient *client,
129 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
130 {
131 (void)client;
132 (void)cmd;
133 (void)data;
134 (void)reply;
135
136 return HDF_SUCCESS;
137 }
138
Sht30BindDriver(struct HdfDeviceObject * device)139 static int32_t Sht30BindDriver(struct HdfDeviceObject *device)
140 {
141 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
142
143 struct Sht30DrvData *drvData = (struct Sht30DrvData *)OsalMemCalloc(sizeof(*drvData));
144 if (drvData == NULL) {
145 HDF_LOGE("%s: malloc drv data fail", __func__);
146 return HDF_ERR_MALLOC_FAIL;
147 }
148
149 drvData->ioService.Dispatch = DispatchSht30;
150 drvData->device = device;
151 device->service = &drvData->ioService;
152 g_sht30DrvData = drvData;
153
154 return HDF_SUCCESS;
155 }
156
Sht30InitDriver(struct HdfDeviceObject * device)157 static int32_t Sht30InitDriver(struct HdfDeviceObject *device)
158 {
159 int32_t ret;
160 struct HumidityOpsCall ops;
161
162 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
163 struct Sht30DrvData *drvData = (struct Sht30DrvData *)device->service;
164 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
165
166 drvData->sensorCfg = HumidityCreateCfgData(device->property);
167 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
168 HDF_LOGE("%s: Creating humidity cfg failed because detection failed", __func__);
169 return HDF_ERR_NOT_SUPPORT;
170 }
171
172 ops.Init = NULL;
173 ops.ReadData = ReadSht30Data;
174 ret = HumidityRegisterChipOps(&ops);
175 if (ret != HDF_SUCCESS) {
176 HDF_LOGE("%s: Register humidity failed", __func__);
177 return HDF_FAILURE;
178 }
179
180 ret = InitSht30(drvData->sensorCfg);
181 if (ret != HDF_SUCCESS) {
182 HDF_LOGE("%s: Init SHT30 humidity sensor failed", __func__);
183 return HDF_FAILURE;
184 }
185
186 return HDF_SUCCESS;
187 }
188
Sht30ReleaseDriver(struct HdfDeviceObject * device)189 static void Sht30ReleaseDriver(struct HdfDeviceObject *device)
190 {
191 CHECK_NULL_PTR_RETURN(device);
192
193 struct Sht30DrvData *drvData = (struct Sht30DrvData *)device->service;
194 CHECK_NULL_PTR_RETURN(drvData);
195
196 if (drvData->sensorCfg != NULL) {
197 HumidityReleaseCfgData(drvData->sensorCfg);
198 drvData->sensorCfg = NULL;
199 }
200 OsalMemFree(drvData);
201 }
202
203 struct HdfDriverEntry g_humiditySht30DevEntry = {
204 .moduleVersion = 1,
205 .moduleName = "HDF_SENSOR_HUMIDITY_SHT30",
206 .Bind = Sht30BindDriver,
207 .Init = Sht30InitDriver,
208 .Release = Sht30ReleaseDriver,
209 };
210
211 HDF_INIT(g_humiditySht30DevEntry);
212