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_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_temperature_driver.h"
16
17 #define HDF_LOG_TAG hdf_sensor_temperature_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_TEMP_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_TEMP_CRC8_MASK) ? \
34 ((value << SHT30_TEMP_SHFIT_1_BIT) ^ SHT30_TEMP_CRC8_POLYNOMIAL) : (value << SHT30_TEMP_SHFIT_1_BIT);
35 }
36 }
37
38 return value;
39 }
40
ReadSht30RawData(struct SensorCfgData * data,struct TemperatureData * rawData,uint64_t * timestamp)41 static int32_t ReadSht30RawData(struct SensorCfgData *data, struct TemperatureData *rawData, uint64_t *timestamp)
42 {
43 OsalTimespec time;
44 uint8_t value[SHT30_TEMP_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_TEMP_DATA_ADDR, value, sizeof(value));
59 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
60
61 tempValue = value[SHT30_TEMP_VALUE_IDX_ZERO];
62 tempValue <<= SENSOR_DATA_WIDTH_8_BIT;
63 tempValue |= value[SHT30_TEMP_VALUE_IDX_ONE];
64
65 rawData->temperature = (SHT30_TEMP_CONSATNT + ((SHT30_TEMP_SLOPE * tempValue) / 0xFFFF));
66
67 if (value[SHT30_TEMP_VALUE_IDX_TWO] != Sht30CalcCrc8(value, SHT30_TEMP_CRC8_LEN)) {
68 HDF_LOGE("%s: Calc temperature crc8 failed!", __func__);
69 return HDF_FAILURE;
70 }
71
72 return HDF_SUCCESS;
73 }
74
ReadSht30Data(struct SensorCfgData * data)75 static int32_t ReadSht30Data(struct SensorCfgData *data)
76 {
77 int32_t ret;
78 static int32_t temperature;
79 struct TemperatureData 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 = ReadSht30RawData(data, &rawData, &event.timestamp);
94 if (ret != HDF_SUCCESS) {
95 HDF_LOGE("%s: SHT30 read raw data failed", __func__);
96 return HDF_FAILURE;
97 }
98
99 temperature = rawData.temperature;
100
101 event.sensorId = SENSOR_TAG_TEMPERATURE;
102 event.mode = SENSOR_WORK_MODE_REALTIME;
103 event.dataLen = sizeof(temperature);
104 event.data = (uint8_t *)&temperature;
105 ret = ReportSensorEvent(&event);
106 if (ret != HDF_SUCCESS) {
107 HDF_LOGE("%s: report data failed", __func__);
108 }
109
110 return ret;
111 }
112
InitSht30(struct SensorCfgData * data)113 static int32_t InitSht30(struct SensorCfgData *data)
114 {
115 int32_t ret;
116
117 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
118 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
119 if (ret != HDF_SUCCESS) {
120 HDF_LOGE("%s: sensor init config failed", __func__);
121 return HDF_FAILURE;
122 }
123
124 return HDF_SUCCESS;
125 }
126
DispatchSht30(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)127 static int32_t DispatchSht30(struct HdfDeviceIoClient *client,
128 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
129 {
130 (void)client;
131 (void)cmd;
132 (void)data;
133 (void)reply;
134
135 return HDF_SUCCESS;
136 }
137
Sht30BindDriver(struct HdfDeviceObject * device)138 static int32_t Sht30BindDriver(struct HdfDeviceObject *device)
139 {
140 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
141
142 struct Sht30DrvData *drvData = (struct Sht30DrvData *)OsalMemCalloc(sizeof(*drvData));
143 if (drvData == NULL) {
144 HDF_LOGE("%s: malloc drv data fail", __func__);
145 return HDF_ERR_MALLOC_FAIL;
146 }
147
148 drvData->ioService.Dispatch = DispatchSht30;
149 drvData->device = device;
150 device->service = &drvData->ioService;
151 g_sht30DrvData = drvData;
152
153 return HDF_SUCCESS;
154 }
155
Sht30InitDriver(struct HdfDeviceObject * device)156 static int32_t Sht30InitDriver(struct HdfDeviceObject *device)
157 {
158 int32_t ret;
159 struct TemperatureOpsCall ops;
160
161 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
162 struct Sht30DrvData *drvData = (struct Sht30DrvData *)device->service;
163 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
164
165 drvData->sensorCfg = TemperatureCreateCfgData(device->property);
166 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
167 HDF_LOGE("%s: Creating temperature cfg failed because detection failed", __func__);
168 return HDF_ERR_NOT_SUPPORT;
169 }
170
171 ops.Init = NULL;
172 ops.ReadData = ReadSht30Data;
173 ret = TemperatureRegisterChipOps(&ops);
174 if (ret != HDF_SUCCESS) {
175 HDF_LOGE("%s: Register temperature failed", __func__);
176 return HDF_FAILURE;
177 }
178
179 ret = InitSht30(drvData->sensorCfg);
180 if (ret != HDF_SUCCESS) {
181 HDF_LOGE("%s: Init SHT30 temperature sensor failed", __func__);
182 return HDF_FAILURE;
183 }
184
185 return HDF_SUCCESS;
186 }
187
Sht30ReleaseDriver(struct HdfDeviceObject * device)188 static void Sht30ReleaseDriver(struct HdfDeviceObject *device)
189 {
190 CHECK_NULL_PTR_RETURN(device);
191
192 struct Sht30DrvData *drvData = (struct Sht30DrvData *)device->service;
193 CHECK_NULL_PTR_RETURN(drvData);
194
195 if (drvData->sensorCfg != NULL) {
196 TemperatureReleaseCfgData(drvData->sensorCfg);
197 drvData->sensorCfg = NULL;
198 }
199 OsalMemFree(drvData);
200 }
201
202 struct HdfDriverEntry g_temperatureSht30DevEntry = {
203 .moduleVersion = 1,
204 .moduleName = "HDF_SENSOR_TEMPERATURE_SHT30",
205 .Bind = Sht30BindDriver,
206 .Init = Sht30InitDriver,
207 .Release = Sht30ReleaseDriver,
208 };
209
210 HDF_INIT(g_temperatureSht30DevEntry);
211