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