]> sigrok.org Git - libsigrok.git/blame - src/hardware/uni-t-ut181a/api.c
uni-t-ut181a: silence compiler warning, use of uninitialized variable
[libsigrok.git] / src / hardware / uni-t-ut181a / api.c
CommitLineData
3094e9d8
GS
1/*
2 * This file is part of the libsigrok project.
3 *
ebc51109 4 * Copyright (C) 2019-2020 Gerhard Sittig <gerhard.sittig@gmx.net>
3094e9d8
GS
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
20#include <config.h>
21#include "protocol.h"
22
ebc51109
GS
23static const uint32_t scanopts[] = {
24 SR_CONF_CONN,
25 SR_CONF_SERIALCOMM,
26};
3094e9d8 27
ebc51109
GS
28static const uint32_t drvopts[] = {
29 SR_CONF_MULTIMETER,
30 SR_CONF_THERMOMETER, /* Supports two temperature probes and diffs. */
31};
3094e9d8 32
ebc51109
GS
33static const uint32_t devopts[] = {
34 SR_CONF_CONN | SR_CONF_GET,
35 SR_CONF_CONTINUOUS,
36 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
37 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
38 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
39 SR_CONF_DATA_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
cbfaf5e0
GS
40 SR_CONF_DATALOG | SR_CONF_GET | SR_CONF_SET,
41 /* TODO SR_CONF_DATALOG is bool only, how to setup interval/duration? */
ebc51109
GS
42 SR_CONF_MEASURED_QUANTITY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43 SR_CONF_RANGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
44};
3094e9d8 45
ebc51109
GS
46static const char *channel_names[] = {
47 [UT181A_CH_MAIN] = "P1",
48 [UT181A_CH_AUX1] = "P2",
49 [UT181A_CH_AUX2] = "P3",
50 [UT181A_CH_AUX3] = "P4",
51 [UT181A_CH_BAR] = "bar",
52#if UT181A_WITH_TIMESTAMP
53 [UT181A_CH_TIME] = "TS",
54#endif
55};
56
57/*
58 * (Re-)retrieve the list of recordings and their names. These can change
59 * without the driver's being aware, the set is under user control.
60 *
61 * TODO Need to re-allocate the list of recording names when a larger
62 * recordings count is seen than previously allocated? This implementation
63 * assumes a known maximum number of recordings, the manual is vague on
64 * these limits.
65 */
66static int ut181a_update_recordings(const struct sr_dev_inst *sdi)
67{
68 struct dev_context *devc;
69 struct sr_serial_dev_inst *serial;
70 size_t rec_count, rec_idx;
71 int ret;
3094e9d8 72
ebc51109
GS
73 if (!sdi)
74 return SR_ERR_ARG;
75 devc = sdi->priv;
76 serial = sdi->conn;
77
78 ret = ut181a_send_cmd_get_recs_count(serial);
79 if (ret < 0)
80 return ret;
81 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
82 FALSE, TRUE, FALSE, FALSE);
83 if (ret < 0)
84 return ret;
85 ret = ut181a_waitfor_response(sdi, 100);
86 if (ret < 0)
87 return ret;
88
89 rec_count = devc->wait_state.data_value;
90 if (rec_count > ARRAY_SIZE(devc->record_names))
91 rec_count = ARRAY_SIZE(devc->record_names);
92 for (rec_idx = 0; rec_idx < rec_count; rec_idx++) {
93 devc->info.rec_info.rec_idx = rec_idx;
94 ret = ut181a_send_cmd_get_rec_info(serial, rec_idx);
95 if (ret < 0)
96 return ret;
97 ret = ut181a_configure_waitfor(devc,
98 FALSE, CMD_CODE_GET_REC_INFO, 0,
99 FALSE, FALSE, FALSE, FALSE);
100 if (ret < 0)
101 return ret;
102 ret = ut181a_waitfor_response(sdi, 100);
103 if (ret < 0)
104 return ret;
105 }
106 devc->record_count = rec_count;
107 devc->data_source_count = DATA_SOURCE_REC_FIRST + devc->record_count;
3094e9d8 108
ebc51109 109 return SR_OK;
3094e9d8
GS
110}
111
ebc51109
GS
112/*
113 * Retrieve the device's current state. Run monitor mode for some time
114 * until the 'mode' (meter's current function) became available. There
115 * is no other way of querying the meter's current state.
116 */
117static int ut181a_query_initial_state(struct sr_dev_inst *sdi, int timeout_ms)
3094e9d8 118{
ebc51109
GS
119 struct dev_context *devc;
120 struct sr_serial_dev_inst *serial;
121 gint64 deadline;
122 int ret;
3094e9d8 123
ebc51109
GS
124 if (!sdi)
125 return SR_ERR_ARG;
126 devc = sdi->priv;
127 serial = sdi->conn;
128
129 devc->info.meas_head.mode = 0;
130 ret = ut181a_send_cmd_monitor(serial, TRUE);
131 if (ret < 0)
132 return ret;
133 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
134 TRUE, FALSE, FALSE, FALSE);
135 if (ret < 0)
136 return ret;
137 deadline = g_get_monotonic_time();
138 deadline += timeout_ms * 1000;
139 while (1) {
140 ret = ut181a_waitfor_response(sdi, 100);
141 if (ret < 0)
142 return ret;
143 if (devc->info.meas_head.mode)
144 break;
145 if (g_get_monotonic_time() >= deadline)
146 return SR_ERR_DATA;
147 }
148 (void)ut181a_send_cmd_monitor(serial, FALSE);
149 ret = ut181a_configure_waitfor(devc, TRUE, 0, 0,
150 FALSE, FALSE, FALSE, FALSE);
151 if (ret < 0)
152 return ret;
153 (void)ut181a_waitfor_response(sdi, 100);
3094e9d8
GS
154
155 return SR_OK;
156}
157
ebc51109 158static GSList *scan(struct sr_dev_driver *di, GSList *options)
3094e9d8 159{
ebc51109
GS
160 const char *conn, *serialcomm;
161 struct sr_config *src;
162 GSList *l, *devices;
163 struct sr_serial_dev_inst *serial;
164 int ret;
165 char conn_id[64];
166 struct sr_dev_inst *sdi;
167 struct dev_context *devc;
168 size_t idx, ds_idx;
169
170 /*
171 * Implementor's note:
172 * Do _not_ add a default conn value here. Always expect users to
173 * specify the connection. Never match in the absence of a user spec.
174 *
175 * Motivation: There is no way to identify the DMM itself. Neither
176 * are the cable nor its chip unique to the device. They are not even
177 * specific to the series or the vendor. The DMM ships with a generic
178 * CP2110 USB-to-UART bridge. Attempts to auto probe will disturb
179 * other types of devices which may be attached to the probed conn.
180 *
181 * On the other hand it's perfectly fine to communicate to the
182 * device and assume that the device model will accept the requests,
183 * once the user specified the connection (and the driver), and thus
184 * instructed this driver to start such activity.
185 */
186 conn = NULL;
187 serialcomm = "9600/8n1";
188 for (l = options; l; l = l->next) {
189 src = l->data;
190 switch (src->key) {
191 case SR_CONF_CONN:
192 conn = g_variant_get_string(src->data, NULL);
193 break;
194 case SR_CONF_SERIALCOMM:
195 serialcomm = g_variant_get_string(src->data, NULL);
196 break;
197 }
198 }
199 if (!conn)
200 return NULL;
3094e9d8 201
ebc51109
GS
202 devices = NULL;
203 serial = sr_serial_dev_inst_new(conn, serialcomm);
204 ret = serial_open(serial, SERIAL_RDWR);
205 snprintf(conn_id, sizeof(conn_id), "%s", serial->port);
206 serial_flush(serial);
207 /*
208 * We cannot identify the device at this point in time.
209 * Successful open shall suffice for now. More activity
210 * will communicate to the device later, after the driver
211 * instance got created. See below for details.
212 */
213 if (ret != SR_OK) {
214 serial_close(serial);
215 sr_serial_dev_inst_free(serial);
216 return devices;
217 }
3094e9d8 218
ebc51109
GS
219 sdi = g_malloc0(sizeof(*sdi));
220 sdi->status = SR_ST_INACTIVE;
221 sdi->vendor = g_strdup("UNI-T");
222 sdi->model = g_strdup("UT181A");
223 sdi->inst_type = SR_INST_SERIAL;
224 sdi->conn = serial;
225 sdi->connection_id = g_strdup(conn_id);
226 devc = g_malloc0(sizeof(*devc));
227 sdi->priv = devc;
228 sr_sw_limits_init(&devc->limits);
229 for (idx = 0; idx < ARRAY_SIZE(channel_names); idx++) {
230 sr_channel_new(sdi, idx, SR_CHANNEL_ANALOG, TRUE,
231 channel_names[idx]);
232 }
233
234 /*
235 * Run monitor mode for a while to determine the current state
236 * of the device (which cannot get queried by other means). This
237 * also deals with devices which happen to already be in monitor
238 * mode when we connect to them. As a byproduct this query drains
239 * potentially pending RX data, before getting recording details.
240 */
241 devc->disable_feed = 1;
242 ret = ut181a_query_initial_state(sdi, 2000);
243 if (ret < 0) {
244 serial_close(serial);
245 sr_serial_dev_inst_free(serial);
246 return devices;
247 }
248
249 /*
250 * Number of recordings and their names are dynamic and under
251 * the user's control. Prepare for a maximum number of string
252 * labels, and fetch (and re-fetch) their names and current
253 * count on demand.
254 */
255 devc->data_source_names[DATA_SOURCE_LIVE] = "Live";
256 devc->data_source_names[DATA_SOURCE_SAVE] = "Save";
257 for (idx = 0; idx < MAX_REC_COUNT; idx++) {
258 ds_idx = DATA_SOURCE_REC_FIRST + idx;
259 devc->data_source_names[ds_idx] = &devc->record_names[idx][0];
260 }
261 devc->data_source_count = DATA_SOURCE_REC_FIRST;
262 ret = ut181a_update_recordings(sdi);
263 devc->data_source_count = DATA_SOURCE_REC_FIRST + devc->record_count;
264 if (ret < 0) {
265 serial_close(serial);
266 sr_serial_dev_inst_free(serial);
267 return devices;
268 }
269
270 devc->disable_feed = 0;
271 serial_close(serial);
272
273 devices = g_slist_append(devices, sdi);
274
275 return std_scan_complete(di, devices);
3094e9d8
GS
276}
277
278static int config_get(uint32_t key, GVariant **data,
279 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
280{
ebc51109
GS
281 struct dev_context *devc;
282 const struct mqopt_item *mqitem;
283 GVariant *arr[2];
284 const char *range;
3094e9d8 285
3094e9d8
GS
286 (void)cg;
287
ebc51109 288 devc = sdi->priv;
3094e9d8 289 switch (key) {
ebc51109
GS
290 case SR_CONF_CONN:
291 *data = g_variant_new_string(sdi->connection_id);
292 break;
293 case SR_CONF_LIMIT_FRAMES:
294 case SR_CONF_LIMIT_SAMPLES:
295 case SR_CONF_LIMIT_MSEC:
296 if (!devc)
297 return SR_ERR_ARG;
298 return sr_sw_limits_config_get(&devc->limits, key, data);
299 case SR_CONF_DATA_SOURCE:
300 if (!devc)
301 return SR_ERR_ARG;
302 *data = g_variant_new_string(devc->data_source_names[devc->data_source]);
303 break;
304 case SR_CONF_DATALOG:
305 if (!devc)
306 return SR_ERR_ARG;
307 *data = g_variant_new_boolean(devc->is_recording ? TRUE : FALSE);
308 break;
309 case SR_CONF_MEASURED_QUANTITY:
310 if (!devc)
311 return SR_ERR_ARG;
312 mqitem = ut181a_get_mqitem_from_mode(devc->info.meas_head.mode);
313 if (!mqitem)
314 return SR_ERR_NA;
315 arr[0] = g_variant_new_uint32(mqitem->mq);
316 arr[1] = g_variant_new_uint64(mqitem->mqflags);
317 *data = g_variant_new_tuple(arr, ARRAY_SIZE(arr));
318 break;
319 case SR_CONF_RANGE:
320 if (!devc)
321 return SR_ERR_ARG;
322 range = ut181a_get_range_from_packet_bytes(devc);
323 if (!range || !*range)
324 return SR_ERR_NA;
325 *data = g_variant_new_string(range);
326 break;
3094e9d8
GS
327 default:
328 return SR_ERR_NA;
329 }
330
ebc51109 331 return SR_OK;
3094e9d8
GS
332}
333
334static int config_set(uint32_t key, GVariant *data,
335 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
336{
ebc51109
GS
337 struct dev_context *devc;
338 ssize_t idx;
cbfaf5e0 339 gboolean on;
ebc51109
GS
340 GVariant *tuple_child;
341 enum sr_mq mq;
342 enum sr_mqflag mqflags;
343 uint16_t mode;
3094e9d8 344 int ret;
ebc51109
GS
345 size_t rec_no;
346 const char *range;
3094e9d8 347
3094e9d8
GS
348 (void)cg;
349
ebc51109 350 devc = sdi->priv;
3094e9d8 351 switch (key) {
ebc51109
GS
352 case SR_CONF_LIMIT_FRAMES:
353 case SR_CONF_LIMIT_SAMPLES:
354 case SR_CONF_LIMIT_MSEC:
355 if (!devc)
356 return SR_ERR_ARG;
357 return sr_sw_limits_config_set(&devc->limits, key, data);
358 case SR_CONF_DATA_SOURCE:
359 if (!devc)
360 return SR_ERR_ARG;
361 /* Prefer data source names for the lookup. */
362 idx = std_str_idx(data, devc->data_source_names, devc->data_source_count);
363 if (idx >= 0) {
364 devc->data_source = idx;
365 break;
366 }
367 /*
368 * Support record number (1-based) as a fallback. The DMM
369 * "supports" ambiguous recording names (keeps offering a
370 * previously stored name for each new recording, neither
371 * automatically increments nor suggests timestamps).
372 */
373 if (sr_atoi(g_variant_get_string(data, NULL), &ret) != SR_OK)
374 return SR_ERR_ARG;
375 if (ret <= 0)
376 return SR_ERR_ARG;
377 rec_no = ret;
378 if (rec_no > devc->record_count)
379 return SR_ERR_ARG;
380 devc->data_source = DATA_SOURCE_REC_FIRST + rec_no - 1;
381 break;
cbfaf5e0
GS
382 case SR_CONF_DATALOG:
383 if (!devc)
384 return SR_ERR_ARG;
385 on = g_variant_get_boolean(data);
386 sr_err("DIAG: record start/stop %d, currently ENOIMPL", on);
387 return SR_ERR_NA;
388 /*
389 * TODO Send command 0x0a (start) or 0x0b (stop). Though
390 * start needs a name (ymd timestamp?) and interval and
391 * duration (arbitrary choice? 1s for 1d?). Or shall this
392 * SET request control "save" items instead? Take one
393 * sample each for every 'datalog=on' request? Combine
394 * limit_samples and limit_msec with datalog to configure
395 * a recording's parameters?
396 */
397 break;
ebc51109
GS
398 case SR_CONF_MEASURED_QUANTITY:
399 if (!devc)
400 return SR_ERR_ARG;
401 tuple_child = g_variant_get_child_value(data, 0);
402 mq = g_variant_get_uint32(tuple_child);
403 g_variant_unref(tuple_child);
404 tuple_child = g_variant_get_child_value(data, 1);
405 mqflags = g_variant_get_uint64(tuple_child);
406 g_variant_unref(tuple_child);
407 mode = ut181a_get_mode_from_mq_flags(mq, mqflags);
408 if (!mode)
409 return SR_ERR_NA;
410 ret = ut181a_send_cmd_setmode(sdi->conn, mode);
411 if (ret < 0)
412 return ret;
413 ret = ut181a_waitfor_response(sdi->conn, 100);
414 if (ret < 0)
415 return ret;
416 if (devc->info.rsp_head.rsp_type != RSP_TYPE_REPLY_CODE)
417 return SR_ERR_DATA;
418 if (!devc->info.reply_code.ok)
419 return SR_ERR_DATA;
420 break;
421 case SR_CONF_RANGE:
422 range = g_variant_get_string(data, NULL);
423 return ut181a_set_range_from_text(sdi, range);
3094e9d8 424 default:
ebc51109 425 return SR_ERR_NA;
3094e9d8
GS
426 }
427
ebc51109 428 return SR_OK;
3094e9d8
GS
429}
430
431static int config_list(uint32_t key, GVariant **data,
432 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
433{
ebc51109 434 struct dev_context *devc;
3094e9d8
GS
435 int ret;
436
ebc51109 437 devc = sdi ? sdi->priv : NULL;
3094e9d8 438 switch (key) {
ebc51109
GS
439 case SR_CONF_SCAN_OPTIONS:
440 case SR_CONF_DEVICE_OPTIONS:
441 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
442 case SR_CONF_DATA_SOURCE:
443 if (!devc)
444 return SR_ERR_NA;
445 ret = ut181a_update_recordings(sdi);
446 if (ret < 0)
447 return ret;
448 *data = g_variant_new_strv(devc->data_source_names, devc->data_source_count);
449 break;
450 case SR_CONF_MEASURED_QUANTITY:
451 *data = ut181a_get_mq_flags_list();
452 break;
453 case SR_CONF_RANGE:
454 *data = ut181a_get_ranges_list();
455 break;
3094e9d8
GS
456 default:
457 return SR_ERR_NA;
458 }
459
ebc51109 460 return SR_OK;
3094e9d8
GS
461}
462
463static int dev_acquisition_start(const struct sr_dev_inst *sdi)
464{
ebc51109
GS
465 struct dev_context *devc;
466 struct sr_serial_dev_inst *serial;
467 int ret;
468 size_t rec_idx;
469
470 devc = sdi->priv;
471 serial = sdi->conn;
472 serial_flush(serial);
473
474 /*
475 * Send an acquisition start command which depends on the
476 * currently selected data source. Enter monitor mode for
477 * Live readings, get saved or recorded data otherwise. The
478 * latter require queries for sample counts, then run chunked
479 * download sequences (single item for Save, set of samples
480 * for Recordings).
481 */
482 if (devc->data_source == DATA_SOURCE_LIVE) {
483 ret = ut181a_send_cmd_monitor(serial, TRUE);
484 } else if (devc->data_source == DATA_SOURCE_SAVE) {
485 /*
486 * There is only one sequence of saved measurements in
487 * the device, but its length is yet unknown. Determine
488 * the number of saved items, and initiate the reception
489 * of the first value. Completion of data reception will
490 * drive subsequent progress.
491 */
492 ret = ut181a_send_cmd_get_save_count(serial);
493 if (ret < 0)
494 return ret;
495 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
496 FALSE, FALSE, TRUE, FALSE);
497 if (ret < 0)
498 return ret;
499 ret = ut181a_waitfor_response(sdi, 200);
500 if (ret < 0)
501 return ret;
502 devc->info.save_info.save_count = devc->wait_state.data_value;
503 devc->info.save_info.save_idx = 0;
504 ret = ut181a_send_cmd_get_saved_value(serial, 0);
505 } else if (devc->data_source >= DATA_SOURCE_REC_FIRST) {
506 /*
507 * When we get here, the data source got selected, which
508 * includes an update of the device's list of recordings.
509 * So the index should be good, just the number of samples
510 * in that recording is yet unknown. Get the sample count
511 * and initiate the reception of the first chunk, completed
512 * reception of a chunk advances through the sequence.
513 */
514 rec_idx = devc->data_source - DATA_SOURCE_REC_FIRST;
515 if (rec_idx >= devc->record_count)
516 return SR_ERR_DATA;
517 devc->info.rec_info.rec_count = devc->record_count;
518 devc->info.rec_info.rec_idx = rec_idx;
519 devc->info.rec_info.auto_next = 0;
520 devc->info.rec_info.auto_feed = 1;
521 ret = ut181a_send_cmd_get_rec_info(serial, rec_idx);
522 if (ret < 0)
523 return ret;
524 ret = ut181a_configure_waitfor(devc,
525 FALSE, CMD_CODE_GET_REC_INFO, 0,
526 FALSE, FALSE, FALSE, FALSE);
527 if (ret < 0)
528 return ret;
529 ret = ut181a_waitfor_response(sdi, 200);
530 if (ret < 0)
531 return ret;
532 devc->info.rec_data.samples_total = devc->wait_state.data_value;
533 devc->info.rec_data.samples_curr = 0;
534 ret = ut181a_send_cmd_get_rec_samples(serial, rec_idx, 0);
deb76152
GS
535 } else {
536 sr_err("Unhandled data source %d, programming error?",
537 (int)devc->data_source);
538 ret = SR_ERR_BUG;
ebc51109
GS
539 }
540 if (ret < 0)
541 return ret;
542
543 sr_sw_limits_acquisition_start(&devc->limits);
544 devc->recv_count = 0;
545 std_session_send_df_header(sdi);
3094e9d8 546
ebc51109
GS
547 serial_source_add(sdi->session, serial, G_IO_IN, 10,
548 ut181a_handle_events, (void *)sdi);
3094e9d8
GS
549
550 return SR_OK;
551}
552
553static int dev_acquisition_stop(struct sr_dev_inst *sdi)
554{
3094e9d8 555
ebc51109
GS
556 sdi->status = SR_ST_STOPPING;
557 /* Initiate stop here. Activity happens in ut181a_handle_events(). */
3094e9d8
GS
558
559 return SR_OK;
560}
561
562static struct sr_dev_driver uni_t_ut181a_driver_info = {
563 .name = "uni-t-ut181a",
564 .longname = "UNI-T UT181A",
565 .api_version = 1,
566 .init = std_init,
567 .cleanup = std_cleanup,
568 .scan = scan,
569 .dev_list = std_dev_list,
570 .dev_clear = std_dev_clear,
571 .config_get = config_get,
572 .config_set = config_set,
573 .config_list = config_list,
ebc51109
GS
574 .dev_open = std_serial_dev_open,
575 .dev_close = std_serial_dev_close,
3094e9d8
GS
576 .dev_acquisition_start = dev_acquisition_start,
577 .dev_acquisition_stop = dev_acquisition_stop,
578 .context = NULL,
579};
580SR_REGISTER_DEV_DRIVER(uni_t_ut181a_driver_info);