1 /*
2 * Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT we_wsen_hids_2525020210002
8
9 #include <stdlib.h>
10
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/logging/log.h>
14
15 #include "wsen_hids_2525020210002.h"
16
17 LOG_MODULE_REGISTER(WSEN_HIDS_2525020210002, CONFIG_SENSOR_LOG_LEVEL);
18
19 static const hids_measureCmd_t precision_cmds[] = {HIDS_MEASURE_LPM, HIDS_MEASURE_MPM,
20 HIDS_MEASURE_HPM};
21
22 static const hids_measureCmd_t heater_cmds[] = {HIDS_HEATER_200_MW_01_S, HIDS_HEATER_200_MW_100_MS,
23 HIDS_HEATER_110_MW_01_S, HIDS_HEATER_110_MW_100_MS,
24 HIDS_HEATER_20_MW_01_S, HIDS_HEATER_20_MW_100_MS};
25
hids_2525020210002_sample_fetch(const struct device * dev,enum sensor_channel chan)26 static int hids_2525020210002_sample_fetch(const struct device *dev, enum sensor_channel chan)
27 {
28 struct hids_2525020210002_data *data = dev->data;
29
30 hids_measureCmd_t cmd;
31
32 int32_t raw_temperature;
33 int32_t raw_humidity;
34
35 switch (chan) {
36 case SENSOR_CHAN_ALL:
37 case SENSOR_CHAN_AMBIENT_TEMP:
38 case SENSOR_CHAN_HUMIDITY:
39 break;
40 default:
41 LOG_ERR("Fetching is not supported on channel %d.", chan);
42 return -ENOTSUP;
43 }
44
45 if (data->sensor_precision == hids_2525020210002_precision_High &&
46 data->sensor_heater != hids_2525020210002_heater_Off) {
47 cmd = heater_cmds[data->sensor_heater - 1];
48 } else {
49 cmd = precision_cmds[data->sensor_precision];
50 }
51
52 if (HIDS_Sensor_Measure_Raw(&data->sensor_interface, cmd, &raw_temperature,
53 &raw_humidity) != WE_SUCCESS) {
54 LOG_ERR("Failed to fetch data sample");
55 return -EIO;
56 }
57
58 switch (chan) {
59 case SENSOR_CHAN_ALL:
60 data->temperature = raw_temperature;
61 data->humidity = raw_humidity;
62 break;
63 case SENSOR_CHAN_AMBIENT_TEMP:
64 data->temperature = raw_temperature;
65 break;
66 case SENSOR_CHAN_HUMIDITY:
67 data->humidity = raw_humidity;
68 break;
69 default:
70 return -ENOTSUP;
71 }
72
73 return 0;
74 }
75
hids_2525020210002_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)76 static int hids_2525020210002_channel_get(const struct device *dev, enum sensor_channel chan,
77 struct sensor_value *val)
78 {
79 struct hids_2525020210002_data *data = dev->data;
80
81 switch (chan) {
82 case SENSOR_CHAN_AMBIENT_TEMP:
83 val->val1 = data->temperature / 1000;
84 val->val2 = ((int32_t)data->temperature % 1000) * (1000000 / 1000);
85 break;
86 case SENSOR_CHAN_HUMIDITY:
87 val->val1 = data->humidity / 1000;
88 val->val2 = ((int32_t)data->humidity % 1000) * (1000000 / 1000);
89 break;
90 default:
91 LOG_ERR("Channel not supported %d", chan);
92 return -ENOTSUP;
93 }
94
95 return 0;
96 }
97
98 /* Set precision configuration. */
hids_2525020210002_precision_set(const struct device * dev,const struct sensor_value * precision)99 static int hids_2525020210002_precision_set(const struct device *dev,
100 const struct sensor_value *precision)
101 {
102 struct hids_2525020210002_data *data = dev->data;
103
104 if (precision->val1 < hids_2525020210002_precision_Low ||
105 precision->val1 > hids_2525020210002_precision_High || precision->val2 != 0) {
106 LOG_ERR("Bad precision configuration %d", precision->val1);
107 return -EINVAL;
108 }
109
110 data->sensor_precision = (hids_2525020210002_precision_t)precision->val1;
111
112 return 0;
113 }
114
115 /* Set heater option. */
hids_2525020210002_heater_set(const struct device * dev,const struct sensor_value * heater)116 static int hids_2525020210002_heater_set(const struct device *dev,
117 const struct sensor_value *heater)
118 {
119 struct hids_2525020210002_data *data = dev->data;
120
121 if (heater->val1 < hids_2525020210002_heater_Off ||
122 heater->val1 > hids_2525020210002_heater_On_20mW_100ms || heater->val2 != 0) {
123 LOG_ERR("Bad heater option %d", heater->val1);
124 return -EINVAL;
125 }
126
127 data->sensor_heater = (hids_2525020210002_heater_t)heater->val1;
128
129 return 0;
130 }
131
hids_2525020210002_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)132 static int hids_2525020210002_attr_set(const struct device *dev, enum sensor_channel chan,
133 enum sensor_attribute attr, const struct sensor_value *val)
134 {
135
136 if (chan != SENSOR_CHAN_ALL) {
137 LOG_WRN("attr_set() is not supported on channel %d.", chan);
138 return -ENOTSUP;
139 }
140
141 switch ((int)attr) {
142 case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION:
143 return hids_2525020210002_precision_set(dev, val);
144 case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER:
145 return hids_2525020210002_heater_set(dev, val);
146 default:
147 LOG_ERR("Operation not supported.");
148 return -ENOTSUP;
149 }
150
151 return 0;
152 }
153
hids_2525020210002_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)154 static int hids_2525020210002_attr_get(const struct device *dev, enum sensor_channel chan,
155 enum sensor_attribute attr, struct sensor_value *val)
156 {
157 struct hids_2525020210002_data *data = dev->data;
158
159 if (chan != SENSOR_CHAN_ALL) {
160 LOG_WRN("attr_get() is not supported on channel %d.", chan);
161 return -ENOTSUP;
162 }
163
164 if (val == NULL) {
165 LOG_WRN("address of passed value is NULL.");
166 return -EFAULT;
167 }
168
169 switch ((int)attr) {
170 case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION:
171 val->val1 = data->sensor_precision;
172 val->val2 = 0;
173 break;
174 case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER:
175 val->val1 = data->sensor_heater;
176 val->val2 = 0;
177 break;
178 default:
179 LOG_ERR("Operation not supported.");
180 return -ENOTSUP;
181 }
182
183 return 0;
184 }
185
186 static DEVICE_API(sensor, hids_2525020210002_driver_api) = {
187 .attr_set = hids_2525020210002_attr_set,
188 .attr_get = hids_2525020210002_attr_get,
189 .sample_fetch = hids_2525020210002_sample_fetch,
190 .channel_get = hids_2525020210002_channel_get,
191 };
192
hids_2525020210002_init(const struct device * dev)193 static int hids_2525020210002_init(const struct device *dev)
194 {
195 const struct hids_2525020210002_config *const config = dev->config;
196 struct hids_2525020210002_data *data = dev->data;
197 struct sensor_value precision, heater;
198
199 /* Initialize WE sensor interface */
200 HIDS_Get_Default_Interface(&data->sensor_interface);
201 data->sensor_interface.interfaceType = WE_i2c;
202 if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) {
203 LOG_ERR("I2C bus device not ready");
204 return -ENODEV;
205 }
206 data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
207
208 /* First communication test - check device ID */
209 if (HIDS_Sensor_Init(&data->sensor_interface) != WE_SUCCESS) {
210 LOG_ERR("Failed to read device ID.");
211 return -EIO;
212 }
213
214 precision.val1 = config->precision;
215 precision.val2 = 0;
216
217 if (hids_2525020210002_precision_set(dev, &precision) < 0) {
218 LOG_ERR("Failed to set precision configuration.");
219 return -EIO;
220 }
221
222 heater.val1 = config->heater;
223 heater.val2 = 0;
224
225 if (hids_2525020210002_heater_set(dev, &heater) < 0) {
226 LOG_ERR("Failed to set heater option.");
227 return -EIO;
228 }
229
230 return 0;
231 }
232
233 /*
234 * Main instantiation macro.
235 */
236 #define HIDS_2525020210002_DEFINE(inst) \
237 static struct hids_2525020210002_data hids_2525020210002_data_##inst; \
238 static const struct hids_2525020210002_config hids_2525020210002_config_##inst = { \
239 .bus_cfg = {.i2c = I2C_DT_SPEC_INST_GET(inst)}, \
240 .precision = (hids_2525020210002_precision_t)(DT_INST_ENUM_IDX(inst, precision)), \
241 .heater = (hids_2525020210002_heater_t)(DT_INST_ENUM_IDX(inst, heater)), \
242 }; \
243 SENSOR_DEVICE_DT_INST_DEFINE(inst, hids_2525020210002_init, NULL, \
244 &hids_2525020210002_data_##inst, \
245 &hids_2525020210002_config_##inst, POST_KERNEL, \
246 CONFIG_SENSOR_INIT_PRIORITY, &hids_2525020210002_driver_api);
247
248 DT_INST_FOREACH_STATUS_OKAY(HIDS_2525020210002_DEFINE)
249