]> sigrok.org Git - libsigrok.git/blob - src/hardware/agilent-dmm/protocol.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / agilent-dmm / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
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 <glib.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <limits.h>
26 #include <math.h>
27 #include <libsigrok/libsigrok.h>
28 #include "libsigrok-internal.h"
29 #include "protocol.h"
30
31 #define JOB_TIMEOUT 300
32
33 #define INFINITE_INTERVAL   INT_MAX
34 #define SAMPLERATE_INTERVAL -1
35
36 static const struct agdmm_job *job_current(const struct dev_context *devc)
37 {
38         return &devc->jobs[devc->current_job];
39 }
40
41 static void job_done(struct dev_context *devc)
42 {
43         devc->job_running = FALSE;
44 }
45
46 static void job_again(struct dev_context *devc)
47 {
48         devc->job_again = TRUE;
49 }
50
51 static gboolean job_is_running(const struct dev_context *devc)
52 {
53         return devc->job_running;
54 }
55
56 static gboolean job_in_interval(const struct dev_context *devc)
57 {
58         int64_t job_start = devc->jobs_start[devc->current_job];
59         int64_t now = g_get_monotonic_time() / 1000;
60         int interval = job_current(devc)->interval;
61         if (interval == SAMPLERATE_INTERVAL)
62                 interval = 1000 / devc->cur_samplerate;
63         return (now - job_start) < interval || interval == INFINITE_INTERVAL;
64 }
65
66 static gboolean job_has_timeout(const struct dev_context *devc)
67 {
68         int64_t job_start = devc->jobs_start[devc->current_job];
69         int64_t now = g_get_monotonic_time() / 1000;
70         return job_is_running(devc) && (now - job_start) > JOB_TIMEOUT;
71 }
72
73 static const struct agdmm_job *job_next(struct dev_context *devc)
74 {
75         int current_job = devc->current_job;
76         do {
77                 devc->current_job++;
78                 if (!job_current(devc)->send)
79                         devc->current_job = 0;
80         } while (job_in_interval(devc) && devc->current_job != current_job);
81         return job_current(devc);
82 }
83
84 static void job_run_again(const struct sr_dev_inst *sdi)
85 {
86         struct dev_context *devc = sdi->priv;
87         devc->job_again = FALSE;
88         devc->job_running = TRUE;
89         if (job_current(devc)->send(sdi) == SR_ERR_NA)
90                 job_done(devc);
91 }
92
93 static void job_run(const struct sr_dev_inst *sdi)
94 {
95         struct dev_context *devc = sdi->priv;
96         int64_t now = g_get_monotonic_time() / 1000;
97         devc->jobs_start[devc->current_job] = now;
98         job_run_again(sdi);
99 }
100
101 static void dispatch(const struct sr_dev_inst *sdi)
102 {
103         struct dev_context *devc = sdi->priv;
104
105         if (devc->job_again) {
106                 job_run_again(sdi);
107                 return;
108         }
109
110         if (!job_is_running(devc))
111                 job_next(devc);
112         else if (job_has_timeout(devc))
113                 job_done(devc);
114
115         if (!job_is_running(devc) && !job_in_interval(devc))
116                 job_run(sdi);
117 }
118
119 static gboolean receive_line(const struct sr_dev_inst *sdi)
120 {
121         struct dev_context *devc;
122         const struct agdmm_recv *recvs, *recv;
123         GRegex *reg;
124         GMatchInfo *match;
125         gboolean stop = FALSE;
126         int i;
127
128         devc = sdi->priv;
129
130         /* Strip CRLF */
131         while (devc->buflen) {
132                 if (*(devc->buf + devc->buflen - 1) == '\r'
133                                 || *(devc->buf + devc->buflen - 1) == '\n')
134                         *(devc->buf + --devc->buflen) = '\0';
135                 else
136                         break;
137         }
138         sr_spew("Received '%s'.", devc->buf);
139
140         recv = NULL;
141         recvs = devc->profile->recvs;
142         for (i = 0; (&recvs[i])->recv_regex; i++) {
143                 reg = g_regex_new((&recvs[i])->recv_regex, 0, 0, NULL);
144                 if (g_regex_match(reg, (char *)devc->buf, 0, &match)) {
145                         recv = &recvs[i];
146                         break;
147                 }
148                 g_match_info_unref(match);
149                 g_regex_unref(reg);
150         }
151         if (recv) {
152                 enum job_type type = recv->recv(sdi, match);
153                 if (type == job_current(devc)->type)
154                         job_done(devc);
155                 else if (type == JOB_AGAIN)
156                         job_again(devc);
157                 else if (type == JOB_STOP)
158                         stop = TRUE;
159                 g_match_info_unref(match);
160                 g_regex_unref(reg);
161         } else
162                 sr_dbg("Unknown line '%s'.", devc->buf);
163
164         /* Done with this. */
165         devc->buflen = 0;
166         return stop;
167 }
168
169 SR_PRIV int agdmm_receive_data(int fd, int revents, void *cb_data)
170 {
171         struct sr_dev_inst *sdi;
172         struct dev_context *devc;
173         struct sr_serial_dev_inst *serial;
174         gboolean stop = FALSE;
175         int len;
176
177         (void)fd;
178
179         if (!(sdi = cb_data))
180                 return TRUE;
181
182         if (!(devc = sdi->priv))
183                 return TRUE;
184
185         serial = sdi->conn;
186         if (revents == G_IO_IN) {
187                 /* Serial data arrived. */
188                 while (AGDMM_BUFSIZE - devc->buflen - 1 > 0) {
189                         len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
190                         if (len < 1)
191                                 break;
192                         devc->buflen += len;
193                         *(devc->buf + devc->buflen) = '\0';
194                         if (*(devc->buf + devc->buflen - 1) == '\n') {
195                                 /* End of line */
196                                 stop = receive_line(sdi);
197                                 break;
198                         }
199                 }
200         }
201
202         if (sr_sw_limits_check(&devc->limits) || stop)
203                 sr_dev_acquisition_stop(sdi);
204         else
205                 dispatch(sdi);
206
207         return TRUE;
208 }
209
210 static int agdmm_send(const struct sr_dev_inst *sdi, const char *cmd, ...)
211 {
212         struct sr_serial_dev_inst *serial;
213         va_list args;
214         char buf[32];
215
216         serial = sdi->conn;
217
218         va_start(args, cmd);
219         vsnprintf(buf, sizeof(buf) - 3, cmd, args);
220         va_end(args);
221         sr_spew("Sending '%s'.", buf);
222         if (!strncmp(buf, "*IDN?", 5))
223                 strcat(buf, "\r\n");
224         else
225                 strcat(buf, "\n\r\n");
226         if (serial_write_blocking(serial, buf, strlen(buf), SERIAL_WRITE_TIMEOUT_MS) < (int)strlen(buf)) {
227                 sr_err("Failed to send.");
228                 return SR_ERR;
229         }
230
231         return SR_OK;
232 }
233
234 static int send_stat(const struct sr_dev_inst *sdi)
235 {
236         return agdmm_send(sdi, "STAT?");
237 }
238
239 static int recv_stat_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
240 {
241         struct dev_context *devc;
242         char *s;
243
244         devc = sdi->priv;
245         s = g_match_info_fetch(match, 1);
246         sr_spew("STAT response '%s'.", s);
247
248         /* Max, Min or Avg mode -- no way to tell which, so we'll
249          * set both flags to denote it's not a normal measurement. */
250         if (s[0] == '1')
251                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX | SR_MQFLAG_MIN;
252         else
253                 devc->cur_mqflags[0] &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN);
254
255         if (s[1] == '1')
256                 devc->cur_mqflags[0] |= SR_MQFLAG_RELATIVE;
257         else
258                 devc->cur_mqflags[0] &= ~SR_MQFLAG_RELATIVE;
259
260         /* Triggered or auto hold modes. */
261         if (s[2] == '1' || s[3] == '1')
262                 devc->cur_mqflags[0] |= SR_MQFLAG_HOLD;
263         else
264                 devc->cur_mqflags[0] &= ~SR_MQFLAG_HOLD;
265
266         /* Temp/aux mode. */
267         if (s[7] == '1')
268                 devc->mode_tempaux = TRUE;
269         else
270                 devc->mode_tempaux = FALSE;
271
272         /* Continuity mode. */
273         if (s[16] == '1')
274                 devc->mode_continuity = TRUE;
275         else
276                 devc->mode_continuity = FALSE;
277
278         g_free(s);
279
280         return JOB_STAT;
281 }
282
283 static int recv_stat_u124x(const struct sr_dev_inst *sdi, GMatchInfo *match)
284 {
285         struct dev_context *devc;
286         char *s;
287
288         devc = sdi->priv;
289         s = g_match_info_fetch(match, 1);
290         sr_spew("STAT response '%s'.", s);
291
292         /* Max, Min or Avg mode -- no way to tell which, so we'll
293          * set both flags to denote it's not a normal measurement. */
294         if (s[0] == '1')
295                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX | SR_MQFLAG_MIN;
296         else
297                 devc->cur_mqflags[0] &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN);
298
299         if (s[1] == '1')
300                 devc->cur_mqflags[0] |= SR_MQFLAG_RELATIVE;
301         else
302                 devc->cur_mqflags[0] &= ~SR_MQFLAG_RELATIVE;
303
304         /* Hold mode. */
305         if (s[7] == '1')
306                 devc->cur_mqflags[0] |= SR_MQFLAG_HOLD;
307         else
308                 devc->cur_mqflags[0] &= ~SR_MQFLAG_HOLD;
309
310         g_free(s);
311
312         return JOB_STAT;
313 }
314
315 static int recv_stat_u124xc(const struct sr_dev_inst *sdi, GMatchInfo *match)
316 {
317         struct dev_context *devc;
318         char *s;
319
320         devc = sdi->priv;
321         s = g_match_info_fetch(match, 1);
322         sr_spew("STAT response '%s'.", s);
323
324         /* Max, Min or Avg mode -- no way to tell which, so we'll
325          * set both flags to denote it's not a normal measurement. */
326         if (s[0] == '1')
327                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX | SR_MQFLAG_MIN | SR_MQFLAG_AVG;
328         else
329                 devc->cur_mqflags[0] &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN | SR_MQFLAG_AVG);
330
331         /* Null function. */
332         if (s[1] == '1')
333                 devc->cur_mqflags[0] |= SR_MQFLAG_RELATIVE;
334         else
335                 devc->cur_mqflags[0] &= ~SR_MQFLAG_RELATIVE;
336
337         /* Triggered or auto hold modes. */
338         if (s[7] == '1' || s[11] == '1')
339                 devc->cur_mqflags[0] |= SR_MQFLAG_HOLD;
340         else
341                 devc->cur_mqflags[0] &= ~SR_MQFLAG_HOLD;
342
343         g_free(s);
344
345         return JOB_STAT;
346 }
347
348 static int recv_stat_u125x(const struct sr_dev_inst *sdi, GMatchInfo *match)
349 {
350         struct dev_context *devc;
351         char *s;
352
353         devc = sdi->priv;
354         s = g_match_info_fetch(match, 1);
355         sr_spew("STAT response '%s'.", s);
356
357         /* dBm/dBV modes. */
358         if ((s[2] & ~0x20) == 'M')
359                 devc->mode_dbm_dbv = devc->cur_unit[0] = SR_UNIT_DECIBEL_MW;
360         else if ((s[2] & ~0x20) == 'V')
361                 devc->mode_dbm_dbv = devc->cur_unit[0] = SR_UNIT_DECIBEL_VOLT;
362         else
363                 devc->mode_dbm_dbv = 0;
364
365         /* Peak hold mode. */
366         if (s[4] == '1')
367                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX;
368         else
369                 devc->cur_mqflags[0] &= ~SR_MQFLAG_MAX;
370
371         /* Triggered hold mode. */
372         if (s[7] == '1')
373                 devc->cur_mqflags[0] |= SR_MQFLAG_HOLD;
374         else
375                 devc->cur_mqflags[0] &= ~SR_MQFLAG_HOLD;
376
377         g_free(s);
378
379         return JOB_STAT;
380 }
381
382 static int recv_stat_u128x(const struct sr_dev_inst *sdi, GMatchInfo *match)
383 {
384         struct dev_context *devc;
385         char *s;
386
387         devc = sdi->priv;
388         s = g_match_info_fetch(match, 1);
389         sr_spew("STAT response '%s'.", s);
390
391         /* Max, Min or Avg mode -- no way to tell which, so we'll
392          * set both flags to denote it's not a normal measurement. */
393         if (s[0] == '1')
394                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX | SR_MQFLAG_MIN | SR_MQFLAG_AVG;
395         else
396                 devc->cur_mqflags[0] &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN | SR_MQFLAG_AVG);
397
398         /* dBm/dBV modes. */
399         if ((s[2] & ~0x20) == 'M')
400                 devc->mode_dbm_dbv = devc->cur_unit[0] = SR_UNIT_DECIBEL_MW;
401         else if ((s[2] & ~0x20) == 'V')
402                 devc->mode_dbm_dbv = devc->cur_unit[0] = SR_UNIT_DECIBEL_VOLT;
403         else
404                 devc->mode_dbm_dbv = 0;
405
406         /* Peak hold mode. */
407         if (s[4] == '4')
408                 devc->cur_mqflags[0] |= SR_MQFLAG_MAX;
409         else
410                 devc->cur_mqflags[0] &= ~SR_MQFLAG_MAX;
411
412         /* Null function. */
413         if (s[1] == '1')
414                 devc->cur_mqflags[0] |= SR_MQFLAG_RELATIVE;
415         else
416                 devc->cur_mqflags[0] &= ~SR_MQFLAG_RELATIVE;
417
418         /* Triggered or auto hold modes. */
419         if (s[7] == '1' || s[11] == '1')
420                 devc->cur_mqflags[0] |= SR_MQFLAG_HOLD;
421         else
422                 devc->cur_mqflags[0] &= ~SR_MQFLAG_HOLD;
423
424         g_free(s);
425
426         return JOB_STAT;
427 }
428
429 static int send_fetc(const struct sr_dev_inst *sdi)
430 {
431         struct dev_context *devc = sdi->priv;
432
433         if (devc->mode_squarewave)
434                 return SR_ERR_NA;
435
436         if (devc->cur_channel->index > 0)
437                 return agdmm_send(sdi, "FETC? @%d", devc->cur_channel->index + 1);
438         else
439                 return agdmm_send(sdi, "FETC?");
440 }
441
442 static int recv_fetc(const struct sr_dev_inst *sdi, GMatchInfo *match)
443 {
444         struct dev_context *devc;
445         struct sr_datafeed_packet packet;
446         struct sr_datafeed_analog analog;
447         struct sr_analog_encoding encoding;
448         struct sr_analog_meaning meaning;
449         struct sr_analog_spec spec;
450         struct sr_channel *prev_chan;
451         float fvalue;
452         const char *s;
453         char *mstr;
454         int i, exp;
455
456         sr_spew("FETC reply '%s'.", g_match_info_get_string(match));
457         devc = sdi->priv;
458         i = devc->cur_channel->index;
459
460         if (devc->cur_mq[i] == -1)
461                 /* This detects when channel P2 is reporting TEMP as an identical
462                  * copy of channel P3. In this case, we just skip P2. */
463                 goto skip_value;
464
465         s = g_match_info_get_string(match);
466         if (!strcmp(s, "-9.90000000E+37") || !strcmp(s, "+9.90000000E+37")) {
467                 /* An invalid measurement shows up on the display as "O.L", but
468                  * comes through like this. Since comparing 38-digit floats
469                  * is rather problematic, we'll cut through this here. */
470                 fvalue = NAN;
471         } else {
472                 mstr = g_match_info_fetch(match, 1);
473                 if (sr_atof_ascii(mstr, &fvalue) != SR_OK) {
474                         g_free(mstr);
475                         sr_dbg("Invalid float.");
476                         return SR_ERR;
477                 }
478                 g_free(mstr);
479                 if (devc->cur_exponent[i] != 0)
480                         fvalue *= powf(10, devc->cur_exponent[i]);
481         }
482
483         if (devc->cur_unit[i] == SR_UNIT_DECIBEL_MW ||
484             devc->cur_unit[i] == SR_UNIT_DECIBEL_VOLT ||
485             devc->cur_unit[i] == SR_UNIT_PERCENTAGE) {
486                 mstr = g_match_info_fetch(match, 2);
487                 if (mstr && sr_atoi(mstr, &exp) == SR_OK) {
488                         devc->cur_digits[i] = MIN(4 - exp, devc->cur_digits[i]);
489                         devc->cur_encoding[i] = MIN(5 - exp, devc->cur_encoding[i]);
490                 }
491                 g_free(mstr);
492         }
493
494         sr_analog_init(&analog, &encoding, &meaning, &spec,
495                        devc->cur_digits[i] - devc->cur_exponent[i]);
496         analog.meaning->mq = devc->cur_mq[i];
497         analog.meaning->unit = devc->cur_unit[i];
498         analog.meaning->mqflags = devc->cur_mqflags[i];
499         analog.meaning->channels = g_slist_append(NULL, devc->cur_channel);
500         analog.num_samples = 1;
501         analog.data = &fvalue;
502         encoding.digits = devc->cur_encoding[i] - devc->cur_exponent[i];
503         packet.type = SR_DF_ANALOG;
504         packet.payload = &analog;
505         sr_session_send(sdi, &packet);
506         g_slist_free(analog.meaning->channels);
507
508         sr_sw_limits_update_samples_read(&devc->limits, 1);
509
510 skip_value:
511         prev_chan = devc->cur_channel;
512         devc->cur_channel = sr_next_enabled_channel(sdi, devc->cur_channel);
513         if (devc->cur_channel->index > prev_chan->index)
514                 return JOB_AGAIN;
515         else
516                 return JOB_FETC;
517 }
518
519 static int send_conf(const struct sr_dev_inst *sdi)
520 {
521         struct dev_context *devc = sdi->priv;
522
523         /* Do not try to send CONF? for internal temperature channel. */
524         if (devc->cur_conf->index >= MIN(devc->profile->nb_channels, 2))
525                 return SR_ERR_NA;
526
527         if (devc->cur_conf->index > 0)
528                 return agdmm_send(sdi, "CONF? @%d", devc->cur_conf->index + 1);
529         else
530                 return agdmm_send(sdi, "CONF?");
531 }
532
533 static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
534 {
535         struct dev_context *devc;
536         char *mstr, *rstr;
537         int i, resolution;
538
539         sr_spew("CONF? response '%s'.", g_match_info_get_string(match));
540         devc = sdi->priv;
541         i = devc->cur_conf->index;
542
543         rstr = g_match_info_fetch(match, 2);
544         if (rstr)
545                 sr_atoi(rstr, &resolution);
546         g_free(rstr);
547
548         mstr = g_match_info_fetch(match, 1);
549         if (!strcmp(mstr, "V")) {
550                 devc->cur_mq[i] = SR_MQ_VOLTAGE;
551                 devc->cur_unit[i] = SR_UNIT_VOLT;
552                 devc->cur_mqflags[i] = 0;
553                 devc->cur_exponent[i] = 0;
554                 devc->cur_digits[i] = 4 - resolution;
555         } else if (!strcmp(mstr, "MV")) {
556                 if (devc->mode_tempaux) {
557                         devc->cur_mq[i] = SR_MQ_TEMPERATURE;
558                         /* No way to detect whether Fahrenheit or Celsius
559                          * is used, so we'll just default to Celsius. */
560                         devc->cur_unit[i] = SR_UNIT_CELSIUS;
561                         devc->cur_mqflags[i] = 0;
562                         devc->cur_exponent[i] = 0;
563                         devc->cur_digits[i] = 1;
564                 } else {
565                         devc->cur_mq[i] = SR_MQ_VOLTAGE;
566                         devc->cur_unit[i] = SR_UNIT_VOLT;
567                         devc->cur_mqflags[i] = 0;
568                         devc->cur_exponent[i] = -3;
569                         devc->cur_digits[i] = 5 - resolution;
570                 }
571         } else if (!strcmp(mstr, "A")) {
572                 devc->cur_mq[i] = SR_MQ_CURRENT;
573                 devc->cur_unit[i] = SR_UNIT_AMPERE;
574                 devc->cur_mqflags[i] = 0;
575                 devc->cur_exponent[i] = 0;
576                 devc->cur_digits[i] = 3 - resolution;
577         } else if (!strcmp(mstr, "MA")) {
578                 devc->cur_mq[i] = SR_MQ_CURRENT;
579                 devc->cur_unit[i] = SR_UNIT_AMPERE;
580                 devc->cur_mqflags[i] = 0;
581                 devc->cur_exponent[i] = -3;
582                 devc->cur_digits[i] = 8 - resolution;
583         } else if (!strcmp(mstr, "UA")) {
584                 devc->cur_mq[i] = SR_MQ_CURRENT;
585                 devc->cur_unit[i] = SR_UNIT_AMPERE;
586                 devc->cur_mqflags[i] = 0;
587                 devc->cur_exponent[i] = -6;
588                 devc->cur_digits[i] = 8 - resolution;
589         } else if (!strcmp(mstr, "FREQ")) {
590                 devc->cur_mq[i] = SR_MQ_FREQUENCY;
591                 devc->cur_unit[i] = SR_UNIT_HERTZ;
592                 devc->cur_mqflags[i] = 0;
593                 devc->cur_exponent[i] = 0;
594                 devc->cur_digits[i] = 2 - resolution;
595         } else if (!strcmp(mstr, "RES")) {
596                 if (devc->mode_continuity) {
597                         devc->cur_mq[i] = SR_MQ_CONTINUITY;
598                         devc->cur_unit[i] = SR_UNIT_BOOLEAN;
599                 } else {
600                         devc->cur_mq[i] = SR_MQ_RESISTANCE;
601                         devc->cur_unit[i] = SR_UNIT_OHM;
602                 }
603                 devc->cur_mqflags[i] = 0;
604                 devc->cur_exponent[i] = 0;
605                 devc->cur_digits[i] = 1 - resolution;
606         } else if (!strcmp(mstr, "DIOD")) {
607                 devc->cur_mq[i] = SR_MQ_VOLTAGE;
608                 devc->cur_unit[i] = SR_UNIT_VOLT;
609                 devc->cur_mqflags[i] = SR_MQFLAG_DIODE | SR_MQFLAG_DC;
610                 devc->cur_exponent[i] = 0;
611                 devc->cur_digits[i] = 3;
612         } else if (!strcmp(mstr, "TEMP")) {
613                 devc->cur_mq[i] = SR_MQ_TEMPERATURE;
614                 devc->cur_unit[i] = SR_UNIT_CELSIUS;
615                 devc->cur_mqflags[i] = 0;
616                 devc->cur_exponent[i] = 0;
617                 devc->cur_digits[i] = 1;
618         } else if (!strcmp(mstr, "CAP")) {
619                 devc->cur_mq[i] = SR_MQ_CAPACITANCE;
620                 devc->cur_unit[i] = SR_UNIT_FARAD;
621                 devc->cur_mqflags[i] = 0;
622                 devc->cur_exponent[i] = 0;
623                 devc->cur_digits[i] = 9 - resolution;
624         } else
625                 sr_dbg("Unknown first argument.");
626         g_free(mstr);
627
628         /* This is based on guess, supposing similarity with other models. */
629         devc->cur_encoding[i] = devc->cur_digits[i] + 1;
630
631         if (g_match_info_get_match_count(match) == 4) {
632                 mstr = g_match_info_fetch(match, 3);
633                 /* Third value, if present, is always AC or DC. */
634                 if (!strcmp(mstr, "AC")) {
635                         devc->cur_mqflags[i] |= SR_MQFLAG_AC;
636                         if (devc->cur_mq[i] == SR_MQ_VOLTAGE)
637                                 devc->cur_mqflags[i] |= SR_MQFLAG_RMS;
638                 } else if (!strcmp(mstr, "DC")) {
639                         devc->cur_mqflags[i] |= SR_MQFLAG_DC;
640                 } else if (!strcmp(mstr, "ACDC")) {
641                         devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS;
642                 } else {
643                         sr_dbg("Unknown first argument '%s'.", mstr);
644                 }
645                 g_free(mstr);
646         } else
647                 devc->cur_mqflags[i] &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
648
649         struct sr_channel *prev_conf = devc->cur_conf;
650         devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
651         if (devc->cur_conf->index >= MIN(devc->profile->nb_channels, 2))
652                 devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
653         if (devc->cur_conf->index > prev_conf->index)
654                 return JOB_AGAIN;
655         else
656                 return JOB_CONF;
657 }
658
659 static int recv_conf_u124x_5x(const struct sr_dev_inst *sdi, GMatchInfo *match)
660 {
661         struct dev_context *devc;
662         char *mstr, *rstr, *m2;
663         int i, resolution;
664
665         sr_spew("CONF? response '%s'.", g_match_info_get_string(match));
666         devc = sdi->priv;
667         i = devc->cur_conf->index;
668
669         devc->mode_squarewave = 0;
670
671         rstr = g_match_info_fetch(match, 4);
672         if (rstr && sr_atoi(rstr, &resolution) == SR_OK) {
673                 devc->cur_digits[i] = -resolution;
674                 devc->cur_encoding[i] = -resolution + 1;
675         }
676         g_free(rstr);
677
678         mstr = g_match_info_fetch(match, 1);
679         if (!strncmp(mstr, "VOLT", 4)) {
680                 devc->cur_mq[i] = SR_MQ_VOLTAGE;
681                 devc->cur_unit[i] = SR_UNIT_VOLT;
682                 devc->cur_mqflags[i] = 0;
683                 devc->cur_exponent[i] = 0;
684                 if (i == 0 && devc->mode_dbm_dbv) {
685                         devc->cur_unit[i] = devc->mode_dbm_dbv;
686                         devc->cur_digits[i] = 3;
687                         devc->cur_encoding[i] = 4;
688                 }
689                 if (mstr[4] == ':') {
690                         if (!strncmp(mstr + 5, "ACDC", 4)) {
691                                 /* AC + DC offset */
692                                 devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS;
693                         } else if (!strncmp(mstr + 5, "AC", 2)) {
694                                 devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_RMS;
695                         } else if (!strncmp(mstr + 5, "DC", 2)) {
696                                 devc->cur_mqflags[i] |= SR_MQFLAG_DC;
697                         } else if (!strncmp(mstr + 5, "HRAT", 4)) {
698                                 devc->cur_mq[i] = SR_MQ_HARMONIC_RATIO;
699                                 devc->cur_unit[i] = SR_UNIT_PERCENTAGE;
700                                 devc->cur_digits[i] = 2;
701                                 devc->cur_encoding[i] = 3;
702                         }
703                 } else
704                         devc->cur_mqflags[i] |= SR_MQFLAG_DC;
705         } else if (!strncmp(mstr, "CURR", 4)) {
706                 devc->cur_mq[i] = SR_MQ_CURRENT;
707                 devc->cur_unit[i] = SR_UNIT_AMPERE;
708                 devc->cur_mqflags[i] = 0;
709                 devc->cur_exponent[i] = 0;
710                 if (mstr[4] == ':') {
711                         if (!strncmp(mstr + 5, "ACDC", 4)) {
712                                 /* AC + DC offset */
713                                 devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS;
714                         } else if (!strncmp(mstr + 5, "AC", 2)) {
715                                 devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_RMS;
716                         } else if (!strncmp(mstr + 5, "DC", 2)) {
717                                 devc->cur_mqflags[i] |= SR_MQFLAG_DC;
718                         }
719                 } else
720                         devc->cur_mqflags[i] |= SR_MQFLAG_DC;
721         } else if (!strcmp(mstr, "RES")) {
722                 devc->cur_mq[i] = SR_MQ_RESISTANCE;
723                 devc->cur_unit[i] = SR_UNIT_OHM;
724                 devc->cur_mqflags[i] = 0;
725                 devc->cur_exponent[i] = 0;
726         } else if (!strcmp(mstr, "COND")) {
727                 devc->cur_mq[i] = SR_MQ_CONDUCTANCE;
728                 devc->cur_unit[i] = SR_UNIT_SIEMENS;
729                 devc->cur_mqflags[i] = 0;
730                 devc->cur_exponent[i] = 0;
731         } else if (!strcmp(mstr, "CAP")) {
732                 devc->cur_mq[i] = SR_MQ_CAPACITANCE;
733                 devc->cur_unit[i] = SR_UNIT_FARAD;
734                 devc->cur_mqflags[i] = 0;
735                 devc->cur_exponent[i] = 0;
736         } else if (!strncmp(mstr, "FREQ", 4) || !strncmp(mstr, "FC1", 3)) {
737                 devc->cur_mq[i] = SR_MQ_FREQUENCY;
738                 devc->cur_unit[i] = SR_UNIT_HERTZ;
739                 devc->cur_mqflags[i] = 0;
740                 devc->cur_exponent[i] = 0;
741         } else if (!strncmp(mstr, "PULS:PWID", 9)) {
742                 devc->cur_mq[i] = SR_MQ_PULSE_WIDTH;
743                 devc->cur_unit[i] = SR_UNIT_SECOND;
744                 devc->cur_mqflags[i] = 0;
745                 devc->cur_exponent[i] = 0;
746                 devc->cur_encoding[i] = MIN(devc->cur_encoding[i], 6);
747         } else if (!strncmp(mstr, "PULS:PDUT", 9)) {
748                 devc->cur_mq[i] = SR_MQ_DUTY_CYCLE;
749                 devc->cur_unit[i] = SR_UNIT_PERCENTAGE;
750                 devc->cur_mqflags[i] = 0;
751                 devc->cur_exponent[i] = 0;
752                 devc->cur_digits[i] = 3;
753                 devc->cur_encoding[i] = 4;
754         } else if (!strcmp(mstr, "CONT")) {
755                 devc->cur_mq[i] = SR_MQ_CONTINUITY;
756                 devc->cur_unit[i] = SR_UNIT_OHM;
757                 devc->cur_mqflags[i] = 0;
758                 devc->cur_exponent[i] = 0;
759         } else if (!strcmp(mstr, "DIOD")) {
760                 devc->cur_mq[i] = SR_MQ_VOLTAGE;
761                 devc->cur_unit[i] = SR_UNIT_VOLT;
762                 devc->cur_mqflags[i] = SR_MQFLAG_DIODE | SR_MQFLAG_DC;
763                 devc->cur_exponent[i] = 0;
764                 if (devc->profile->model == KEYSIGHT_U1281 ||
765                     devc->profile->model == KEYSIGHT_U1282) {
766                         devc->cur_digits[i] = 4;
767                         devc->cur_encoding[i] = 5;
768                 } else {
769                         devc->cur_digits[i] = 3;
770                         devc->cur_encoding[i] = 4;
771                 }
772         } else if (!strncmp(mstr, "T1", 2) || !strncmp(mstr, "T2", 2) ||
773                    !strncmp(mstr, "TEMP", 4)) {
774                 devc->cur_mq[i] = SR_MQ_TEMPERATURE;
775                 m2 = g_match_info_fetch(match, 2);
776                 if (!m2 && devc->profile->nb_channels == 3)
777                         /*
778                          * TEMP without param is for secondary display (channel P2)
779                          * and is identical to channel P3, so discard it.
780                          */
781                         devc->cur_mq[i] = -1;
782                 else if (m2 && !strcmp(m2, "FAR"))
783                         devc->cur_unit[i] = SR_UNIT_FAHRENHEIT;
784                 else
785                         devc->cur_unit[i] = SR_UNIT_CELSIUS;
786                 g_free(m2);
787                 devc->cur_mqflags[i] = 0;
788                 devc->cur_exponent[i] = 0;
789                 devc->cur_digits[i] = 1;
790                 devc->cur_encoding[i] = 2;
791         } else if (!strcmp(mstr, "SCOU")) {
792                 /*
793                  * Switch counter, not supported. Not sure what values
794                  * come from FETC in this mode, or how they would map
795                  * into libsigrok.
796                  */
797         } else if (!strncmp(mstr, "CPER:", 5)) {
798                 devc->cur_mq[i] = SR_MQ_CURRENT;
799                 devc->cur_unit[i] = SR_UNIT_PERCENTAGE;
800                 devc->cur_mqflags[i] = 0;
801                 devc->cur_exponent[i] = 0;
802                 devc->cur_digits[i] = 2;
803                 devc->cur_encoding[i] = 3;
804         } else if (!strcmp(mstr, "SQU")) {
805                 /*
806                  * Square wave output, not supported. FETC just return
807                  * an error in this mode, so don't even call it.
808                  */
809                 devc->mode_squarewave = 1;
810         } else if (!strcmp(mstr, "NCV")) {
811                 devc->cur_mq[i] = SR_MQ_VOLTAGE;
812                 devc->cur_unit[i] = SR_UNIT_VOLT;
813                 devc->cur_mqflags[i] = SR_MQFLAG_AC;
814                 if (devc->profile->model == KEYSIGHT_U1281 ||
815                     devc->profile->model == KEYSIGHT_U1282) {
816                         devc->cur_exponent[i] = -3;
817                         devc->cur_digits[i] = -1;
818                         devc->cur_encoding[i] = 0;
819                 } else {
820                         devc->cur_exponent[i] = 0;
821                         devc->cur_digits[i] = 2;
822                         devc->cur_encoding[i] = 3;
823                 }
824         } else {
825                 sr_dbg("Unknown first argument '%s'.", mstr);
826         }
827         g_free(mstr);
828
829         struct sr_channel *prev_conf = devc->cur_conf;
830         devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
831         if (devc->cur_conf->index >= MIN(devc->profile->nb_channels, 2))
832                 devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
833         if (devc->cur_conf->index > prev_conf->index)
834                 return JOB_AGAIN;
835         else
836                 return JOB_CONF;
837 }
838
839 static int send_log(const struct sr_dev_inst *sdi)
840 {
841         const char *source[] = { "LOG:HAND", "LOG:TRIG", "LOG:AUTO", "LOG:EXPO" };
842         struct dev_context *devc = sdi->priv;
843         return agdmm_send(sdi, "%s %d",
844                           source[devc->data_source - 1], devc->cur_sample);
845 }
846
847 static int recv_log(const struct sr_dev_inst *sdi, GMatchInfo *match,
848                     const int mqs[], const int units[], const int exponents[],
849                     unsigned int num_functions)
850 {
851         struct dev_context *devc;
852         struct sr_datafeed_packet packet;
853         struct sr_datafeed_analog analog;
854         struct sr_analog_encoding encoding;
855         struct sr_analog_meaning meaning;
856         struct sr_analog_spec spec;
857         char *mstr;
858         unsigned function;
859         int value, negative, overload, exponent, alternate_unit, mq, unit;
860         int mqflags = 0;
861         float fvalue;
862
863         sr_spew("LOG response '%s'.", g_match_info_get_string(match));
864
865         devc = sdi->priv;
866
867         mstr = g_match_info_fetch(match, 2);
868         if (sr_atoi(mstr, (int*)&function) != SR_OK || function >= num_functions) {
869                 g_free(mstr);
870                 sr_dbg("Invalid function.");
871                 return SR_ERR;
872         }
873         g_free(mstr);
874
875         mstr = g_match_info_fetch(match, 3);
876         if (sr_atoi(mstr, &value) != SR_OK) {
877                 g_free(mstr);
878                 sr_dbg("Invalid value.");
879                 return SR_ERR;
880         }
881         g_free(mstr);
882
883         mstr = g_match_info_fetch(match, 1);
884         negative = mstr[7] & 2 ? -1 : 1;
885         overload = mstr[8] & 4;
886         exponent = (mstr[9] & 0xF) + exponents[function];
887         alternate_unit = mstr[10] & 1;
888
889         if (mstr[ 8] & 1)  mqflags |= SR_MQFLAG_DC;
890         if (mstr[ 8] & 2)  mqflags |= SR_MQFLAG_AC;
891         if (mstr[11] & 4)  mqflags |= SR_MQFLAG_RELATIVE;
892         if (mstr[12] & 1)  mqflags |= SR_MQFLAG_AVG;
893         if (mstr[12] & 2)  mqflags |= SR_MQFLAG_MIN;
894         if (mstr[12] & 4)  mqflags |= SR_MQFLAG_MAX;
895         if (function == 5) mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
896         g_free(mstr);
897
898         mq = mqs[function];
899         unit = units[function];
900         if (alternate_unit) {
901                 if (mq == SR_MQ_RESISTANCE)
902                         mq = SR_MQ_CONTINUITY;
903                 if (unit == SR_UNIT_DECIBEL_MW)
904                         unit = SR_UNIT_DECIBEL_VOLT;
905                 if (unit == SR_UNIT_CELSIUS) {
906                         unit = SR_UNIT_FAHRENHEIT;
907                         if (devc->profile->model == KEYSIGHT_U1281 ||
908                             devc->profile->model == KEYSIGHT_U1282)
909                                 exponent--;
910                 }
911         }
912
913         if (overload)
914                 fvalue = NAN;
915         else
916                 fvalue = negative * value * powf(10, exponent);
917
918         sr_analog_init(&analog, &encoding, &meaning, &spec, -exponent);
919         analog.meaning->mq = mq;
920         analog.meaning->unit = unit;
921         analog.meaning->mqflags = mqflags;
922         analog.meaning->channels = g_slist_append(NULL, devc->cur_channel);
923         analog.num_samples = 1;
924         analog.data = &fvalue;
925         packet.type = SR_DF_ANALOG;
926         packet.payload = &analog;
927         sr_session_send(sdi, &packet);
928         g_slist_free(analog.meaning->channels);
929
930         sr_sw_limits_update_samples_read(&devc->limits, 1);
931         devc->cur_sample++;
932
933         return JOB_LOG;
934 }
935
936 static int recv_log_u124xc(const struct sr_dev_inst *sdi, GMatchInfo *match)
937 {
938         static const int mqs[] = { SR_MQ_VOLTAGE, SR_MQ_VOLTAGE, SR_MQ_CURRENT, SR_MQ_CURRENT, SR_MQ_RESISTANCE, SR_MQ_VOLTAGE, SR_MQ_TEMPERATURE, SR_MQ_CAPACITANCE, SR_MQ_FREQUENCY, SR_MQ_HARMONIC_RATIO, SR_MQ_CURRENT };
939         static const int units[] = { SR_UNIT_VOLT, SR_UNIT_VOLT, SR_UNIT_AMPERE, SR_UNIT_AMPERE, SR_UNIT_OHM, SR_UNIT_VOLT, SR_UNIT_CELSIUS, SR_UNIT_FARAD, SR_UNIT_HERTZ, SR_UNIT_PERCENTAGE, SR_UNIT_PERCENTAGE };
940         static const int exponents[] = { -5, -4, -7, -3, -2, -3, -1, -10, -2, -2, -2 };
941
942         return recv_log(sdi, match, mqs, units, exponents, ARRAY_SIZE(mqs));
943 }
944
945 static int recv_log_u128x(const struct sr_dev_inst *sdi, GMatchInfo *match)
946 {
947         static const int mqs[] = { SR_MQ_VOLTAGE, SR_MQ_VOLTAGE, SR_MQ_CURRENT, SR_MQ_CURRENT, SR_MQ_RESISTANCE, SR_MQ_VOLTAGE, SR_MQ_TEMPERATURE, SR_MQ_CAPACITANCE, SR_MQ_FREQUENCY, SR_MQ_DUTY_CYCLE, SR_MQ_PULSE_WIDTH, SR_MQ_VOLTAGE, SR_MQ_CURRENT, SR_MQ_CONDUCTANCE };
948         static const int units[] = { SR_UNIT_VOLT, SR_UNIT_VOLT, SR_UNIT_AMPERE, SR_UNIT_AMPERE, SR_UNIT_OHM, SR_UNIT_VOLT, SR_UNIT_CELSIUS, SR_UNIT_FARAD, SR_UNIT_HERTZ, SR_UNIT_PERCENTAGE, SR_UNIT_SECOND, SR_UNIT_DECIBEL_MW, SR_UNIT_PERCENTAGE, SR_UNIT_SIEMENS };
949         static const int exponents[] = { -6, -4, -9, -4, -3, -4, -1, -12, -3, -3, -6, -3, -2, -11 };
950
951         return recv_log(sdi, match, mqs, units, exponents, ARRAY_SIZE(mqs));
952 }
953
954 /* This comes in whenever the rotary switch is changed to a new position.
955  * We could use it to determine the major measurement mode, but we already
956  * have the output of CONF? for that, which is more detailed. However
957  * we do need to catch this here, or it'll show up in some other output. */
958 static int recv_switch(const struct sr_dev_inst *sdi, GMatchInfo *match)
959 {
960         struct dev_context *devc = sdi->priv;
961
962         sr_spew("Switch '%s'.", g_match_info_get_string(match));
963
964         devc->current_job = 0;
965         devc->job_running = FALSE;
966         memset(devc->jobs_start, 0, sizeof(devc->jobs_start));
967         devc->cur_mq[0] = -1;
968         if (devc->profile->nb_channels > 2)
969                 devc->cur_mq[1] = -1;
970
971         return SR_OK;
972 }
973
974 static int recv_err(const struct sr_dev_inst *sdi, GMatchInfo *match)
975 {
976         struct dev_context *devc = sdi->priv;
977
978         (void) match;
979
980         if (devc->data_source != DATA_SOURCE_LIVE)
981                 return JOB_STOP; /* In log mode, stop acquisition after receiving *E. */
982         else
983                 return JOB_AGAIN;
984 }
985
986 /* Poll CONF/STAT at 1Hz and values at samplerate. */
987 SR_PRIV const struct agdmm_job agdmm_jobs_live[] = {
988         { JOB_FETC, SAMPLERATE_INTERVAL, send_fetc },
989         { JOB_CONF,                1000, send_conf },
990         { JOB_STAT,                1000, send_stat },
991         ALL_ZERO
992 };
993
994 /* Poll LOG as fast as possible. */
995 SR_PRIV const struct agdmm_job agdmm_jobs_log[] = {
996         { JOB_LOG,                    0, send_log  },
997         ALL_ZERO
998 };
999
1000 SR_PRIV const struct agdmm_recv agdmm_recvs_u123x[] = {
1001         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u123x },
1002         { "^\\*([0-9])$", recv_switch },
1003         { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
1004         { "^\"(V|MV|A|UA|FREQ),(\\d),(AC|DC)\"$", recv_conf_u123x },
1005         { "^\"(RES|CAP),(\\d)\"$", recv_conf_u123x},
1006         { "^\"(DIOD)\"$", recv_conf_u123x },
1007         ALL_ZERO
1008 };
1009
1010 SR_PRIV const struct agdmm_recv agdmm_recvs_u124x[] = {
1011         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u124x },
1012         { "^\\*([0-9])$", recv_switch },
1013         { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
1014         { "^\"(VOLT|CURR|RES|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6,8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1015         { "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6,8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1016         { "^\"(CURR:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6,8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1017         { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6,8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1018         { "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1019         { "^\"(TEMP:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1020         { "^\"(DIOD)\"$", recv_conf_u124x_5x },
1021         ALL_ZERO
1022 };
1023
1024 SR_PRIV const struct agdmm_recv agdmm_recvs_u124xc[] = {
1025         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u124xc },
1026         { "^\\*([0-9])$", recv_switch },
1027         { "^([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))$", recv_fetc },
1028         { "^\"(VOLT|VOLT:AC|VOLT:HRAT|CURR|CURR:AC|RES|CONT|CAP|FREQ|FREQ:AC) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1029         { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1030         { "^\"(TEMP:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1031         { "^\"(NCV) (HI|LO)\"$", recv_conf_u124x_5x },
1032         { "^\"(DIOD|TEMP)\"$", recv_conf_u124x_5x },
1033         { "^\"((\\d{2})(\\d{5})\\d{7})\"$", recv_log_u124xc },
1034         { "^\\*E$", recv_err },
1035         ALL_ZERO
1036 };
1037
1038 SR_PRIV const struct agdmm_recv agdmm_recvs_u125x[] = {
1039         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u125x },
1040         { "^\\*([0-9])$", recv_switch },
1041         { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
1042         { "^\"(VOLT|CURR|RES|CONT|COND|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1043         { "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1044         { "^\"(CURR:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1045         { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1046         { "^\"(PULS:PWID|PULS:PWID:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1047         { "^\"(TEMP:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1048         { "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1049         { "^\"(DIOD|PULS:[PN]DUT)\"$", recv_conf_u124x_5x },
1050         ALL_ZERO
1051 };
1052
1053 SR_PRIV const struct agdmm_recv agdmm_recvs_u127x[] = {
1054         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u123x },
1055         { "^\\*([0-9]+)$", recv_switch },
1056         { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
1057         { "^\"(V|MV|A|MA|UA|FREQ),(\\d),(AC|DC|ACDC)\"$", recv_conf_u123x },
1058         { "^\"(RES|CAP),(\\d)\"$", recv_conf_u123x},
1059         { "^\"(DIOD|TEMP)\"$", recv_conf_u123x },
1060         ALL_ZERO
1061 };
1062
1063 SR_PRIV const struct agdmm_recv agdmm_recvs_u128x[] = {
1064         { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u128x },
1065         { "^\\*([0-9])$", recv_switch },
1066         { "^([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))$", recv_fetc },
1067         { "^\"(VOLT|CURR|RES|CONT|COND|CAP|FREQ|FC1|FC100) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1068         { "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1069         { "^\"(CURR:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1070         { "^\"(FREQ:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1071         { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1072         { "^\"(PULS:PWID|PULS:PWID:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
1073         { "^\"(TEMP:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
1074         { "^\"(NCV) (HIGH|LOW)\"$", recv_conf_u124x_5x },
1075         { "^\"(DIOD|SQU|PULS:PDUT|TEMP)\"$", recv_conf_u124x_5x },
1076         { "^\"((\\d{2})(\\d{5})\\d{7})\"$", recv_log_u128x },
1077         { "^\\*E$", recv_err },
1078         ALL_ZERO
1079 };