2 * This file is part of the libsigrok project.
4 * Copyright (C) 2019-2020 Gerhard Sittig <gerhard.sittig@gmx.net>
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.
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.
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/>.
21 * This implementation uses protocol information which was provided by
22 * the MIT licensed ut181a project. See Protocol.md for more details:
24 * https://github.com/antage/ut181a/blob/master/Protocol.md
35 * This driver depends on the user's enabling serial communication in
36 * the multimeter's menu system: SETUP -> Communication -> ON. The BLE
37 * adapter will shutdown within a short period of time when it's not
38 * being communicated to, needs another power cycle to re-connect. The
39 * USB cable does not suffer from such a constraint.
41 * Developer notes on the UT181A protocol:
42 * - Serial communication over HID or BLE based "cables", UT-D09 or
43 * UT-D07A, bidirectional communication (UT-D04 won't do).
44 * - UART frame format 8n1 at 9600 bps. Variable length DMM packets.
45 * - DMM packet starts with a magic marker, followed by the length,
46 * followed by data bytes and terminated by the checksum field.
47 * The length includes the remainder of the frame. The checksum
48 * includes the length field as well. The checksum value is the
49 * 16bit sum of all preceeding byte values.
50 * - The meter has many features (live readings, saved measurements,
51 * recorded measurement series) with many additional attributes:
52 * relative, min/max/avg, peak, AC+DC, multiple temperature probes,
53 * COMP mode (PASS/FAIL). The protocol reflects this with highly
54 * variable responses, with differing response layouts including
55 * optional field presence.
56 * - Frame field values are communicated in 8/16/32 bit integer as well
57 * as 32bit float formats in little endian presentation. Measurement
58 * values are represented by a combination of a float value and flags
59 * and a precision (digits count) and a text string which encodes the
60 * measured quantity including its flags and another scale factor
61 * (prefix reflecting the current range).
62 * - Response frames often provide a set of values at the same time:
63 * There are multiple displays, like current and min/max/avg values,
64 * relative values including their reference and the absolute value,
65 * differences between probes, etc.
66 * - The meter can hold multiple recordings with user assigned names,
67 * sample interval and duration, including interactive stop of a
68 * currently active recording. These recordings contain samples that
69 * were taken at a user specified interval.
70 * - The meter can store a list of measurements, which get saved upon
71 * user requests, and can span arbitrary modes/functions/layouts per
72 * saved measurement. In contrast to recordings which keep their type
73 * of measurement across the set of samples.
75 * See https://github.com/antage/ut181a/blob/master/Protocol.md for a
76 * detailled description of the meter's protocol. Some additional notes
77 * in slightly reformatted layout for improved maintainability:
80 * 0x01 60 mV 6 V 600 uA 60 mA 600 R 60 Hz 6 nF
81 * 0x02 600 mV 60 V 6000 uA 600 mA 6 K 600 Hz 60 nF
82 * 0x03 600V (20A is: auto) 60 K 6 KHz 600 nF
83 * 0x04 1000 V 600 K 60 KHz 6 uF
84 * 0x05 6 M 600 KHz 60 uF
85 * 0x06 60 M 6 MHz 600 uF
88 * ampere: 20A is auto, not user selectable
89 * continuity: 600 R, not user selectable
90 * conductivity: 60nS, not user selectable
91 * temperature: not user selectable
92 * diode: not user selectable
93 * frequency: all of the above ranges are available
94 * duty cycle, period: 60Hz to 60kHz, not user selectable beyond 60kHz
95 * - DMM response packets in COMP mode (limits check, PASS/FAIL):
96 * - The device supports two limits (upper, lower) and several modes
97 * ("inner", "outer", "below", "above"). The result is boolean for
99 * - Response packets are NORMAL MEASUREMENTs, with a MAIN value but
100 * without AUX1/AUX2/BAR. Plus some more fields after the bargraph
101 * unit field's position which are specific to COMP mode. Auto range
102 * is off (also in the display).
103 * - Example data for COMP mode responses:
104 * INNER +0mV +3.3mV PASS -- 00 00 03 33 33 53 40 00 00 00 00
105 * INNER +0mV +3.3mV FAIL -- 00 01 03 33 33 53 40 00 00 00 00
106 * INNER +1mV +3.3mV FAIL -- 00 01 03 33 33 53 40 00 00 80 3f
107 * OUTER +0mV +3.3mV PASS -- 01 00 03 33 33 53 40 00 00 00 00
108 * BELOW +30mV PASS -- 02 00 03 00 00 f0 41
110 * 1 byte mode, can be 0 to 3 for INNER/OUTER/BELOW/ABOVE
111 * 1 byte test result, bool failure, 0 is PASS, 1 is FAIL
112 * 1 byte digits, *not* shifted as in other precision fields
113 * 4 byte (always) high limit
114 * 4 byte (conditional) low limit, not in all modes
116 * Implementation notes on this driver version:
117 * - DMM channel assignment for measurement types:
118 * - normal: P1 main, P2 aux1, P3 aux2, P5 bar (as applicable)
119 * - relative: P1 relative, P2 reference, P3 absolute
120 * - min-max: P1 current, P2 maximum, P3 average, P4 minimum
121 * - peak: P2 maximum, P4 minimum
122 * - save/recording: P5 timestamp (in addition to the above)
127 * - General question: How many channels to export? An overlay with ever
128 * changing meanings? Or a multitude where values are sparse?
129 * - Check how the PC side can _set_ the mode and range. Does mode
130 * selection depend on the physical knob? Would assume it does.
131 * The multitude of mode codes (some 70) and the lack of an apparent
132 * formula to them makes this enhancement tedious. Listing too many
133 * items in the "list" query could reduce usability.
134 * - Add support for "COMP mode" (comparison, PASS/FAIL result).
135 * - How to express PASS/FAIL in the data feed submission? There is
136 * SR_UNIT_BOOLEAN but not a good MQ for envelope test results.
137 * - How to communicate limits to the session feed? COMP replies are
138 * normal measurements without aux1 and aux2. Is it appropriate to
139 * re-use DMM channels, or shall we add more of them?
140 * - Communicate timestamps for saved measurements and recordings to the
142 * - There is SR_MQ_TIME and SR_MQFLAG_RELATIVE, and SR_UNIT_SECOND.
143 * Absolute time seems appropriate for save, relative (to the start
144 * of the recording) for recordings.
145 * - Unfortunately double data types are not fully operational, so we
146 * use float. Which is limited to 23 bits, thus can only span some
147 * 100 days. But recordings can span longer periods when the sample
149 * - Absolute times suffer from the 23bit limit (epoch time_t values
150 * require 32 bits these days). And they get presented as 1.5Gs,
151 * there seems to be no "date/time" flag or format.
152 * - Dynamically allocate and re-allocate the record name table. There
153 * appears to be no limit of 20 recordings. The manual won't tell, but
154 * it's assumed that a few hundreds or thousands are supported (10K
155 * samples in total? that's a guess though).
156 * - The PC side could initiate to save a live measurement. The command
157 * is there, it's just uncertain which SR_CONF_ key to use, DATALOG
158 * appears to enter/leave a period of recording, not a single shot.
159 * - The PC side could start and stop recordings. But the start command
160 * requires a name, sample interval, and duration, but SR_CONF_DATALOG
161 * is just a boolean. Combining SR_CONF_LIMIT_SAMPLES, _DATALOG, et al
162 * raises the question which order applications will send configure
164 * - How to communicate the LOWPASS condition? PASS/FAIL results for
165 * COMP mode? Timestamps (absolute wall clock times)? High voltage,
166 * lead errors (probe plugs in ampere modes)?
170 * Development HACK, to see data frame exchange at -l 2 without the
171 * serial spew of -l 5. Also lets you concentrate on some of the code
172 * paths which currently are most interesting during maintenance. :)
174 #if UT181A_WITH_SER_ECHO
175 # define FRAME_DUMP_LEVEL SR_LOG_WARN
176 # define FRAME_DUMP_CALL sr_warn
178 # define FRAME_DUMP_LEVEL (SR_LOG_SPEW + 1)
179 # define sr_nop(...) do { /* EMPTY */ } while (0)
180 # define FRAME_DUMP_CALL sr_nop
183 #define FRAME_DUMP_RXDATA 0 /* UART level receive data. */
184 #define FRAME_DUMP_CSUM 0 /* Chunking, frame isolation. */
185 #define FRAME_DUMP_FRAME 0 /* DMM frames, including envelope. */
186 #define FRAME_DUMP_BYTES 0 /* DMM frame's payload data, "DMM packet". */
187 #define FRAME_DUMP_PARSE 1 /* Measurement value extraction. */
188 #define FRAME_DUMP_REMAIN 1 /* Unprocessed response data. */
191 * TODO Can we collapse several u16 modes in useful ways? Need we keep
192 * them separate for "MQ+flags to mode" lookups, yet mark only some of
193 * them for LIST result sets? Can't filter and need to provide them all
194 * to the user? There are some 70-80 combinations. :-O
196 * Unfortunately there is no general pattern to these code numbers, or
197 * when there is it's non-obvious. There are _some_ conventions, but also
198 * exceptions, so that programmatic handling fails.
201 * - Factor out LOWPASS to a separate mode? At least derive an MQFLAG.
203 static const struct mqopt_item ut181a_mqopts[] = {
205 SR_MQ_VOLTAGE, SR_MQFLAG_AC, {
206 MODE_V_AC, MODE_V_AC_REL,
207 MODE_mV_AC, MODE_mV_AC_REL,
208 MODE_V_AC_PEAK, MODE_mV_AC_PEAK,
209 MODE_V_AC_LOWPASS, MODE_V_AC_LOWPASS_REL,
214 SR_MQ_VOLTAGE, SR_MQFLAG_DC, {
215 MODE_V_DC, MODE_V_DC_REL,
216 MODE_mV_DC, MODE_mV_DC_REL,
217 MODE_V_DC_PEAK, MODE_mV_DC_PEAK,
222 SR_MQ_VOLTAGE, SR_MQFLAG_DC | SR_MQFLAG_AC, {
223 MODE_V_DC_ACDC, MODE_V_DC_ACDC_REL,
224 MODE_mV_AC_ACDC, MODE_mV_AC_ACDC_REL,
230 MODE_V_AC_dBV, MODE_V_AC_dBV_REL,
231 MODE_V_AC_dBm, MODE_V_AC_dBm_REL,
236 SR_MQ_CURRENT, SR_MQFLAG_AC, {
237 MODE_A_AC, MODE_A_AC_REL,
239 MODE_mA_AC, MODE_mA_AC_REL,
241 MODE_uA_AC, MODE_uA_AC_REL,
247 SR_MQ_CURRENT, SR_MQFLAG_DC, {
248 MODE_A_DC, MODE_A_DC_REL,
250 MODE_mA_DC, MODE_mA_DC_REL,
251 MODE_uA_DC, MODE_uA_DC_REL,
257 SR_MQ_CURRENT, SR_MQFLAG_DC | SR_MQFLAG_AC, {
258 MODE_A_DC_ACDC, MODE_A_DC_ACDC_REL,
259 MODE_mA_DC_ACDC, MODE_mA_DC_ACDC_REL,
260 MODE_uA_DC_ACDC, MODE_uA_DC_ACDC_REL,
261 MODE_mA_DC_ACDC_PEAK,
266 SR_MQ_RESISTANCE, 0, {
267 MODE_RES, MODE_RES_REL, 0,
271 SR_MQ_CONDUCTANCE, 0, {
272 MODE_COND, MODE_COND_REL, 0,
276 SR_MQ_CONTINUITY, 0, {
277 MODE_CONT_SHORT, MODE_CONT_OPEN, 0,
281 SR_MQ_VOLTAGE, SR_MQFLAG_DIODE | SR_MQFLAG_DC, {
282 MODE_DIODE, MODE_DIODE_ALARM, 0,
286 SR_MQ_CAPACITANCE, 0, {
287 MODE_CAP, MODE_CAP_REL, 0,
291 SR_MQ_FREQUENCY, 0, {
292 MODE_FREQ, MODE_FREQ_REL,
293 MODE_V_AC_Hz, MODE_mV_AC_Hz,
294 MODE_A_AC_Hz, MODE_mA_AC_Hz, MODE_uA_AC_Hz,
299 SR_MQ_DUTY_CYCLE, 0, {
300 MODE_DUTY, MODE_DUTY_REL, 0,
304 SR_MQ_PULSE_WIDTH, 0, {
305 MODE_PULSEWIDTH, MODE_PULSEWIDTH_REL, 0,
309 SR_MQ_TEMPERATURE, 0, {
310 MODE_TEMP_C_T1_and_T2, MODE_TEMP_C_T1_and_T2_REL,
311 MODE_TEMP_C_T1_minus_T2, MODE_TEMP_F_T1_and_T2,
312 MODE_TEMP_C_T2_and_T1, MODE_TEMP_C_T2_and_T1_REL,
313 MODE_TEMP_C_T2_minus_T1,
314 MODE_TEMP_F_T1_and_T2_REL, MODE_TEMP_F_T1_minus_T2,
315 MODE_TEMP_F_T2_and_T1, MODE_TEMP_F_T2_and_T1_REL,
316 MODE_TEMP_F_T2_minus_T1,
322 SR_PRIV const struct mqopt_item *ut181a_get_mqitem_from_mode(uint16_t mode)
324 size_t mq_idx, mode_idx;
325 const struct mqopt_item *item;
327 for (mq_idx = 0; mq_idx < ARRAY_SIZE(ut181a_mqopts); mq_idx++) {
328 item = &ut181a_mqopts[mq_idx];
329 for (mode_idx = 0; mode_idx < ARRAY_SIZE(item->modes); mode_idx++) {
330 if (!item->modes[mode_idx])
332 if (item->modes[mode_idx] != mode)
334 /* Found a matching mode. */
341 SR_PRIV uint16_t ut181a_get_mode_from_mq_flags(enum sr_mq mq, enum sr_mqflag mqflags)
344 const struct mqopt_item *item;
346 for (mq_idx = 0; mq_idx < ARRAY_SIZE(ut181a_mqopts); mq_idx++) {
347 item = &ut181a_mqopts[mq_idx];
350 /* TODO Need finer checks? Masked? */
351 if (mqflags != item->mqflags)
353 return item->modes[0];
358 SR_PRIV GVariant *ut181a_get_mq_flags_list_item(enum sr_mq mq, enum sr_mqflag mqflag)
360 GVariant *arr[2], *tuple;
362 arr[0] = g_variant_new_uint32(mq);
363 arr[1] = g_variant_new_uint64(mqflag);
364 tuple = g_variant_new_tuple(arr, ARRAY_SIZE(arr));
369 SR_PRIV GVariant *ut181a_get_mq_flags_list(void)
372 GVariant *tuple, *list;
374 const struct mqopt_item *item;
376 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
377 for (i = 0; i < ARRAY_SIZE(ut181a_mqopts); i++) {
378 item = &ut181a_mqopts[i];
379 tuple = ut181a_get_mq_flags_list_item(item->mq, item->mqflags);
380 g_variant_builder_add_value(&gvb, tuple);
382 list = g_variant_builder_end(&gvb);
388 * See the Protocol.md document's "Range byte" section. Value 0 is said
389 * to communicate "auto range", while values 1-8 are said to communicate
390 * specific ranges which depend on the meter's current function. Yet
391 * there is another misc flag for auto range.
393 * From this information, and observed packet content, it is assumed
394 * that the following logic applies:
395 * - Measurements (response packets) carry the "auto" flag, _and_ a
396 * "range" byte, to provide the information that auto ranging was in
397 * effect, and which specific range the automatic detection picked.
398 * - "Set range" requests can request a specific range (values 1-8), or
399 * switch to auto range (value 0).
401 * This driver implementation returns non-settable string literals for
402 * modes where auto ranging is not user adjustable (high current, diode,
403 * continuity, conductivity, temperature). Setup requests get rejected.
404 * (The local user interface neither responds to RANGE button presses.)
406 static const char *range_auto = "auto";
407 static const char *ranges_volt_mv[] = {
408 "60mV", "600mV", NULL,
410 static const char *ranges_volt_v[] = {
411 "6V", "60V", "600V", "1000V", NULL,
413 static const char *ranges_volt_diode[] = {
414 /* Diode is always auto, not user adjustable. */
417 static const char *ranges_amp_ua[] = {
418 "600uA", "6000uA", NULL,
420 static const char *ranges_amp_ma[] = {
421 "60mA", "600mA", NULL,
423 static const char *ranges_amp_a[] = {
424 /* The 'A' range is always 20A (in the display, manual says 10A). */
427 static const char *ranges_ohm_res[] = {
429 * Prefer "Ohm" (or "R" for sub-kilo ranges) instead? We try to
430 * keep usability in other places (micro), too, by letting users
431 * type regular non-umlaut text, and avoiding encoding issues.
433 "600Ω", "6kΩ", "60kΩ", "600kΩ", "6MΩ", "60MΩ", NULL,
435 static const char *ranges_ohm_600[] = {
436 /* Continuity is always 600R, not user adjustable. */
439 static const char *ranges_cond[] = {
440 /* Conductivity is always 60nS, not user adjustable. */
443 static const char *ranges_capa[] = {
444 "6nF", "60nF", "600nF", "6uF", "60uF", "600uF", "6mF", "600mF", NULL,
446 static const char *ranges_freq_full[] = {
447 "60Hz", "600Hz", "6kHz", "60kHz", "600kHz", "6MHz", "60MHz", NULL,
449 static const char *ranges_freq_60khz[] = {
450 /* Duty cycle and period only support up to 60kHz. */
451 "60Hz", "600Hz", "6kHz", "60kHz", NULL,
453 static const char *ranges_temp_c[] = {
454 /* Temperature always is up to 1000 degree C, not user adjustable. */
457 static const char *ranges_temp_f[] = {
458 /* Temperature always is up to 1832 F, not user adjustable. */
462 static void ut181a_add_ranges_list(GVariantBuilder *b, const char **l)
466 while (l && *l && **l) {
468 g_variant_builder_add(b, "s", range);
472 SR_PRIV GVariant *ut181a_get_ranges_list(void)
477 /* Also list those ranges which cannot get set? */
478 #define WITH_RANGE_LIST_FIXED 1
480 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
481 g_variant_builder_add(&gvb, "s", range_auto);
482 ut181a_add_ranges_list(&gvb, ranges_volt_mv);
483 ut181a_add_ranges_list(&gvb, ranges_volt_v);
484 (void)ranges_volt_diode;
485 ut181a_add_ranges_list(&gvb, ranges_amp_ua);
486 ut181a_add_ranges_list(&gvb, ranges_amp_ma);
487 #if WITH_RANGE_LIST_FIXED
488 ut181a_add_ranges_list(&gvb, ranges_amp_a);
492 ut181a_add_ranges_list(&gvb, ranges_ohm_res);
493 (void)ranges_ohm_600;
494 ut181a_add_ranges_list(&gvb, ranges_cond);
495 ut181a_add_ranges_list(&gvb, ranges_capa);
496 ut181a_add_ranges_list(&gvb, ranges_freq_full);
497 (void)ranges_freq_60khz;
498 #if WITH_RANGE_LIST_FIXED
499 ut181a_add_ranges_list(&gvb, ranges_temp_c);
500 ut181a_add_ranges_list(&gvb, ranges_temp_f);
505 list = g_variant_builder_end(&gvb);
510 SR_PRIV const char *ut181a_get_range_from_packet_bytes(struct dev_context *devc)
519 mode = devc->info.meas_head.mode;
520 range = devc->info.meas_head.range;
521 is_auto = devc->info.meas_head.is_auto_range;
523 /* Handle the simple cases of "auto" and out of (absolute) limits. */
530 if (range > MAX_RANGE_INDEX)
533 /* Lookup the list of ranges which depend on the meter's current mode. */
540 case MODE_V_AC_LOWPASS:
541 case MODE_V_AC_LOWPASS_REL:
543 case MODE_V_AC_dBV_REL:
545 case MODE_V_AC_dBm_REL:
549 case MODE_V_DC_ACDC_REL:
551 ranges = ranges_volt_v;
556 case MODE_mV_AC_PEAK:
557 case MODE_mV_AC_ACDC:
558 case MODE_mV_AC_ACDC_REL:
561 case MODE_mV_DC_PEAK:
562 ranges = ranges_volt_mv;
566 ranges = ranges_ohm_res;
568 case MODE_CONT_SHORT:
570 ranges = ranges_ohm_600;
574 ranges = ranges_cond;
578 ranges = ranges_capa;
582 ranges = ranges_freq_full;
586 case MODE_PULSEWIDTH:
587 case MODE_PULSEWIDTH_REL:
588 ranges = ranges_freq_60khz;
592 case MODE_uA_DC_ACDC:
593 case MODE_uA_DC_ACDC_REL:
594 case MODE_uA_DC_PEAK:
598 case MODE_uA_AC_PEAK:
599 ranges = ranges_amp_ua;
603 case MODE_mA_DC_ACDC:
604 case MODE_mA_DC_ACDC_REL:
605 case MODE_mA_DC_ACDC_PEAK:
609 case MODE_mA_AC_PEAK:
610 ranges = ranges_amp_ma;
613 /* Some modes are neither flexible nor adjustable. */
614 case MODE_TEMP_C_T1_and_T2:
615 case MODE_TEMP_C_T1_and_T2_REL:
616 case MODE_TEMP_C_T2_and_T1:
617 case MODE_TEMP_C_T2_and_T1_REL:
618 case MODE_TEMP_C_T1_minus_T2:
619 case MODE_TEMP_C_T2_minus_T1:
620 ranges = ranges_temp_c;
622 case MODE_TEMP_F_T1_and_T2:
623 case MODE_TEMP_F_T1_and_T2_REL:
624 case MODE_TEMP_F_T2_and_T1:
625 case MODE_TEMP_F_T2_and_T1_REL:
626 case MODE_TEMP_F_T1_minus_T2:
627 case MODE_TEMP_F_T2_minus_T1:
628 ranges = ranges_temp_f;
630 /* Diode, always 3V. */
632 case MODE_DIODE_ALARM:
633 ranges = ranges_volt_diode;
635 /* High current (A range). Always 20A. */
639 case MODE_A_DC_ACDC_REL:
645 ranges = ranges_amp_a;
648 /* Unknown mode? Programming error? */
653 /* Lookup the range in the list of the mode's ranges. */
654 while (ranges && *ranges && **ranges && --range > 0) {
657 if (!ranges || !*ranges || !**ranges)
662 SR_PRIV int ut181a_set_range_from_text(const struct sr_dev_inst *sdi, const char *text)
664 struct dev_context *devc;
669 /* We must have determined the meter's current mode first. */
677 mode = devc->info.meas_head.mode;
681 /* Handle the simple case of "auto" caller spec. */
682 if (strcmp(text, range_auto) == 0) {
684 return ut181a_send_cmd_setmode(sdi->conn, range);
687 /* Lookup the list of ranges which depend on the meter's current mode. */
690 /* Map "user servicable" modes to their respective ranges list. */
695 case MODE_V_AC_LOWPASS:
696 case MODE_V_AC_LOWPASS_REL:
698 case MODE_V_AC_dBV_REL:
700 case MODE_V_AC_dBm_REL:
704 case MODE_V_DC_ACDC_REL:
706 ranges = ranges_volt_v;
711 case MODE_mV_AC_PEAK:
712 case MODE_mV_AC_ACDC:
713 case MODE_mV_AC_ACDC_REL:
716 case MODE_mV_DC_PEAK:
717 ranges = ranges_volt_mv;
721 ranges = ranges_ohm_res;
725 ranges = ranges_capa;
729 ranges = ranges_freq_full;
733 case MODE_PULSEWIDTH:
734 case MODE_PULSEWIDTH_REL:
735 ranges = ranges_freq_60khz;
739 case MODE_uA_DC_ACDC:
740 case MODE_uA_DC_ACDC_REL:
741 case MODE_uA_DC_PEAK:
745 case MODE_uA_AC_PEAK:
746 ranges = ranges_amp_ua;
750 case MODE_mA_DC_ACDC:
751 case MODE_mA_DC_ACDC_REL:
752 case MODE_mA_DC_ACDC_PEAK:
756 case MODE_mA_AC_PEAK:
757 ranges = ranges_amp_ma;
761 * Some modes use fixed ranges. Accept their specs or refuse to
762 * set a specific range? The meter's UI refuses MANUAL mode and
763 * remains in AUTO mode. So do we here.
765 case MODE_CONT_SHORT:
768 ranges = ranges_ohm_600;
773 ranges = ranges_cond;
775 case MODE_TEMP_C_T1_and_T2:
776 case MODE_TEMP_C_T1_and_T2_REL:
777 case MODE_TEMP_C_T2_and_T1:
778 case MODE_TEMP_C_T2_and_T1_REL:
779 case MODE_TEMP_C_T1_minus_T2:
780 case MODE_TEMP_C_T2_minus_T1:
782 ranges = ranges_temp_c;
784 case MODE_TEMP_F_T1_and_T2:
785 case MODE_TEMP_F_T1_and_T2_REL:
786 case MODE_TEMP_F_T2_and_T1:
787 case MODE_TEMP_F_T2_and_T1_REL:
788 case MODE_TEMP_F_T1_minus_T2:
789 case MODE_TEMP_F_T2_minus_T1:
791 ranges = ranges_temp_f;
793 /* Diode, always 3V. */
795 case MODE_DIODE_ALARM:
797 ranges = ranges_volt_diode;
799 /* High current (A range). Always 20A. */
803 case MODE_A_DC_ACDC_REL:
810 ranges = ranges_amp_a;
813 /* Unknown mode? Programming error? */
818 /* Lookup the range in the list of the mode's ranges. */
820 while (ranges && *ranges && **ranges) {
821 if (strcmp(*ranges, text) != 0) {
826 return ut181a_send_cmd_setrange(sdi->conn, range);
832 * Parse a unit text into scale factor, MQ and flags, and unit.
834 * @param[out] mqs The scale/MQ/unit details to fill in.
835 * @param[in] text The DMM's "unit text" (string label).
837 * @returns SR_OK upon success, SR_ERR_* upon error.
839 * UT181A unit text strings encode several details: They start with an
840 * optional prefix (which communicates a scale factor), specify the unit
841 * of the measured value (which hints towards the measured quantity),
842 * and carry optional attributes (which MQ flags can get derived from).
844 * See unit.rs for the list of known input strings. Though there are
845 * unexpected differences:
846 * - \u{FFFD}C/F instead of 0xb0 for degree (local platform conversion?)
847 * - 'u' seems to be used for micro, good (no 'micro' umlaut involved)
848 * - '~' (tilde, 0x7e) for Ohm
850 * Prefixes: p n u m '' k M G
854 * - dBV, dBm (no prefix)
855 * - ~ (tilde, Ohm) (- k M)
857 * - % percent (no prefix)
860 * - xC, xF degree (no prefix)
863 * - Aac+dc ampere AC+DC (- m u)
864 * - AAC ampere AC (- m u)
865 * - ADC ampere DC (- m u)
866 * - Vac+dc volt AC+DC (- m)
867 * - VAC volt AC (- m)
868 * - VDC volt DC (- m)
870 static int ut181a_get_mq_details_from_text(struct mq_scale_params *mqs, const char *text)
875 enum sr_mqflag mqflags;
880 memset(mqs, 0, sizeof(*mqs));
882 /* Start from unknown state, no modifiers. */
888 /* Derive the scale factor from the optional prefix. */
889 scale_char = *text++;
890 if (scale_char == 'p')
892 else if (scale_char == 'n')
894 else if (scale_char == 'u')
896 else if (scale_char == 'm')
898 else if (scale_char == 'k')
900 else if (scale_char == 'M')
902 else if (scale_char == 'G')
907 /* Guess the MQ (and flags) from the unit text. */
908 if (g_str_has_prefix(text, "F")) {
910 unit = SR_UNIT_FARAD;
912 mq = SR_MQ_CAPACITANCE;
913 } else if (g_str_has_prefix(text, "dBV")) {
914 text += strlen("dBV");
915 unit = SR_UNIT_DECIBEL_VOLT;
918 } else if (g_str_has_prefix(text, "dBm")) {
919 text += strlen("dBm");
920 unit = SR_UNIT_DECIBEL_MW;
923 } else if (g_str_has_prefix(text, "~")) {
927 mq = SR_MQ_RESISTANCE;
928 } else if (g_str_has_prefix(text, "S")) {
930 unit = SR_UNIT_SIEMENS;
932 mq = SR_MQ_CONDUCTANCE;
933 } else if (g_str_has_prefix(text, "%")) {
935 unit = SR_UNIT_PERCENTAGE;
937 mq = SR_MQ_DUTY_CYCLE;
938 } else if (g_str_has_prefix(text, "s")) {
940 unit = SR_UNIT_SECOND;
942 mq = SR_MQ_PULSE_WIDTH;
943 } else if (g_str_has_prefix(text, "Hz")) {
944 text += strlen("Hz");
945 unit = SR_UNIT_HERTZ;
947 mq = SR_MQ_FREQUENCY;
948 } else if (g_str_has_prefix(text, "\xb0" "C")) {
949 text += strlen("\xb0" "C");
950 unit = SR_UNIT_CELSIUS;
952 mq = SR_MQ_TEMPERATURE;
953 } else if (g_str_has_prefix(text, "\xb0" "F")) {
954 text += strlen("\xb0" "F");
955 unit = SR_UNIT_FAHRENHEIT;
957 mq = SR_MQ_TEMPERATURE;
958 } else if (g_str_has_prefix(text, "A")) {
960 unit = SR_UNIT_AMPERE;
963 } else if (g_str_has_prefix(text, "V")) {
968 } else if (g_str_has_prefix(text, "timestamp")) {
970 * The meter never provides this "timestamp" label,
971 * but the driver re-uses common logic here to have
972 * the MQ details filled in for save/record stamps.
974 text += strlen("timestamp");
975 unit = SR_UNIT_SECOND;
980 /* Amend MQ flags from an optional suffix. */
981 if (g_str_has_prefix(text, "ac+dc")) {
982 text += strlen("ac+dc");
983 mqflags |= SR_MQFLAG_AC | SR_MQFLAG_DC;
984 } else if (g_str_has_prefix(text, "AC")) {
985 text += strlen("AC");
986 mqflags |= SR_MQFLAG_AC;
987 } else if (g_str_has_prefix(text, "DC")) {
988 text += strlen("DC");
989 mqflags |= SR_MQFLAG_DC;
992 /* Put all previously determined details into the container. */
995 mqs->mqflags = mqflags;
1002 * Break down a packed 32bit timestamp presentation, and create an epoch
1003 * value from it. The UT181A protocol encodes timestamps in a 32bit value:
1012 * TODO Find a portable and correct conversion helper. The mktime() API
1013 * is said to involve timezone details, and modify the environment. Is
1014 * strftime("%s") a better approach? Until then mktime() might be good
1015 * enough an approach, assuming that the meter will be set to the user's
1018 static time_t ut181a_get_epoch_for_timestamp(uint32_t ts)
1022 memset(&t, 0, sizeof(t));
1023 t.tm_year = ((ts >> 0) & 0x3f) + 2000 - 1900;
1024 t.tm_mon = ((ts >> 6) & 0x0f) - 1;
1025 t.tm_mday = ((ts >> 10) & 0x1f);
1026 t.tm_hour = ((ts >> 15) & 0x1f);
1027 t.tm_min = ((ts >> 20) & 0x3f);
1028 t.tm_sec = ((ts >> 26) & 0x3f);
1035 * Calculate UT181A specific checksum for serial data frame.
1037 * @param[in] data The payload bytes to calculate the checksum for.
1038 * @param[in] dlen The number of payload bytes.
1040 * @returns The checksum value.
1042 * On the wire the checksum covers all fields after the magic and before
1043 * the checksum. In other words the checksum covers the length field and
1044 * the payload bytes.
1046 static uint16_t ut181a_checksum(const uint8_t *data, size_t dlen)
1058 * Send payload bytes via serial comm, add frame envelope and transmit.
1060 * @param[in] serial Serial port.
1061 * @param[in] data Payload bytes.
1062 * @param[in] dlen Payload length.
1064 * @returns >= 0 upon success, negative upon failure (SR_ERR codes)
1066 static int ut181a_send_frame(struct sr_serial_dev_inst *serial,
1067 const uint8_t *data, size_t dlen)
1069 uint8_t frame_buff[SEND_BUFF_SIZE];
1071 const uint8_t *cs_data;
1076 if (FRAME_DUMP_BYTES && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
1078 spew = sr_hexdump_new(data, dlen);
1079 FRAME_DUMP_CALL("TX payload, %zu bytes: %s", dlen, spew->str);
1080 sr_hexdump_free(spew);
1084 * The frame buffer must hold the magic and length and payload
1085 * bytes and checksum. Check for the available space.
1087 if (dlen > sizeof(frame_buff) - 3 * sizeof(uint16_t)) {
1092 * Create a frame for the payload bytes. The length field's value
1093 * also includes the checksum field (spans the remainder of the
1094 * frame). The checksum covers everything between the magic and
1095 * the checksum field.
1098 WL16(&frame_buff[frame_off], FRAME_MAGIC);
1099 frame_off += sizeof(uint16_t);
1100 WL16(&frame_buff[frame_off], dlen + sizeof(uint16_t));
1101 frame_off += sizeof(uint16_t);
1102 memcpy(&frame_buff[frame_off], data, dlen);
1104 cs_data = &frame_buff[sizeof(uint16_t)];
1105 cs_dlen = frame_off - sizeof(uint16_t);
1106 cs_value = ut181a_checksum(cs_data, cs_dlen);
1107 WL16(&frame_buff[frame_off], cs_value);
1108 frame_off += sizeof(uint16_t);
1110 if (FRAME_DUMP_FRAME && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
1112 spew = sr_hexdump_new(frame_buff, frame_off);
1113 FRAME_DUMP_CALL("TX frame, %zu bytes: %s", frame_off, spew->str);
1114 sr_hexdump_free(spew);
1117 ret = serial_write_blocking(serial, frame_buff, frame_off, SEND_TO_MS);
1124 /* Construct and transmit "set mode" command. */
1125 SR_PRIV int ut181a_send_cmd_setmode(struct sr_serial_dev_inst *serial, uint16_t mode)
1127 uint8_t cmd[sizeof(uint8_t) + sizeof(uint16_t)];
1131 cmd[cmd_off++] = CMD_CODE_SET_MODE;
1132 WL16(&cmd[cmd_off], mode);
1133 cmd_off += sizeof(uint16_t);
1135 return ut181a_send_frame(serial, cmd, cmd_off);
1138 /* Construct and transmit "set range" command. */
1139 SR_PRIV int ut181a_send_cmd_setrange(struct sr_serial_dev_inst *serial, uint8_t range)
1141 uint8_t cmd[sizeof(uint8_t) + sizeof(uint8_t)];
1145 cmd[cmd_off++] = CMD_CODE_SET_RANGE;
1146 cmd[cmd_off++] = range;
1148 return ut181a_send_frame(serial, cmd, cmd_off);
1151 /* Construct and transmit "monitor on/off" command. */
1152 SR_PRIV int ut181a_send_cmd_monitor(struct sr_serial_dev_inst *serial, gboolean on)
1154 uint8_t cmd[sizeof(uint8_t) + sizeof(uint8_t)];
1158 cmd[cmd_off++] = CMD_CODE_SET_MONITOR;
1159 cmd[cmd_off++] = on ? 1 : 0;
1161 return ut181a_send_frame(serial, cmd, cmd_off);
1164 /* Construct and transmit "get saved measurements count" command. */
1165 SR_PRIV int ut181a_send_cmd_get_save_count(struct sr_serial_dev_inst *serial)
1169 cmd = CMD_CODE_GET_SAVED_COUNT;
1170 return ut181a_send_frame(serial, &cmd, sizeof(cmd));
1174 * Construct and transmit "get saved measurement value" command.
1175 * Important: Callers use 0-based index, protocol needs 1-based index.
1177 SR_PRIV int ut181a_send_cmd_get_saved_value(struct sr_serial_dev_inst *serial, size_t idx)
1179 uint8_t cmd[sizeof(uint8_t) + sizeof(uint16_t)];
1183 cmd[cmd_off++] = CMD_CODE_GET_SAVED_MEAS;
1184 WL16(&cmd[cmd_off], idx + 1);
1185 cmd_off += sizeof(uint16_t);
1187 return ut181a_send_frame(serial, cmd, sizeof(cmd));
1190 /* Construct and transmit "get recordings count" command. */
1191 SR_PRIV int ut181a_send_cmd_get_recs_count(struct sr_serial_dev_inst *serial)
1195 cmd = CMD_CODE_GET_RECS_COUNT;
1196 return ut181a_send_frame(serial, &cmd, sizeof(cmd));
1200 * Construct and transmit "get recording information" command.
1201 * Important: Callers use 0-based index, protocol needs 1-based index.
1203 SR_PRIV int ut181a_send_cmd_get_rec_info(struct sr_serial_dev_inst *serial, size_t idx)
1205 uint8_t cmd[sizeof(uint8_t) + sizeof(uint16_t)];
1209 cmd[cmd_off++] = CMD_CODE_GET_REC_INFO;
1210 WL16(&cmd[cmd_off], idx + 1);
1211 cmd_off += sizeof(uint16_t);
1213 return ut181a_send_frame(serial, cmd, sizeof(cmd));
1217 * Construct and transmit "get recording samples" command.
1218 * Important: Callers use 0-based index, protocol needs 1-based index.
1220 SR_PRIV int ut181a_send_cmd_get_rec_samples(struct sr_serial_dev_inst *serial, size_t idx, size_t off)
1222 uint8_t cmd[sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t)];
1226 cmd[cmd_off++] = CMD_CODE_GET_REC_SAMPLES;
1227 WL16(&cmd[cmd_off], idx + 1);
1228 cmd_off += sizeof(uint16_t);
1229 WL32(&cmd[cmd_off], off + 1);
1230 cmd_off += sizeof(uint32_t);
1232 return ut181a_send_frame(serial, cmd, sizeof(cmd));
1236 * Construct and transmit "record on/off" command. Requires a caption,
1237 * an interval, and a duration to start a recording. Recordings can get
1238 * stopped upon request, or end when the requested duration has passed.
1242 * Specify which kind of response to wait for.
1244 * @param[in] devc The device context.
1245 * @param[in] want_code Reply code wanted, boolean.
1246 * @param[in] want_data Reply data wanted, boolean.
1247 * @param[in] want_rsp_type Special response type wanted.
1248 * @param[in] want_measure Measurement wanted, boolean.
1249 * @param[in] want_rec_count Records count wanted, boolean.
1250 * @param[in] want_save_count Saved count wanted, boolean.
1251 * @param[in] want_sample_count Samples count wanted, boolean.
1253 SR_PRIV int ut181a_configure_waitfor(struct dev_context *devc,
1254 gboolean want_code, enum ut181_cmd_code want_data,
1255 enum ut181_rsp_type want_rsp_type,
1256 gboolean want_measure, gboolean want_rec_count,
1257 gboolean want_save_count, gboolean want_sample_count)
1261 want_data = CMD_CODE_GET_RECS_COUNT;
1262 if (want_save_count)
1263 want_data = CMD_CODE_GET_SAVED_COUNT;
1264 if (want_sample_count)
1265 want_data = CMD_CODE_GET_REC_SAMPLES;
1267 memset(&devc->wait_state, 0, sizeof(devc->wait_state));
1268 devc->wait_state.want_code = want_code;
1269 devc->wait_state.want_data = want_data;
1270 devc->wait_state.want_rsp_type = want_rsp_type;
1271 devc->wait_state.want_measure = want_measure;
1272 memset(&devc->last_data, 0, sizeof(devc->last_data));
1278 * Wait for a response (or timeout) after a command was sent.
1280 * @param[in] sdi The device instance.
1281 * @param[in] timeout_ms The timeout in milliseconds.
1283 * @returns SR_OK upon success, SR_ERR_* upon error.
1285 * This routine waits for the complete reception of a response (any kind)
1286 * after a command was previously sent by the caller, or terminates when
1287 * the timeout has expired without reception of a response. Callers need
1288 * to check the kind of response (data values, or status, or error codes).
1290 SR_PRIV int ut181a_waitfor_response(const struct sr_dev_inst *sdi, int timeout_ms)
1292 struct dev_context *devc;
1293 gint64 deadline, delay;
1294 struct wait_state *state;
1297 state = &devc->wait_state;
1298 state->response_count = 0;
1300 deadline = g_get_monotonic_time();
1301 deadline += timeout_ms * 1000;
1304 gboolean got_wanted;
1305 if (g_get_monotonic_time() >= deadline)
1310 ut181a_handle_events(-1, G_IO_IN, (void *)sdi);
1312 if (state->want_code && state->got_code)
1314 if (state->want_data && state->got_data)
1316 if (state->want_rsp_type && state->got_rsp_type)
1318 if (state->want_measure && state->got_measure)
1320 if (state->want_data == CMD_CODE_GET_RECS_COUNT && state->got_rec_count)
1322 if (state->want_data == CMD_CODE_GET_SAVED_COUNT && state->got_save_count)
1324 if (state->want_data == CMD_CODE_GET_REC_INFO && state->got_sample_count)
1332 * Get measurement value and precision details from protocol's raw bytes.
1334 static int ut181a_get_value_params(struct value_params *params, float value, uint8_t prec)
1340 memset(params, 0, sizeof(*params));
1341 params->value = value;
1342 params->digits = (prec >> 4) & 0x0f;
1343 params->ol_neg = (prec & (1 << 1)) ? 1 : 0;
1344 params->ol_pos = (prec & (1 << 0)) ? 1 : 0;
1349 static void ut181a_cond_stop_acquisition(struct sr_dev_inst *sdi)
1351 struct dev_context *devc;
1359 if (sdi->status == SR_ST_ACTIVE)
1360 sr_dev_acquisition_stop(sdi);
1364 * Send meta packet with samplerate to the session feed.
1366 * @param[in] sdi The device instance.
1367 * @param[in] interval The sample interval in seconds.
1369 * @returns SR_OK upon success, SR_ERR_* upon error.
1371 * The DMM records data at intervals which are multiples of seconds.
1372 * The @ref SR_CONF_SAMPLERATE key cannot express the rate values which
1373 * are below 1Hz. Instead the @ref SR_CONF_SAMPLE_INTERVAL key is sent,
1374 * which applications may or may not support.
1376 static int ut181a_feed_send_rate(struct sr_dev_inst *sdi, int interval)
1379 return sr_session_send_meta(sdi,
1380 SR_CONF_SAMPLE_INTERVAL, g_variant_new_uint64(interval));
1385 * In theory we know the sample interval, and could provide a
1386 * corresponding sample rate. In practice the interval has a
1387 * resolution of seconds, which translates to rates below 1Hz,
1388 * which we cannot express. So let's keep the routine here for
1389 * awareness, and send a rate of 0.
1394 return sr_session_send_meta(sdi,
1395 SR_CONF_SAMPLERATE, g_variant_new_uint64(rate));
1400 * Initialize session feed buffer before submission of values.
1402 static int ut181a_feedbuff_initialize(struct feed_buffer *buff)
1405 memset(buff, 0, sizeof(*buff));
1408 * NOTE: The 'digits' fields get updated later from sample data.
1409 * As do the MQ and unit fields and the channel list.
1411 memset(&buff->packet, 0, sizeof(buff->packet));
1412 sr_analog_init(&buff->analog, &buff->encoding, &buff->meaning, &buff->spec, 0);
1413 buff->analog.meaning->mq = 0;
1414 buff->analog.meaning->mqflags = 0;
1415 buff->analog.meaning->unit = 0;
1416 buff->analog.meaning->channels = NULL;
1417 buff->analog.encoding->unitsize = sizeof(buff->main_value);
1418 buff->analog.encoding->digits = 0;
1419 buff->analog.spec->spec_digits = 0;
1420 buff->analog.num_samples = 1;
1421 buff->analog.data = &buff->main_value;
1422 buff->packet.type = SR_DF_ANALOG;
1423 buff->packet.payload = &buff->analog;
1429 * Setup feed buffer's MQ, MQ flags, and unit before submission of values.
1431 static int ut181a_feedbuff_setup_unit(struct feed_buffer *buff, const char *text)
1434 struct mq_scale_params scale;
1436 /* Derive MQ, flags, unit, and scale from caller's unit text. */
1437 ret = ut181a_get_mq_details_from_text(&scale, text);
1440 buff->scale = scale.scale;
1441 buff->analog.meaning->mq = scale.mq;
1442 buff->analog.meaning->mqflags = scale.mqflags;
1443 buff->analog.meaning->unit = scale.unit;
1449 * Setup feed buffer's measurement value details before submission of values.
1451 static int ut181a_feedbuff_setup_value(struct feed_buffer *buff,
1452 struct value_params *value)
1455 if (!buff || !value)
1459 value->value *= pow(10, buff->scale);
1460 value->digits += -buff->scale;
1463 value->value = -INFINITY;
1465 value->value = +INFINITY;
1467 buff->main_value = value->value;
1468 buff->analog.encoding->digits = value->digits;
1469 buff->analog.spec->spec_digits = value->digits;
1475 * Setup feed buffer's channel before submission of values.
1477 static int ut181a_feedbuff_setup_channel(struct feed_buffer *buff,
1478 enum ut181a_channel_idx ch, struct sr_dev_inst *sdi)
1483 if (!buff->analog.meaning)
1486 g_slist_free(buff->analog.meaning->channels);
1487 buff->analog.meaning->channels = g_slist_append(NULL,
1488 g_slist_nth_data(sdi->channels, ch));
1494 * Send previously configured feed buffer's content to the session.
1496 static int ut181a_feedbuff_send_feed(struct feed_buffer *buff,
1497 struct sr_dev_inst *sdi, size_t count)
1500 struct dev_context *devc;
1505 if (sdi->status != SR_ST_ACTIVE)
1508 if (!devc || devc->disable_feed)
1511 ret = sr_session_send(sdi, &buff->packet);
1512 if (ret == SR_OK && count && sdi->priv) {
1513 sr_sw_limits_update_samples_read(&devc->limits, count);
1514 if (sr_sw_limits_check(&devc->limits))
1515 ut181a_cond_stop_acquisition(sdi);
1522 * Release previously allocated resources in the feed buffer.
1524 static int ut181a_feedbuff_cleanup(struct feed_buffer *buff)
1529 if (buff->analog.meaning)
1530 g_slist_free(buff->analog.meaning->channels);
1535 static int ut181a_feedbuff_start_frame(struct sr_dev_inst *sdi)
1537 struct dev_context *devc;
1541 if (devc->disable_feed)
1543 if (devc->frame_started)
1546 ret = std_session_send_df_frame_begin(sdi);
1548 devc->frame_started = TRUE;
1553 static int ut181a_feedbuff_count_frame(struct sr_dev_inst *sdi)
1555 struct dev_context *devc;
1559 if (devc->disable_feed)
1561 if (!devc->frame_started)
1564 ret = std_session_send_df_frame_end(sdi);
1567 devc->frame_started = FALSE;
1569 sr_sw_limits_update_frames_read(&devc->limits, 1);
1570 if (sr_sw_limits_check(&devc->limits))
1571 ut181a_cond_stop_acquisition(sdi);
1576 /* Deserializing helpers which also advance the read pointer. */
1578 static int check_len(size_t *got, size_t want)
1589 static void advance_len(const uint8_t **p, size_t *l, size_t sz)
1598 static int consume_u8(uint8_t *v, const uint8_t **p, size_t *l)
1606 sz = sizeof(uint8_t);
1607 ret = check_len(l, sz);
1613 advance_len(p, l, sz);
1618 static int consume_u16(uint16_t *v, const uint8_t **p, size_t *l)
1626 sz = sizeof(uint16_t);
1627 ret = check_len(l, sz);
1633 advance_len(p, l, sz);
1638 static int consume_u32(uint32_t *v, const uint8_t **p, size_t *l)
1646 sz = sizeof(uint32_t);
1647 ret = check_len(l, sz);
1653 advance_len(p, l, sz);
1658 static int consume_flt(float *v, const uint8_t **p, size_t *l)
1667 ret = check_len(l, sz);
1673 advance_len(p, l, sz);
1679 * Fills the caller's text buffer from input data. Also trims and NUL
1680 * terminates the buffer content so that callers don't have to.
1682 static int consume_str(char *buff, size_t sz, const uint8_t **p, size_t *l)
1690 ret = check_len(l, sz);
1695 * Quickly grab current position. Immediate bailout if there is
1696 * no caller buffer to fill in. Simpilifies the remaining logic.
1698 v = (const char *)*p;
1699 advance_len(p, l, sz);
1704 * Trim leading space off the input text. Then copy the remaining
1705 * input data to the caller's buffer. This operation is bounded,
1706 * and adds the NUL termination. Then trim trailing space.
1708 * The resulting buffer content is known to be NUL terminated.
1709 * It has at most the requested size (modulo the termination).
1710 * The content may be empty, which can be acceptable to callers.
1711 * So these need to check for and handle that condition.
1713 memset(buff, 0, sz);
1714 while (sz && isspace(*v)) {
1719 snprintf(buff, sz, "%s", v);
1722 while (sz && isspace(buff[sz - 1])) {
1729 /* Process a DMM packet (a frame in the serial protocol). */
1730 static int process_packet(struct sr_dev_inst *sdi, uint8_t *pkt, size_t len)
1732 struct dev_context *devc;
1733 struct wait_state *state;
1734 struct ut181a_info *info;
1735 uint16_t got_magic, got_length, got_cs, want_cs;
1736 const uint8_t *cs_data, *payload;
1737 size_t cs_dlen, pl_dlen;
1739 enum sr_mqflag add_mqflags;
1740 char unit_buff[8], rec_name_buff[11];
1741 const char *unit_text, *rec_name;
1742 struct feed_buffer feedbuff;
1743 struct value_params value;
1744 const struct mqopt_item *mqitem;
1746 uint8_t v8; uint16_t v16; uint32_t v32; float vf;
1749 * Cope with different calling contexts. The packet parser can
1750 * get invoked outside of data acquisition, during preparation
1751 * or in shutdown paths.
1753 devc = sdi ? sdi->priv : NULL;
1754 state = devc ? &devc->wait_state : NULL;
1755 info = devc ? &devc->info : NULL;
1756 if (FRAME_DUMP_FRAME && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
1758 spew = sr_hexdump_new(pkt, len);
1759 FRAME_DUMP_CALL("RX frame, %zu bytes: %s", len, spew->str);
1760 sr_hexdump_free(spew);
1764 * Check the frame envelope. Redundancy with common reception
1765 * logic is perfectly fine. Several code paths end up here, we
1766 * need to gracefully deal with incomplete or incorrect data.
1768 * This stage uses random access to arbitrary positions in the
1769 * packet which surround the payload. Before the then available
1770 * payload gets consumed in a strict serial manner.
1772 if (len < 3 * sizeof(uint16_t)) {
1773 /* Need at least magic, length, checksum. */
1774 if (FRAME_DUMP_CSUM) {
1775 FRAME_DUMP_CALL("Insufficient frame data, need %zu, got %zu.",
1776 3 * sizeof(uint16_t), len);
1781 got_magic = RL16(&pkt[0]);
1782 if (got_magic != FRAME_MAGIC) {
1783 if (FRAME_DUMP_CSUM) {
1784 FRAME_DUMP_CALL("Frame magic mismatch, want 0x%04x, got 0x%04x.",
1785 (unsigned int)FRAME_MAGIC, (unsigned int)got_magic);
1790 got_length = RL16(&pkt[sizeof(uint16_t)]);
1791 if (got_length != len - 2 * sizeof(uint16_t)) {
1792 if (FRAME_DUMP_CSUM) {
1793 FRAME_DUMP_CALL("Frame length mismatch, want %zu, got %u.",
1794 len - 2 * sizeof(uint16_t), got_length);
1799 payload = &pkt[2 * sizeof(uint16_t)];
1800 pl_dlen = got_length - sizeof(uint16_t);
1802 cs_data = &pkt[sizeof(uint16_t)];
1803 cs_dlen = len - 2 * sizeof(uint16_t);
1804 want_cs = ut181a_checksum(cs_data, cs_dlen);
1805 got_cs = RL16(&pkt[len - sizeof(uint16_t)]);
1806 if (got_cs != want_cs) {
1807 if (FRAME_DUMP_CSUM) {
1808 FRAME_DUMP_CALL("Frame checksum mismatch, want 0x%04x, got 0x%04x.",
1809 (unsigned int)want_cs, (unsigned int)got_cs);
1814 state->response_count++;
1815 if (FRAME_DUMP_BYTES && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
1817 spew = sr_hexdump_new(payload, pl_dlen);
1818 FRAME_DUMP_CALL("RX payload, %zu bytes: %s", pl_dlen, spew->str);
1819 sr_hexdump_free(spew);
1823 * Interpret the frame's payload data. The first byte contains
1824 * a packet type which specifies how to interpret the remainder.
1826 ret = consume_u8(&v8, &payload, &pl_dlen);
1828 sr_err("Insufficient payload data, need packet type.");
1833 info->rsp_head.rsp_type = rsp_type;
1837 case RSP_TYPE_REPLY_CODE:
1839 * Reply code: One 16bit item with either 'OK' or 'ER'
1840 * "string literals" to communicate boolean state.
1842 ret = consume_u16(&v16, &payload, &pl_dlen);
1846 info->reply_code.code = v16;
1847 info->reply_code.ok = v16 == REPLY_CODE_OK;
1849 if (state && state->want_code) {
1850 state->got_code = TRUE;
1851 state->code_ok = v16 == REPLY_CODE_OK;
1856 * Saved measurement: A 32bit timestamp, followed by a
1857 * measurement (FALLTHROUGH).
1859 ret = consume_u32(&v32, &payload, &pl_dlen);
1863 info->save_time.stamp = v32;
1864 v32 = ut181a_get_epoch_for_timestamp(v32);
1866 info->save_time.epoch = v32;
1868 #if UT181A_WITH_TIMESTAMP
1870 ret = ut181a_feedbuff_start_frame(sdi);
1874 ret |= ut181a_feedbuff_initialize(&feedbuff);
1875 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_TIME, sdi);
1876 ret |= ut181a_feedbuff_setup_unit(&feedbuff, "timestamp");
1877 ret |= ut181a_get_value_params(&value, v32, 0x00);
1878 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
1879 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
1880 ret |= ut181a_feedbuff_cleanup(&feedbuff);
1886 info->save_info.save_idx++;
1889 case RSP_TYPE_MEASUREMENT:
1891 * A measurement. Starts with a common header, which
1892 * specifies the layout of the remainder (variants, with
1893 * optional fields, depending on preceeding fields).
1895 * Only useful to process when 'info' (and thus 'devc')
1902 * Get the header fields (misc1, misc2, mode, and range),
1903 * derive local packet type details and flags from them.
1905 ret = consume_u8(&v8, &payload, &pl_dlen);
1908 info->meas_head.misc1 = v8;
1909 info->meas_head.has_hold = (v8 & 0x80) ? 1 : 0;
1910 info->meas_head.is_type = (v8 & 0x70) >> 4;
1911 info->meas_head.is_norm = (info->meas_head.is_type == 0) ? 1 : 0;
1912 info->meas_head.is_rel = (info->meas_head.is_type == 1) ? 1 : 0;
1913 info->meas_head.is_minmax = (info->meas_head.is_type == 2) ? 1 : 0;
1914 info->meas_head.is_peak = (info->meas_head.is_type == 4) ? 1 : 0;
1915 info->meas_head.has_bar = (v8 & 0x8) ? 1 : 0;
1916 info->meas_head.has_aux2 = (v8 & 0x4) ? 1 : 0;
1917 info->meas_head.has_aux1 = (v8 & 0x2) ? 1 : 0;
1919 ret = consume_u8(&v8, &payload, &pl_dlen);
1922 info->meas_head.misc2 = v8;
1923 info->meas_head.is_rec = (v8 & 0x20) ? 1 : 0;
1925 devc->is_recording = info->meas_head.is_rec;
1926 info->meas_head.is_comp = (v8 & 0x10) ? 1 : 0;
1927 info->meas_head.has_lead_err = (v8 & 0x8) ? 1 : 0;
1928 info->meas_head.has_high_volt = (v8 & 0x2) ? 1 : 0;
1929 info->meas_head.is_auto_range = (v8 & 0x1) ? 1 : 0;
1931 ret = consume_u16(&v16, &payload, &pl_dlen);
1934 info->meas_head.mode = v16;
1935 mqitem = ut181a_get_mqitem_from_mode(v16);
1936 if (!mqitem || !mqitem->mq)
1938 add_mqflags |= mqitem->mqflags;
1939 if (info->meas_head.has_hold)
1940 add_mqflags |= SR_MQFLAG_HOLD;
1941 if (info->meas_head.is_auto_range)
1942 add_mqflags |= SR_MQFLAG_AUTORANGE;
1943 if (add_mqflags & SR_MQFLAG_DIODE)
1944 add_mqflags |= SR_MQFLAG_DC;
1946 ret = consume_u8(&v8, &payload, &pl_dlen);
1949 info->meas_head.range = v8;
1951 if (state && state->want_measure)
1952 state->got_measure = TRUE;
1954 ret = ut181a_feedbuff_start_frame(sdi);
1959 * The remaining measurement's layout depends on type.
1960 * - Normal measurement:
1961 * - Main value (4/1/8 value/precision/unit).
1962 * - Aux1 value (4/1/8 value/precision/unit) when AUX1
1964 * - Aux2 value (4/1/8 value/precision/unit) when AUX2
1966 * - Bargraph (4/8 value/unit) when BAR flag active.
1967 * - COMP result when COMP flag active.
1968 * - Always 1/1/1/4 mode/flags/digits/limit: type
1969 * of check, PASS/FAIL verdict, limit values'
1970 * precision, upper or only limit.
1971 * - Conditional 4 limit: Lower limit for checks
1972 * which involve two limit values.
1973 * - Relative measurement:
1974 * - Relative value (4/1/8 value/precision/unit).
1975 * - Reference value (4/1/8 value/precision/unit),
1976 * when AUX1 active (practically always).
1977 * - Absolute value (4/1/8 value/precision/unit),
1978 * when AUX2 active (practically always).
1979 * - Bargraph (4/8 value/unit) when BAR flag active.
1980 * - Min/Max measurement:
1981 * - All fields always present, no conditions.
1982 * - One common unit spec at the end which applies to
1983 * all curr/max/avg/min values.
1984 * - Current value (4/1 value/precision).
1985 * - Maximum value (4/1/4 value/precision/time).
1986 * - Average value (4/1/4 value/precision/time).
1987 * - Minimum value (4/1/4 value/precision/time).
1988 * - Common unit text (8).
1989 * - Peak measurement:
1990 * - All fields always present.
1991 * - Maximum value (4/1/8 value/precision/unit).
1992 * - Minimum value (4/1/8 value/precision/unit).
1994 ret = ut181a_feedbuff_initialize(&feedbuff);
1995 if (info->meas_head.is_norm) {
1996 /* Main value, unconditional. Get details. */
1997 ret = consume_flt(&vf, &payload, &pl_dlen);
2000 info->meas_data.norm.main_value = vf;
2001 ret = consume_u8(&v8, &payload, &pl_dlen);
2004 info->meas_data.norm.main_prec = v8;
2005 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2006 unit_text = &unit_buff[0];
2009 snprintf(info->meas_data.norm.main_unit,
2010 sizeof(info->meas_data.norm.main_unit),
2012 unit_text = info->meas_data.norm.main_unit;
2014 /* Submit main value to session feed. */
2016 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_MAIN, sdi);
2017 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2018 feedbuff.analog.meaning->mqflags |= add_mqflags;
2019 ret |= ut181a_get_value_params(&value, vf, v8);
2020 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2021 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 1);
2025 if (info->meas_head.is_norm && info->meas_head.has_aux1) {
2026 /* Aux1 value, optional. Get details. */
2027 ret = consume_flt(&vf, &payload, &pl_dlen);
2030 info->meas_data.norm.aux1_value = vf;
2031 ret = consume_u8(&v8, &payload, &pl_dlen);
2034 info->meas_data.norm.aux1_prec = v8;
2035 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2036 unit_text = &unit_buff[0];
2039 snprintf(info->meas_data.norm.aux1_unit,
2040 sizeof(info->meas_data.norm.aux1_unit),
2042 unit_text = info->meas_data.norm.aux1_unit;
2044 /* Submit aux1 value to session feed. */
2046 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX1, sdi);
2047 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2048 ret |= ut181a_get_value_params(&value, vf, v8);
2049 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2050 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2054 if (info->meas_head.is_norm && info->meas_head.has_aux2) {
2055 /* Aux2 value, optional. Get details. */
2056 ret = consume_flt(&vf, &payload, &pl_dlen);
2059 info->meas_data.norm.aux2_value = vf;
2060 ret = consume_u8(&v8, &payload, &pl_dlen);
2063 info->meas_data.norm.aux2_prec = v8;
2064 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2065 unit_text = &unit_buff[0];
2068 snprintf(info->meas_data.norm.aux2_unit,
2069 sizeof(info->meas_data.norm.aux2_unit),
2071 unit_text = info->meas_data.norm.aux2_unit;
2073 /* Submit aux2 value to session feed. */
2075 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX2, sdi);
2076 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2077 ret |= ut181a_get_value_params(&value, vf, v8);
2078 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2079 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2083 if (info->meas_head.is_norm && info->meas_head.has_bar) {
2084 /* Bargraph value, optional. */
2085 ret = consume_flt(&vf, &payload, &pl_dlen);
2088 info->meas_data.norm.bar_value = vf;
2089 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2090 unit_text = &unit_buff[0];
2093 snprintf(info->meas_data.norm.bar_unit,
2094 sizeof(info->meas_data.norm.bar_unit),
2096 unit_text = info->meas_data.norm.bar_unit;
2098 /* Submit bargraph value to session feed. */
2100 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_BAR, sdi);
2101 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2102 ret |= ut181a_get_value_params(&value, vf, 0x00);
2103 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2104 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2108 if (info->meas_head.is_norm && info->meas_head.is_comp) {
2109 /* COMP result, optional. Get details. */
2110 ret = consume_u8(&v8, &payload, &pl_dlen);
2113 if (v8 > COMP_MODE_ABOVE)
2115 info->meas_data.comp.mode = v8;
2116 ret = consume_u8(&v8, &payload, &pl_dlen);
2119 info->meas_data.comp.fail = v8 ? TRUE : FALSE;
2120 ret = consume_u8(&v8, &payload, &pl_dlen);
2123 info->meas_data.comp.digits = v8 & 0x0f;
2124 ret = consume_flt(&vf, &payload, &pl_dlen);
2127 info->meas_data.comp.limit_high = vf;
2128 if (info->meas_data.comp.mode <= COMP_MODE_OUTER) {
2129 ret = consume_flt(&vf, &payload, &pl_dlen);
2132 info->meas_data.comp.limit_low = vf;
2136 * How to present this result to the feed? This
2137 * implementation extracts and interprets the
2138 * fields, but does not pass the values to the
2139 * session. Which MQ to use for PASS/FAIL checks?
2141 static const char *mode_text[] = {
2142 [COMP_MODE_INNER] = "INNER",
2143 [COMP_MODE_OUTER] = "OUTER",
2144 [COMP_MODE_BELOW] = "BELOW",
2145 [COMP_MODE_ABOVE] = "ABOVE",
2148 if (info->meas_data.comp.mode <= COMP_MODE_OUTER) {
2149 sr_dbg("Unprocessed COMP result:"
2150 " mode %s, %s, digits %d, low %f, high %f",
2151 mode_text[info->meas_data.comp.mode],
2152 info->meas_data.comp.fail ? "FAIL" : "PASS",
2153 info->meas_data.comp.digits,
2154 info->meas_data.comp.limit_low,
2155 info->meas_data.comp.limit_high);
2157 sr_dbg("Unprocessed COMP result:"
2158 " mode %s, %s, digits %d, limit %f",
2159 mode_text[info->meas_data.comp.mode],
2160 info->meas_data.comp.fail ? "FAIL" : "PASS",
2161 info->meas_data.comp.digits,
2162 info->meas_data.comp.limit_high);
2165 if (info->meas_head.is_norm) {
2166 /* Normal measurement code path done. */
2167 ret = ut181a_feedbuff_cleanup(&feedbuff);
2168 ret = ut181a_feedbuff_count_frame(sdi);
2174 if (info->meas_head.is_rel) {
2175 /* Relative value, unconditional. Get details. */
2176 ret = consume_flt(&vf, &payload, &pl_dlen);
2179 info->meas_data.rel.rel_value = vf;
2180 ret = consume_u8(&v8, &payload, &pl_dlen);
2183 info->meas_data.rel.rel_prec = v8;
2184 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2185 unit_text = &unit_buff[0];
2188 snprintf(info->meas_data.rel.rel_unit,
2189 sizeof(info->meas_data.rel.rel_unit),
2191 unit_text = info->meas_data.rel.rel_unit;
2193 /* Submit relative value to session feed. */
2195 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_MAIN, sdi);
2196 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2197 feedbuff.analog.meaning->mqflags |= add_mqflags;
2198 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_RELATIVE;
2199 ret |= ut181a_get_value_params(&value, vf, v8);
2200 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2201 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 1);
2205 if (info->meas_head.is_rel && info->meas_head.has_aux1) {
2206 /* Reference value, "conditional" in theory. */
2207 ret = consume_flt(&vf, &payload, &pl_dlen);
2210 info->meas_data.rel.ref_value = vf;
2211 ret = consume_u8(&v8, &payload, &pl_dlen);
2214 info->meas_data.rel.ref_prec = v8;
2215 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2216 unit_text = &unit_buff[0];
2219 snprintf(info->meas_data.rel.ref_unit,
2220 sizeof(info->meas_data.rel.ref_unit),
2222 unit_text = info->meas_data.rel.ref_unit;
2224 /* Submit reference value to session feed. */
2226 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX1, sdi);
2227 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2228 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_REFERENCE;
2229 ret |= ut181a_get_value_params(&value, vf, v8);
2230 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2231 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2235 if (info->meas_head.is_rel && info->meas_head.has_aux2) {
2236 /* Absolute value, "conditional" in theory. */
2237 ret = consume_flt(&vf, &payload, &pl_dlen);
2240 info->meas_data.rel.abs_value = vf;
2241 ret = consume_u8(&v8, &payload, &pl_dlen);
2244 info->meas_data.rel.abs_prec = v8;
2245 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2246 unit_text = &unit_buff[0];
2249 snprintf(info->meas_data.rel.abs_unit,
2250 sizeof(info->meas_data.rel.abs_unit),
2252 unit_text = info->meas_data.rel.abs_unit;
2254 /* Submit absolute value to session feed. */
2256 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX2, sdi);
2257 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2258 ret |= ut181a_get_value_params(&value, vf, v8);
2259 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2260 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2264 if (info->meas_head.is_rel && info->meas_head.has_bar) {
2265 /* Bargraph value, conditional. */
2266 ret = consume_flt(&vf, &payload, &pl_dlen);
2269 info->meas_data.rel.bar_value = vf;
2270 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2271 unit_text = &unit_buff[0];
2274 snprintf(info->meas_data.rel.bar_unit,
2275 sizeof(info->meas_data.rel.bar_unit),
2277 unit_text = info->meas_data.rel.bar_unit;
2279 /* Submit bargraph value to session feed. */
2281 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_BAR, sdi);
2282 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2283 ret |= ut181a_get_value_params(&value, vf, 0x00);
2284 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2285 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2289 if (info->meas_head.is_rel) {
2290 /* Relative measurement code path done. */
2291 ret = ut181a_feedbuff_cleanup(&feedbuff);
2292 ret = ut181a_feedbuff_count_frame(sdi);
2298 if (info->meas_head.is_minmax) {
2300 * Min/max measurement values, none of them are
2301 * conditional in practice (all are present).
2302 * This is special in that all of curr, max, avg,
2303 * and min values share the same unit text which
2304 * is only at the end of the data fields.
2307 ret |= consume_flt(&info->meas_data.minmax.curr_value, &payload, &pl_dlen);
2308 ret |= consume_u8(&info->meas_data.minmax.curr_prec, &payload, &pl_dlen);
2309 ret |= consume_flt(&info->meas_data.minmax.max_value, &payload, &pl_dlen);
2310 ret |= consume_u8(&info->meas_data.minmax.max_prec, &payload, &pl_dlen);
2311 ret |= consume_u32(&info->meas_data.minmax.max_stamp, &payload, &pl_dlen);
2312 ret |= consume_flt(&info->meas_data.minmax.avg_value, &payload, &pl_dlen);
2313 ret |= consume_u8(&info->meas_data.minmax.avg_prec, &payload, &pl_dlen);
2314 ret |= consume_u32(&info->meas_data.minmax.avg_stamp, &payload, &pl_dlen);
2315 ret |= consume_flt(&info->meas_data.minmax.min_value, &payload, &pl_dlen);
2316 ret |= consume_u8(&info->meas_data.minmax.min_prec, &payload, &pl_dlen);
2317 ret |= consume_u32(&info->meas_data.minmax.min_stamp, &payload, &pl_dlen);
2318 ret |= consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2319 unit_text = &unit_buff[0];
2322 snprintf(info->meas_data.minmax.all_unit,
2323 sizeof(info->meas_data.minmax.all_unit),
2325 unit_text = info->meas_data.minmax.all_unit;
2327 /* Submit the current value. */
2328 vf = info->meas_data.minmax.curr_value;
2329 v8 = info->meas_data.minmax.curr_prec;
2331 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_MAIN, sdi);
2332 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2333 feedbuff.analog.meaning->mqflags |= add_mqflags;
2334 ret |= ut181a_get_value_params(&value, vf, v8);
2335 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2336 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 1);
2340 /* Submit the maximum value. */
2341 vf = info->meas_data.minmax.max_value;
2342 v8 = info->meas_data.minmax.max_prec;
2344 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX1, sdi);
2345 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2346 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_MAX;
2347 ret |= ut181a_get_value_params(&value, vf, v8);
2348 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2349 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2353 /* Submit the average value. */
2354 vf = info->meas_data.minmax.avg_value;
2355 v8 = info->meas_data.minmax.avg_prec;
2357 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX2, sdi);
2358 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2359 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_AVG;
2360 ret |= ut181a_get_value_params(&value, vf, v8);
2361 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2362 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2366 /* Submit the minimum value. */
2367 vf = info->meas_data.minmax.min_value;
2368 v8 = info->meas_data.minmax.min_prec;
2370 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX3, sdi);
2371 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2372 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_MIN;
2373 ret |= ut181a_get_value_params(&value, vf, v8);
2374 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2375 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2379 if (info->meas_head.is_minmax) {
2380 /* Min/max measurement code path done. */
2381 ret = ut181a_feedbuff_cleanup(&feedbuff);
2382 ret = ut181a_feedbuff_count_frame(sdi);
2388 if (info->meas_head.is_peak) {
2389 /* Maximum value, unconditional. Get details. */
2390 ret = consume_flt(&vf, &payload, &pl_dlen);
2393 info->meas_data.peak.max_value = vf;
2394 ret = consume_u8(&v8, &payload, &pl_dlen);
2397 info->meas_data.peak.max_prec = v8;
2398 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2399 unit_text = &unit_buff[0];
2402 snprintf(info->meas_data.peak.max_unit,
2403 sizeof(info->meas_data.peak.max_unit),
2405 unit_text = info->meas_data.peak.max_unit;
2407 /* Submit max value to session feed. */
2409 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX1, sdi);
2410 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2411 feedbuff.analog.meaning->mqflags |= add_mqflags; /* ??? */
2412 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_MAX;
2413 ret |= ut181a_get_value_params(&value, vf, v8);
2414 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2415 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 1);
2419 /* Minimum value, unconditional. Get details. */
2420 ret = consume_flt(&vf, &payload, &pl_dlen);
2423 info->meas_data.peak.min_value = vf;
2424 ret = consume_u8(&v8, &payload, &pl_dlen);
2427 info->meas_data.peak.min_prec = v8;
2428 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2429 unit_text = &unit_buff[0];
2432 snprintf(info->meas_data.peak.min_unit,
2433 sizeof(info->meas_data.peak.min_unit),
2435 unit_text = info->meas_data.peak.min_unit;
2437 /* Submit min value to session feed. */
2439 ret |= ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_AUX3, sdi);
2440 ret |= ut181a_feedbuff_setup_unit(&feedbuff, unit_text);
2441 feedbuff.analog.meaning->mqflags |= SR_MQFLAG_MIN;
2442 ret |= ut181a_get_value_params(&value, vf, v8);
2443 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2444 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 0);
2448 if (info->meas_head.is_peak) {
2449 /* Relative measurement code path done. */
2450 ret = ut181a_feedbuff_cleanup(&feedbuff);
2451 ret = ut181a_feedbuff_count_frame(sdi);
2457 /* ShouldNeverHappen(TM) */
2458 sr_dbg("Unhandled measurement type.");
2461 case RSP_TYPE_REC_INFO:
2463 * Not useful to process without 'devc' or 'info'.
2464 * The caller provided the recording's index (the
2465 * protocol won't in the response).
2471 * Record information:
2472 * - User specified recording's name (11 ASCIIZ chars).
2474 * - Interval, duration, sample count (2/4/4).
2475 * - Max/avg/min values and precision (4+1/4+1/4+1).
2476 * - Time when recording started (4).
2478 * Notice that the recording name needs to get trimmed
2479 * due to limited text editing capabilities of the DMM
2480 * UI. The name need not be unique, and typically isn't
2481 * (again: because of limited editing, potential numbers
2482 * in names are not auto incremented in the firmware).
2484 ret = consume_str(&rec_name_buff[0], 11, &payload, &pl_dlen);
2485 rec_name = &rec_name_buff[0];
2490 snprintf(devc->record_names[info->rec_info.rec_idx],
2491 sizeof(devc->record_names[info->rec_info.rec_idx]),
2493 snprintf(info->rec_info.name, sizeof(info->rec_info.name),
2495 ret = consume_str(&unit_buff[0], 8, &payload, &pl_dlen);
2496 unit_text = &unit_buff[0];
2499 snprintf(info->rec_info.unit,
2500 sizeof(info->rec_info.unit),
2502 unit_text = info->rec_info.unit;
2504 ret |= consume_u16(&info->rec_info.interval, &payload, &pl_dlen);
2505 ret |= consume_u32(&info->rec_info.duration, &payload, &pl_dlen);
2506 ret |= consume_u32(&info->rec_info.samples, &payload, &pl_dlen);
2507 ret |= consume_flt(&info->rec_info.max_value, &payload, &pl_dlen);
2508 ret |= consume_u8(&info->rec_info.max_prec, &payload, &pl_dlen);
2509 ret |= consume_flt(&info->rec_info.avg_value, &payload, &pl_dlen);
2510 ret |= consume_u8(&info->rec_info.avg_prec, &payload, &pl_dlen);
2511 ret |= consume_flt(&info->rec_info.min_value, &payload, &pl_dlen);
2512 ret |= consume_u8(&info->rec_info.min_prec, &payload, &pl_dlen);
2513 ret |= consume_u32(&v32, &payload, &pl_dlen);
2516 info->rec_info.start_stamp = ut181a_get_epoch_for_timestamp(v32);
2519 * Cheat, provide sample count as if it was reply data.
2520 * Some api.c code paths assume to find this detail there.
2521 * Keep the last unit text at hand, subsequent reception
2522 * of record data will reference it.
2524 if (state && state->want_data == CMD_CODE_GET_REC_INFO) {
2525 state->got_sample_count = TRUE;
2526 state->data_value = info->rec_info.samples;
2528 snprintf(devc->last_data.unit_text,
2529 sizeof(devc->last_data.unit_text),
2533 * Optionally automatically forward the sample interval
2534 * to the session feed, before record data is sent.
2536 if (devc->info.rec_info.auto_feed) {
2537 ret = ut181a_feed_send_rate(sdi, info->rec_info.interval);
2542 case RSP_TYPE_REC_DATA:
2544 * We expect record data only during acquisitions from
2545 * that data source, and depend on being able to feed
2546 * data to the session.
2548 if (sdi->status != SR_ST_ACTIVE)
2550 if (!devc || devc->disable_feed || !info)
2552 ret = ut181a_feedbuff_initialize(&feedbuff);
2553 ret = ut181a_feedbuff_setup_channel(&feedbuff, UT181A_CH_MAIN, sdi);
2554 ret = ut181a_feedbuff_setup_unit(&feedbuff, devc->last_data.unit_text);
2558 * - u8 sample count for this data chunk, then the
2559 * corresponding number of samples, each is 9 bytes:
2564 ret = consume_u8(&info->rec_data.samples_chunk, &payload, &pl_dlen);
2567 info->rec_data.samples_curr += info->rec_data.samples_chunk;
2568 while (info->rec_data.samples_chunk--) {
2570 * Implementation detail: Consume all received
2571 * data, yet skip processing when a limit was
2572 * reached and previously terminated acquisition.
2575 ret |= consume_flt(&vf, &payload, &pl_dlen);
2576 ret |= consume_u8(&v8, &payload, &pl_dlen);
2577 ret |= consume_u32(&v32, &payload, &pl_dlen);
2581 if (sdi->status != SR_ST_ACTIVE)
2584 ret = ut181a_feedbuff_start_frame(sdi);
2589 ret |= ut181a_get_value_params(&value, vf, v8);
2590 ret |= ut181a_feedbuff_setup_value(&feedbuff, &value);
2591 ret |= ut181a_feedbuff_send_feed(&feedbuff, sdi, 1);
2595 ret = ut181a_feedbuff_count_frame(sdi);
2599 ret = ut181a_feedbuff_cleanup(&feedbuff);
2602 case RSP_TYPE_REPLY_DATA:
2604 * Reply data. Generic 16bit value preceeded by 8bit
2608 ret |= consume_u8(&v8, &payload, &pl_dlen);
2609 ret |= consume_u16(&v16, &payload, &pl_dlen);
2613 info->reply_data.code = v8;
2614 info->reply_data.data = v16;
2616 if (state && state->want_data && state->want_data == v8) {
2617 state->got_data = TRUE;
2618 state->data_value = v16;
2619 if (v8 == CMD_CODE_GET_RECS_COUNT)
2620 state->got_rec_count = TRUE;
2621 if (v8 == CMD_CODE_GET_SAVED_COUNT)
2622 state->got_save_count = TRUE;
2623 if (v8 == CMD_CODE_GET_REC_INFO)
2624 state->got_sample_count = TRUE;
2629 if (FRAME_DUMP_PARSE)
2630 FRAME_DUMP_CALL("Unhandled response type 0x%02x", rsp_type);
2633 if (state && state->want_rsp_type == rsp_type)
2634 state->got_rsp_type = TRUE;
2635 if (FRAME_DUMP_REMAIN && pl_dlen) {
2637 txt = sr_hexdump_new(payload, pl_dlen);
2638 FRAME_DUMP_CALL("Unprocessed response data: %s", txt->str);
2639 sr_hexdump_free(txt);
2642 /* Unconditionally check, we may have hit a time limit. */
2643 if (sr_sw_limits_check(&devc->limits)) {
2644 ut181a_cond_stop_acquisition(sdi);
2649 * Only emit next requests for chunked downloads after successful
2650 * reception and consumption of the currently received item(s).
2653 struct sr_serial_dev_inst *serial;
2660 /* Sample count was incremented during reception above. */
2661 if (info->save_info.save_idx >= info->save_info.save_count) {
2662 ut181a_cond_stop_acquisition(sdi);
2665 ret = ut181a_send_cmd_get_saved_value(serial, info->save_info.save_idx);
2667 ut181a_cond_stop_acquisition(sdi);
2669 case RSP_TYPE_REC_DATA:
2673 * The sample count was incremented above during
2674 * reception, because of variable length chunks
2677 if (info->rec_data.samples_curr >= info->rec_data.samples_total) {
2678 ut181a_cond_stop_acquisition(sdi);
2681 ret = ut181a_send_cmd_get_rec_samples(serial,
2682 info->rec_data.rec_idx, info->rec_data.samples_curr);
2684 ut181a_cond_stop_acquisition(sdi);
2695 /* Process a previously received RX buffer. May find none or several packets. */
2696 static int process_buffer(struct sr_dev_inst *sdi)
2698 struct dev_context *devc;
2701 size_t pkt_len, remain, idx;
2707 * Specifically do not insist on finding the packet boundary at
2708 * the edge of the most recently received data chunk. Serial ports
2709 * might involve hardware buffers (FIFO). We want to sync as fast
2712 * Handle the synchronized situation first. Process complete and
2713 * valid packets that reside at the start of the buffer. Continue
2714 * reception when partially valid data was received but does not
2715 * yet span a complete frame. Break out if data was received that
2716 * failed verification. Assume temporary failure and try to sync
2717 * to the input stream again.
2719 * This logic is a little more complex than the typical DMM parser
2720 * because of the variable frame length of the UT181A protocol. A
2721 * frame always contains a magic (u16) and a length (u16), then a
2722 * number of bytes according to length. The frame ends there, the
2723 * checksum field is covered by the length value. packet processing
2724 * will verify the checksum.
2726 pkt = &devc->recv_buff[0];
2728 /* Search for (the start of) a valid packet. */
2729 if (devc->recv_count < 2 * sizeof(uint16_t)) {
2730 /* Need more RX data for magic and length. */
2733 v16 = RL16(&pkt[0]);
2734 if (v16 != FRAME_MAGIC) {
2735 /* Not the expected magic marker. */
2736 if (FRAME_DUMP_CSUM) {
2737 FRAME_DUMP_CALL("Not a frame marker -> re-sync");
2741 v16 = RL16(&pkt[sizeof(uint16_t)]);
2742 if (v16 < sizeof(uint16_t)) {
2743 /* Insufficient length value, need at least checksum. */
2744 if (FRAME_DUMP_CSUM) {
2745 FRAME_DUMP_CALL("Too small a length -> re-sync");
2749 /* TODO Can we expect a maximum length value? */
2750 pkt_len = 2 * sizeof(uint16_t) + v16;
2751 if (pkt_len >= sizeof(devc->recv_buff)) {
2752 /* Frame will never fit in RX buffer. Invalid RX data? */
2753 if (FRAME_DUMP_CSUM) {
2754 FRAME_DUMP_CALL("Excessive length -> re-sync");
2758 if (pkt_len > devc->recv_count) {
2759 /* Need more RX data to complete the frame. */
2763 /* Process the packet which completed reception. */
2764 if (FRAME_DUMP_CSUM && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
2766 spew = sr_hexdump_new(pkt, pkt_len);
2767 FRAME_DUMP_CALL("Found RX frame, %zu bytes: %s", pkt_len, spew->str);
2768 sr_hexdump_free(spew);
2770 ret = process_packet(sdi, pkt, pkt_len);
2771 if (ret == SR_ERR_DATA) {
2772 /* Verification failed, might be invalid RX data. */
2773 if (FRAME_DUMP_CSUM) {
2774 FRAME_DUMP_CALL("RX frame processing failed -> re-sync");
2778 remain = devc->recv_count - pkt_len;
2780 memmove(&pkt[0], &pkt[pkt_len], remain);
2781 devc->recv_count -= pkt_len;
2783 if (devc->recv_count < 2 * sizeof(uint16_t)) {
2784 /* Assume incomplete reception. Re-check later. */
2789 * Data was received but failed the test for a valid frame. Try to
2790 * synchronize to the next frame marker. Make sure to skip the
2791 * current position which might have been a marker yet the frame
2794 if (FRAME_DUMP_CSUM) {
2795 FRAME_DUMP_CALL("Trying to re-sync on RX frame");
2797 for (idx = 1; idx < devc->recv_count; idx++) {
2798 if (devc->recv_count - idx < sizeof(uint16_t)) {
2799 /* Nothing found. Drop all but the last byte here. */
2801 devc->recv_count = 1;
2802 if (FRAME_DUMP_CSUM) {
2803 FRAME_DUMP_CALL("Dropping %zu bytes, still not in sync", idx);
2807 v16 = RL16(&pkt[idx]);
2808 if (v16 != FRAME_MAGIC)
2811 * Found a frame marker at offset 'idx'. Discard data
2812 * before the marker. Next receive starts another attempt
2813 * to interpret the frame, and may search the next marker
2816 if (FRAME_DUMP_CSUM) {
2817 FRAME_DUMP_CALL("Dropping %zu bytes, next marker found", idx);
2819 remain = devc->recv_count - idx;
2821 memmove(&pkt[0], &pkt[idx], remain);
2822 devc->recv_count -= idx;
2829 /* Gets invoked when RX data is available. */
2830 static int ut181a_receive_data(struct sr_dev_inst *sdi)
2832 struct dev_context *devc;
2833 struct sr_serial_dev_inst *serial;
2843 * Discard receive data when the buffer is exhausted. This shall
2844 * allow to (re-)synchronize to the data stream when we find it
2845 * in an arbitrary state. (Takes a while to exhaust the buffer.
2846 * Data is seriously unusable when we get here.)
2848 if (devc->recv_count == sizeof(devc->recv_buff)) {
2849 if (FRAME_DUMP_RXDATA)
2850 FRAME_DUMP_CALL("Discarding RX buffer (space exhausted)");
2851 (void)process_packet(sdi, &devc->recv_buff[0], devc->recv_count);
2852 devc->recv_count = 0;
2856 * Drain more data from the serial port, and check the receive
2857 * buffer for packets. Process what was found to be complete.
2859 len = sizeof(devc->recv_buff) - devc->recv_count;
2860 data = &devc->recv_buff[devc->recv_count];
2861 slen = serial_read_nonblocking(serial, data, len);
2863 if (FRAME_DUMP_RXDATA)
2864 FRAME_DUMP_CALL("UART RX failed, rc %zd", slen);
2868 if (FRAME_DUMP_RXDATA && sr_log_loglevel_get() >= FRAME_DUMP_LEVEL) {
2869 spew = sr_hexdump_new(data, len);
2870 FRAME_DUMP_CALL("UART RX, %zu bytes: %s", len, spew->str);
2871 sr_hexdump_free(spew);
2873 devc->recv_count += len;
2874 process_buffer(sdi);
2879 SR_PRIV int ut181a_handle_events(int fd, int revents, void *cb_data)
2881 struct sr_dev_inst *sdi;
2882 struct sr_serial_dev_inst *serial;
2883 struct dev_context *devc;
2895 if (revents & G_IO_IN)
2896 (void)ut181a_receive_data(sdi);
2898 if (sdi->status == SR_ST_STOPPING) {
2899 if (devc->data_source == DATA_SOURCE_LIVE) {
2900 sdi->status = SR_ST_INACTIVE;
2901 (void)ut181a_send_cmd_monitor(serial, FALSE);
2902 (void)ut181a_waitfor_response(sdi, 100);
2904 serial_source_remove(sdi->session, serial);
2905 std_session_send_df_end(sdi);