]> sigrok.org Git - libsigrok.git/blame - src/hardware/devantech-eth008/api.c
raspberrypi-pico: Fix serial comm parameters
[libsigrok.git] / src / hardware / devantech-eth008 / api.c
CommitLineData
c12ca361
GS
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2023 Gerhard Sittig <gerhard.sittig@gmx.net>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
8712c783
GS
20#include "config.h"
21
22#include <string.h>
23
c12ca361
GS
24#include "protocol.h"
25
8712c783 26#define VENDOR_TEXT "Devantech"
c12ca361 27
8712c783
GS
28static const uint32_t scanopts[] = {
29 SR_CONF_CONN,
30};
31
32static const uint32_t drvopts[] = {
33 SR_CONF_MULTIPLEXER,
34};
c12ca361 35
8712c783
GS
36static const uint32_t devopts[] = {
37 SR_CONF_CONN | SR_CONF_GET,
38 SR_CONF_ENABLED | SR_CONF_SET, /* Enable/disable all relays at once. */
39};
c12ca361 40
8712c783
GS
41static const uint32_t devopts_cg_do[] = {
42 SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
43};
44
0220481e
GS
45static const uint32_t devopts_cg_di[] = {
46 SR_CONF_ENABLED | SR_CONF_GET,
47};
48
8712c783
GS
49static const uint32_t devopts_cg_ai[] = {
50 SR_CONF_VOLTAGE | SR_CONF_GET,
51};
52
53static const struct devantech_eth008_model models[] = {
0220481e
GS
54 { 18, "ETH002", 2, 0, 0, 0, 1, 0, },
55 { 19, "ETH008", 8, 0, 0, 0, 1, 0, },
56 { 20, "ETH484", 16, 8, 4, 0, 2, 0x00f0, },
57 { 21, "ETH8020", 20, 8, 8, 0, 3, 0, },
8712c783 58};
c12ca361 59
8712c783
GS
60static const struct devantech_eth008_model *find_model(uint8_t code)
61{
62 size_t idx;
63 const struct devantech_eth008_model *check;
64
65 for (idx = 0; idx < ARRAY_SIZE(models); idx++) {
66 check = &models[idx];
67 if (check->code != code)
68 continue;
69 return check;
70 }
c12ca361 71
8712c783 72 return NULL;
c12ca361
GS
73}
74
8712c783
GS
75static struct sr_dev_driver devantech_eth008_driver_info;
76
77static struct sr_dev_inst *probe_device_conn(const char *conn)
c12ca361 78{
8712c783
GS
79 struct sr_dev_inst *sdi;
80 struct dev_context *devc;
81 struct sr_serial_dev_inst *ser;
82 uint8_t code, hwver, fwver;
83 const struct devantech_eth008_model *model;
84 gboolean has_serno_cmd;
85 char snr_txt[16];
86 struct channel_group_context *cgc;
0220481e 87 size_t ch_idx, nr, do_idx, di_idx, ai_idx;
8712c783
GS
88 struct sr_channel_group *cg;
89 char cg_name[24];
90 int ret;
c12ca361 91
8712c783
GS
92 sdi = g_malloc0(sizeof(*sdi));
93 devc = g_malloc0(sizeof(*devc));
94 sdi->priv = devc;
95 ser = sr_serial_dev_inst_new(conn, NULL);
96 sdi->conn = ser;
97 if (!ser)
98 goto probe_fail;
99 ret = serial_open(ser, 0);
100 if (ret != SR_OK)
101 goto probe_fail;
102
103 ret = devantech_eth008_get_model(ser, &code, &hwver, &fwver);
104 if (ret != SR_OK)
105 goto probe_fail;
106 model = find_model(code);
107 if (!model) {
108 sr_err("Unknown model ID 0x%02x (HW %u, FW %u).",
109 code, hwver, fwver);
110 goto probe_fail;
111 }
112 devc->model_code = code;
113 devc->hardware_version = hwver;
114 devc->firmware_version = fwver;
115 devc->model = model;
116 sdi->vendor = g_strdup(VENDOR_TEXT);
117 sdi->model = g_strdup(model->name);
118 sdi->version = g_strdup_printf("HW%u FW%u", hwver, fwver);
119 sdi->connection_id = g_strdup(conn);
120 sdi->driver = &devantech_eth008_driver_info;
121 sdi->inst_type = SR_INST_SERIAL;
122
123 has_serno_cmd = TRUE;
124 if (model->min_serno_fw && fwver < model->min_serno_fw)
125 has_serno_cmd = FALSE;
126 if (has_serno_cmd) {
127 snr_txt[0] = '\0';
128 ret = devantech_eth008_get_serno(ser,
129 snr_txt, sizeof(snr_txt));
130 if (ret != SR_OK)
131 goto probe_fail;
132 sdi->serial_num = g_strdup(snr_txt);
133 }
c12ca361 134
8712c783
GS
135 ch_idx = 0;
136 devc->mask_do = (1UL << devc->model->ch_count_do) - 1;
0220481e 137 devc->mask_do &= ~devc->model->mask_do_missing;
8712c783
GS
138 for (do_idx = 0; do_idx < devc->model->ch_count_do; do_idx++) {
139 nr = do_idx + 1;
0220481e 140 if (devc->model->mask_do_missing & (1UL << do_idx))
6af128b6 141 continue;
8712c783
GS
142 snprintf(cg_name, sizeof(cg_name), "DO%zu", nr);
143 cgc = g_malloc0(sizeof(*cgc));
144 cg = sr_channel_group_new(sdi, cg_name, cgc);
145 cgc->index = do_idx;
146 cgc->number = nr;
147 cgc->ch_type = DV_CH_DIGITAL_OUTPUT;
148 (void)cg;
149 ch_idx++;
150 }
0220481e
GS
151 for (di_idx = 0; di_idx < devc->model->ch_count_di; di_idx++) {
152 nr = di_idx + 1;
153 snprintf(cg_name, sizeof(cg_name), "DI%zu", nr);
154 cgc = g_malloc0(sizeof(*cgc));
155 cg = sr_channel_group_new(sdi, cg_name, cgc);
156 cgc->index = di_idx;
157 cgc->number = nr;
158 cgc->ch_type = DV_CH_DIGITAL_INPUT;
159 (void)cg;
160 ch_idx++;
161 }
162 for (ai_idx = 0; ai_idx < devc->model->ch_count_ai; ai_idx++) {
163 nr = ai_idx + 1;
164 snprintf(cg_name, sizeof(cg_name), "AI%zu", nr);
165 cgc = g_malloc0(sizeof(*cgc));
166 cg = sr_channel_group_new(sdi, cg_name, cgc);
167 cgc->index = ai_idx;
168 cgc->number = nr;
169 cgc->ch_type = DV_CH_ANALOG_INPUT;
170 (void)cg;
171 ch_idx++;
172 }
8712c783
GS
173 if (1) {
174 /* Create an analog channel for the supply voltage. */
175 snprintf(cg_name, sizeof(cg_name), "Vsupply");
176 cgc = g_malloc0(sizeof(*cgc));
177 cg = sr_channel_group_new(sdi, cg_name, cgc);
178 cgc->index = 0;
179 cgc->number = 0;
180 cgc->ch_type = DV_CH_SUPPLY_VOLTAGE;
181 (void)cg;
182 ch_idx++;
183 }
184
185 return sdi;
186
187probe_fail:
188 if (ser) {
189 serial_close(ser);
190 sr_serial_dev_inst_free(ser);
191 }
192 if (devc) {
193 g_free(devc);
194 }
195 if (sdi) {
196 sdi->priv = NULL;
197 sr_dev_inst_free(sdi);
198 sdi = NULL;
199 }
200 return sdi;
c12ca361
GS
201}
202
8712c783 203static GSList *scan(struct sr_dev_driver *di, GSList *options)
c12ca361 204{
8712c783
GS
205 struct drv_context *drvc;
206 const char *conn;
207 GSList *devices;
208 struct sr_dev_inst *sdi;
c12ca361 209
8712c783
GS
210 drvc = di->context;
211 drvc->instances = NULL;
c12ca361 212
8712c783
GS
213 /* A conn= spec is required for the TCP attached device. */
214 conn = NULL;
215 (void)sr_serial_extract_options(options, &conn, NULL);
216 if (!conn || !*conn)
217 return NULL;
218
219 devices = NULL;
220 sdi = probe_device_conn(conn);
221 if (sdi)
222 devices = g_slist_append(devices, sdi);
223
224 return std_scan_complete(di, devices);
c12ca361
GS
225}
226
227static int config_get(uint32_t key, GVariant **data,
228 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
229{
8712c783
GS
230 struct channel_group_context *cgc;
231 gboolean on;
232 uint16_t vin;
233 double vsupply;
c12ca361
GS
234 int ret;
235
8712c783
GS
236 if (!cg) {
237 switch (key) {
238 case SR_CONF_CONN:
239 if (!sdi->connection_id)
240 return SR_ERR_NA;
241 *data = g_variant_new_string(sdi->connection_id);
242 return SR_OK;
243 default:
244 return SR_ERR_NA;
245 }
246 }
c12ca361 247
8712c783
GS
248 cgc = cg->priv;
249 if (!cgc)
250 return SR_ERR_NA;
c12ca361 251 switch (key) {
8712c783
GS
252 case SR_CONF_ENABLED:
253 if (cgc->ch_type == DV_CH_DIGITAL_OUTPUT) {
254 ret = devantech_eth008_query_do(sdi, cg, &on);
255 if (ret != SR_OK)
256 return ret;
257 *data = g_variant_new_boolean(on);
258 return SR_OK;
259 }
0220481e
GS
260 if (cgc->ch_type == DV_CH_DIGITAL_INPUT) {
261 ret = devantech_eth008_query_di(sdi, cg, &on);
262 if (ret != SR_OK)
263 return ret;
264 *data = g_variant_new_boolean(on);
265 return SR_OK;
266 }
8712c783
GS
267 return SR_ERR_NA;
268 case SR_CONF_VOLTAGE:
0220481e
GS
269 if (cgc->ch_type == DV_CH_ANALOG_INPUT) {
270 ret = devantech_eth008_query_ai(sdi, cg, &vin);
271 if (ret != SR_OK)
272 return ret;
273 *data = g_variant_new_uint32(vin);
274 return SR_OK;
275 }
8712c783
GS
276 if (cgc->ch_type == DV_CH_SUPPLY_VOLTAGE) {
277 ret = devantech_eth008_query_supply(sdi, cg, &vin);
278 if (ret != SR_OK)
279 return ret;
280 vsupply = vin;
281 vsupply /= 1000.;
282 *data = g_variant_new_double(vsupply);
283 return SR_OK;
284 }
285 return SR_ERR_NA;
c12ca361
GS
286 default:
287 return SR_ERR_NA;
288 }
c12ca361
GS
289}
290
291static int config_set(uint32_t key, GVariant *data,
292 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
293{
8712c783
GS
294 struct channel_group_context *cgc;
295 gboolean on;
296
297 if (!cg) {
298 switch (key) {
299 case SR_CONF_ENABLED:
300 /* Enable/disable all channels at the same time. */
301 on = g_variant_get_boolean(data);
302 return devantech_eth008_setup_do(sdi, cg, on);
303 default:
304 return SR_ERR_NA;
305 }
306 }
c12ca361 307
8712c783
GS
308 cgc = cg->priv;
309 if (!cgc)
310 return SR_ERR_NA;
c12ca361 311 switch (key) {
8712c783
GS
312 case SR_CONF_ENABLED:
313 if (cgc->ch_type != DV_CH_DIGITAL_OUTPUT)
314 return SR_ERR_NA;
315 on = g_variant_get_boolean(data);
316 return devantech_eth008_setup_do(sdi, cg, on);
c12ca361 317 default:
8712c783 318 return SR_ERR_NA;
c12ca361
GS
319 }
320
8712c783
GS
321 /* XXX Is this actually UNREACH? */
322 return SR_OK;
c12ca361
GS
323}
324
325static int config_list(uint32_t key, GVariant **data,
326 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
327{
8712c783
GS
328 struct channel_group_context *cgc;
329
330 if (!cg) {
331 switch (key) {
332 case SR_CONF_SCAN_OPTIONS:
333 case SR_CONF_DEVICE_OPTIONS:
334 return STD_CONFIG_LIST(key, data, sdi, cg,
335 scanopts, drvopts, devopts);
336 default:
337 return SR_ERR_NA;
338 }
339 }
c12ca361 340
8712c783
GS
341 cgc = cg->priv;
342 if (!cgc)
343 return SR_ERR_NA;
c12ca361 344 switch (key) {
8712c783
GS
345 case SR_CONF_DEVICE_OPTIONS:
346 if (cgc->ch_type == DV_CH_DIGITAL_OUTPUT) {
347 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_do));
348 return SR_OK;
349 }
0220481e
GS
350 if (cgc->ch_type == DV_CH_DIGITAL_INPUT) {
351 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_di));
352 return SR_OK;
353 }
354 if (cgc->ch_type == DV_CH_ANALOG_INPUT) {
355 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_ai));
356 return SR_OK;
357 }
8712c783
GS
358 if (cgc->ch_type == DV_CH_SUPPLY_VOLTAGE) {
359 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_ai));
360 return SR_OK;
361 }
362 return SR_ERR_NA;
c12ca361
GS
363 default:
364 return SR_ERR_NA;
365 }
c12ca361
GS
366}
367
368static struct sr_dev_driver devantech_eth008_driver_info = {
369 .name = "devantech-eth008",
370 .longname = "Devantech ETH008",
371 .api_version = 1,
372 .init = std_init,
373 .cleanup = std_cleanup,
374 .scan = scan,
375 .dev_list = std_dev_list,
376 .dev_clear = std_dev_clear,
377 .config_get = config_get,
378 .config_set = config_set,
379 .config_list = config_list,
8712c783
GS
380 .dev_open = std_serial_dev_open,
381 .dev_close = std_serial_dev_close,
382 .dev_acquisition_start = std_dummy_dev_acquisition_start,
383 .dev_acquisition_stop = std_dummy_dev_acquisition_stop,
c12ca361
GS
384 .context = NULL,
385};
386SR_REGISTER_DEV_DRIVER(devantech_eth008_driver_info);