]> sigrok.org Git - libsigrok.git/blob - src/hardware/scpi-dmm/protocol.c
scpi-dmm: add support to get/set range on Agilent protocol using meters
[libsigrok.git] / src / hardware / scpi-dmm / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2018 Gerhard Sittig <gerhard.sittig@gmx.net>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <math.h>
22 #include <string.h>
23 #include "protocol.h"
24
25 #define WITH_CMD_DELAY 0        /* TODO See which devices need delays. */
26
27 SR_PRIV void scpi_dmm_cmd_delay(struct sr_scpi_dev_inst *scpi)
28 {
29         if (WITH_CMD_DELAY)
30                 g_usleep(WITH_CMD_DELAY * 1000);
31
32         if (!scpi->no_opc_command)
33                 sr_scpi_get_opc(scpi);
34 }
35
36 SR_PRIV const struct mqopt_item *scpi_dmm_lookup_mq_number(
37         const struct sr_dev_inst *sdi, enum sr_mq mq, enum sr_mqflag flag)
38 {
39         struct dev_context *devc;
40         size_t i;
41         const struct mqopt_item *item;
42
43         devc = sdi->priv;
44         for (i = 0; i < devc->model->mqopt_size; i++) {
45                 item = &devc->model->mqopts[i];
46                 if (item->mq != mq || item->mqflag != flag)
47                         continue;
48                 return item;
49         }
50
51         return NULL;
52 }
53
54 SR_PRIV const struct mqopt_item *scpi_dmm_lookup_mq_text(
55         const struct sr_dev_inst *sdi, const char *text)
56 {
57         struct dev_context *devc;
58         size_t i;
59         const struct mqopt_item *item;
60
61         devc = sdi->priv;
62         for (i = 0; i < devc->model->mqopt_size; i++) {
63                 item = &devc->model->mqopts[i];
64                 if (!item->scpi_func_query || !item->scpi_func_query[0])
65                         continue;
66                 if (!g_str_has_prefix(text, item->scpi_func_query))
67                         continue;
68                 return item;
69         }
70
71         return NULL;
72 }
73
74 SR_PRIV int scpi_dmm_get_mq(const struct sr_dev_inst *sdi,
75         enum sr_mq *mq, enum sr_mqflag *flag, char **rsp,
76         const struct mqopt_item **mqitem)
77 {
78         struct dev_context *devc;
79         const char *command;
80         char *response;
81         const char *have;
82         int ret;
83         const struct mqopt_item *item;
84
85         devc = sdi->priv;
86         if (mq)
87                 *mq = 0;
88         if (flag)
89                 *flag = 0;
90         if (rsp)
91                 *rsp = NULL;
92         if (mqitem)
93                 *mqitem = NULL;
94
95         scpi_dmm_cmd_delay(sdi->conn);
96         command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_FUNC);
97         if (!command || !*command)
98                 return SR_ERR_NA;
99         response = NULL;
100         ret = sr_scpi_get_string(sdi->conn, command, &response);
101         if (ret != SR_OK)
102                 return ret;
103         if (!response || !*response) {
104                 g_free(response);
105                 return SR_ERR_NA;
106         }
107         have = response;
108         if (*have == '"')
109                 have++;
110
111         ret = SR_ERR_NA;
112         item = scpi_dmm_lookup_mq_text(sdi, have);
113         if (item) {
114                 if (mq)
115                         *mq = item->mq;
116                 if (flag)
117                         *flag = item->mqflag;
118                 if (mqitem)
119                         *mqitem = item;
120                 ret = SR_OK;
121         } else {
122                 sr_warn("Unknown measurement quantity: %s", have);
123         }
124
125         if (rsp) {
126                 *rsp = response;
127                 response = NULL;
128         }
129         g_free(response);
130
131         return ret;
132 }
133
134 SR_PRIV int scpi_dmm_set_mq(const struct sr_dev_inst *sdi,
135         enum sr_mq mq, enum sr_mqflag flag)
136 {
137         struct dev_context *devc;
138         const struct mqopt_item *item;
139         const char *mode, *command;
140         int ret;
141
142         devc = sdi->priv;
143         item = scpi_dmm_lookup_mq_number(sdi, mq, flag);
144         if (!item)
145                 return SR_ERR_NA;
146
147         mode = item->scpi_func_setup;
148         command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_SETUP_FUNC);
149         scpi_dmm_cmd_delay(sdi->conn);
150         ret = sr_scpi_send(sdi->conn, command, mode);
151         if (ret != SR_OK)
152                 return ret;
153
154         return SR_OK;
155 }
156
157 SR_PRIV const char *scpi_dmm_get_range_text(const struct sr_dev_inst *sdi)
158 {
159         struct dev_context *devc;
160         int ret;
161         const struct mqopt_item *mqitem;
162         gboolean is_auto;
163         char *response, *pos;
164         double range;
165         int digits;
166
167         devc = sdi->priv;
168
169         ret = scpi_dmm_get_mq(sdi, NULL, NULL, NULL, &mqitem);
170         if (ret != SR_OK)
171                 return NULL;
172         if (!mqitem || !mqitem->scpi_func_setup)
173                 return NULL;
174
175         scpi_dmm_cmd_delay(sdi->conn);
176         ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
177                 DMM_CMD_QUERY_RANGE_AUTO, mqitem->scpi_func_setup);
178         if (ret != SR_OK)
179                 return NULL;
180         ret = sr_scpi_get_bool(sdi->conn, NULL, &is_auto);
181         if (ret != SR_OK)
182                 return NULL;
183         if (is_auto)
184                 return "auto";
185
186         /*
187          * Get the response into a text buffer. The range value may be
188          * followed by a precision value separated by comma. Common text
189          * to number conversion support code may assume that the input
190          * text spans to the end of the text, need not accept trailing
191          * text which is not part of a number.
192          */
193         scpi_dmm_cmd_delay(sdi->conn);
194         ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
195                 DMM_CMD_QUERY_RANGE, mqitem->scpi_func_setup);
196         if (ret != SR_OK)
197                 return NULL;
198         response = NULL;
199         ret = sr_scpi_get_string(sdi->conn, NULL, &response);
200         if (ret != SR_OK) {
201                 g_free(response);
202                 return NULL;
203         }
204         pos = strchr(response, ',');
205         if (pos)
206                 *pos = '\0';
207         ret = sr_atod_ascii_digits(response, &range, &digits);
208         g_free(response);
209         if (ret != SR_OK)
210                 return NULL;
211         snprintf(devc->range_text, sizeof(devc->range_text), "%lf", range);
212         return devc->range_text;
213 }
214
215 SR_PRIV int scpi_dmm_set_range_from_text(const struct sr_dev_inst *sdi,
216         const char *range)
217 {
218         struct dev_context *devc;
219         int ret;
220         const struct mqopt_item *item;
221         gboolean is_auto;
222
223         devc = sdi->priv;
224
225         if (!range || !*range)
226                 return SR_ERR_ARG;
227
228         ret = scpi_dmm_get_mq(sdi, NULL, NULL, NULL, &item);
229         if (ret != SR_OK)
230                 return ret;
231         if (!item || !item->scpi_func_setup)
232                 return SR_ERR_ARG;
233
234         is_auto = g_ascii_strcasecmp(range, "auto") == 0;
235         scpi_dmm_cmd_delay(sdi->conn);
236         ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
237                 is_auto ? DMM_CMD_SETUP_RANGE_AUTO : DMM_CMD_SETUP_RANGE,
238                 item->scpi_func_setup, is_auto ? "" : range);
239         if (ret != SR_OK)
240                 return ret;
241
242         return SR_OK;
243 }
244
245 SR_PRIV GVariant *scpi_dmm_get_range_text_list(const struct sr_dev_inst *sdi)
246 {
247         GVariantBuilder gvb;
248         GVariant *list;
249
250         (void)sdi;
251
252         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
253         /* TODO
254          * Add more items _when_ the connected device supports a fixed
255          * or known set of ranges. The Agilent protocol is flexible and
256          * tolerant, set requests accept any value, and the device will
257          * use an upper limit which is at least the specified value.
258          * The values are communicated as mere numbers without units.
259          */
260         list = g_variant_builder_end(&gvb);
261
262         return list;
263 }
264
265 SR_PRIV int scpi_dmm_get_meas_agilent(const struct sr_dev_inst *sdi, size_t ch)
266 {
267         struct sr_scpi_dev_inst *scpi;
268         struct dev_context *devc;
269         struct scpi_dmm_acq_info *info;
270         struct sr_datafeed_analog *analog;
271         int ret;
272         enum sr_mq mq;
273         enum sr_mqflag mqflag;
274         char *mode_response;
275         const char *p;
276         char **fields;
277         size_t count;
278         char prec_text[20];
279         const struct mqopt_item *item;
280         int prec_exp;
281         const char *command;
282         char *response;
283         gboolean use_double;
284         int sig_digits, val_exp;
285         int digits;
286         enum sr_unit unit;
287         double limit;
288
289         scpi = sdi->conn;
290         devc = sdi->priv;
291         info = &devc->run_acq_info;
292         analog = &info->analog[ch];
293
294         /*
295          * Get the meter's current mode, keep the response around.
296          * Skip the measurement if the mode is uncertain.
297          */
298         ret = scpi_dmm_get_mq(sdi, &mq, &mqflag, &mode_response, &item);
299         if (ret != SR_OK) {
300                 g_free(mode_response);
301                 return ret;
302         }
303         if (!mode_response)
304                 return SR_ERR;
305         if (!mq) {
306                 g_free(mode_response);
307                 return +1;
308         }
309
310         /*
311          * Get the last comma separated field of the function query
312          * response, or fallback to the model's default precision for
313          * the current function. This copes with either of these cases:
314          *   VOLT +1.00000E-01,+1.00000E-06
315          *   DIOD
316          *   TEMP THER,5000,+1.00000E+00,+1.00000E-01
317          */
318         p = sr_scpi_unquote_string(mode_response);
319         fields = g_strsplit(p, ",", 0);
320         count = g_strv_length(fields);
321         if (count >= 2) {
322                 snprintf(prec_text, sizeof(prec_text),
323                         "%s", fields[count - 1]);
324                 p = prec_text;
325         } else if (!item) {
326                 p = NULL;
327         } else if (item->default_precision == NO_DFLT_PREC) {
328                 p = NULL;
329         } else {
330                 snprintf(prec_text, sizeof(prec_text),
331                         "1e%d", item->default_precision);
332                 p = prec_text;
333         }
334         g_strfreev(fields);
335
336         /*
337          * Need to extract the exponent value ourselves, since a strtod()
338          * call will "eat" the exponent, too. Strip space, strip sign,
339          * strip float number (without! exponent), check for exponent
340          * and get exponent value. Accept absence of Esnn suffixes.
341          */
342         while (p && *p && g_ascii_isspace(*p))
343                 p++;
344         if (p && *p && (*p == '+' || *p == '-'))
345                 p++;
346         while (p && *p && g_ascii_isdigit(*p))
347                 p++;
348         if (p && *p && *p == '.')
349                 p++;
350         while (p && *p && g_ascii_isdigit(*p))
351                 p++;
352         ret = SR_OK;
353         if (!p || !*p)
354                 prec_exp = 0;
355         else if (*p != 'e' && *p != 'E')
356                 ret = SR_ERR_DATA;
357         else
358                 ret = sr_atoi(++p, &prec_exp);
359         g_free(mode_response);
360         if (ret != SR_OK)
361                 return ret;
362
363         /*
364          * Get the measurement value. Make sure to strip trailing space
365          * or else number conversion may fail in fatal ways. Detect OL
366          * conditions. Determine the measurement's precision: Count the
367          * number of significant digits before the period, and get the
368          * exponent's value.
369          *
370          * The text presentation of values is like this:
371          *   +1.09450000E-01
372          * Skip space/sign, count digits before the period, skip to the
373          * exponent, get exponent value.
374          *
375          * TODO Can sr_parse_rational() return the exponent for us? In
376          * addition to providing a precise rational value instead of a
377          * float that's an approximation of the received value? Can the
378          * 'analog' struct that we fill in carry rationals?
379          *
380          * Use double precision FP here during conversion. Optionally
381          * downgrade to single precision later to reduce the amount of
382          * logged information.
383          */
384         command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_VALUE);
385         if (!command || !*command)
386                 return SR_ERR_NA;
387         scpi_dmm_cmd_delay(scpi);
388         ret = sr_scpi_get_string(scpi, command, &response);
389         if (ret != SR_OK)
390                 return ret;
391         g_strstrip(response);
392         use_double = devc->model->digits > 6;
393         ret = sr_atod_ascii(response, &info->d_value);
394         if (ret != SR_OK) {
395                 g_free(response);
396                 return ret;
397         }
398         if (!response)
399                 return SR_ERR;
400         limit = 9e37;
401         if (info->d_value > +limit) {
402                 info->d_value = +INFINITY;
403         } else if (info->d_value < -limit) {
404                 info->d_value = -INFINITY;
405         } else {
406                 p = response;
407                 while (p && *p && g_ascii_isspace(*p))
408                         p++;
409                 if (p && *p && (*p == '-' || *p == '+'))
410                         p++;
411                 sig_digits = 0;
412                 while (p && *p && g_ascii_isdigit(*p)) {
413                         sig_digits++;
414                         p++;
415                 }
416                 if (p && *p && *p == '.')
417                         p++;
418                 while (p && *p && g_ascii_isdigit(*p))
419                         p++;
420                 ret = SR_OK;
421                 if (!p || !*p)
422                         val_exp = 0;
423                 else if (*p != 'e' && *p != 'E')
424                         ret = SR_ERR_DATA;
425                 else
426                         ret = sr_atoi(++p, &val_exp);
427         }
428         g_free(response);
429         if (ret != SR_OK)
430                 return ret;
431         /*
432          * TODO Come up with the most appropriate 'digits' calculation.
433          * This implementation assumes that either the device provides
434          * the resolution with the query for the meter's function, or
435          * the driver uses a fallback text pretending the device had
436          * provided it. This works with supported Agilent devices.
437          *
438          * An alternative may be to assume a given digits count which
439          * depends on the device, and adjust that count based on the
440          * value's significant digits and exponent. But this approach
441          * fails if devices change their digits count depending on
442          * modes or user requests, and also fails when e.g. devices
443          * with "100000 counts" can provide values between 100000 and
444          * 120000 in either 4 or 5 digits modes, depending on the most
445          * recent trend of the values. This less robust approach should
446          * only be taken if the mode inquiry won't yield the resolution
447          * (as e.g. DIOD does on 34405A, though we happen to know the
448          * fixed resolution for this very mode on this very model).
449          *
450          * For now, let's keep the prepared code path for the second
451          * approach in place, should some Agilent devices need it yet
452          * benefit from re-using most of the remaining acquisition
453          * routine.
454          */
455 #if 1
456         digits = -prec_exp;
457 #else
458         digits = devc->model->digits;
459         digits -= sig_digits;
460         digits -= val_exp;
461 #endif
462
463         /*
464          * Fill in the 'analog' description: value, encoding, meaning.
465          * Callers will fill in the sample count, and channel name,
466          * and will send out the packet.
467          */
468         if (use_double) {
469                 analog->data = &info->d_value;
470                 analog->encoding->unitsize = sizeof(info->d_value);
471         } else {
472                 info->f_value = info->d_value;
473                 analog->data = &info->f_value;
474                 analog->encoding->unitsize = sizeof(info->f_value);
475         }
476         analog->encoding->digits = digits;
477         analog->meaning->mq = mq;
478         analog->meaning->mqflags = mqflag;
479         switch (mq) {
480         case SR_MQ_VOLTAGE:
481                 unit = SR_UNIT_VOLT;
482                 break;
483         case SR_MQ_CURRENT:
484                 unit = SR_UNIT_AMPERE;
485                 break;
486         case SR_MQ_RESISTANCE:
487         case SR_MQ_CONTINUITY:
488                 unit = SR_UNIT_OHM;
489                 break;
490         case SR_MQ_CAPACITANCE:
491                 unit = SR_UNIT_FARAD;
492                 break;
493         case SR_MQ_TEMPERATURE:
494                 unit = SR_UNIT_CELSIUS;
495                 break;
496         case SR_MQ_FREQUENCY:
497                 unit = SR_UNIT_HERTZ;
498                 break;
499         case SR_MQ_TIME:
500                 unit = SR_UNIT_SECOND;
501                 break;
502         default:
503                 return SR_ERR_NA;
504         }
505         analog->meaning->unit = unit;
506         analog->spec->spec_digits = digits;
507
508         return SR_OK;
509 }
510
511 SR_PRIV int scpi_dmm_get_meas_gwinstek(const struct sr_dev_inst *sdi, size_t ch)
512 {
513         struct sr_scpi_dev_inst *scpi;
514         struct dev_context *devc;
515         struct scpi_dmm_acq_info *info;
516         struct sr_datafeed_analog *analog;
517         int ret;
518         enum sr_mq mq;
519         enum sr_mqflag mqflag;
520         char *mode_response;
521         const char *p;
522         const struct mqopt_item *item;
523         const char *command;
524         char *response;
525         gboolean use_double;
526         double limit;
527         int sig_digits, val_exp;
528         int digits;
529         enum sr_unit unit;
530         int mmode;
531
532         scpi = sdi->conn;
533         devc = sdi->priv;
534         info = &devc->run_acq_info;
535         analog = &info->analog[ch];
536
537         /*
538          * Get the meter's current mode, keep the response around.
539          * Skip the measurement if the mode is uncertain.
540          */
541         ret = scpi_dmm_get_mq(sdi, &mq, &mqflag, &mode_response, &item);
542         if (ret != SR_OK) {
543                 g_free(mode_response);
544                 return ret;
545         }
546         if (!mode_response)
547                 return SR_ERR;
548         if (!mq) {
549                 g_free(mode_response);
550                 return +1;
551         }
552         mmode = atoi(mode_response);
553         g_free(mode_response);
554
555         /*
556          * Get the current reading from the meter.
557          */
558         scpi_dmm_cmd_delay(scpi);
559         command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_VALUE);
560         if (!command || !*command)
561                 return SR_ERR_NA;
562         scpi_dmm_cmd_delay(scpi);
563         ret = sr_scpi_get_string(scpi, command, &response);
564         if (ret != SR_OK)
565                 return ret;
566         g_strstrip(response);
567         use_double = devc->model->digits > 6;
568         ret = sr_atod_ascii(response, &info->d_value);
569         if (ret != SR_OK) {
570                 g_free(response);
571                 return ret;
572         }
573         if (!response)
574                 return SR_ERR;
575         limit = 9e37;
576         if (devc->model->infinity_limit != 0.0)
577                 limit = devc->model->infinity_limit;
578         if (info->d_value >= +limit) {
579                 info->d_value = +INFINITY;
580         } else if (info->d_value <= -limit) {
581                 info->d_value = -INFINITY;
582         } else {
583                 p = response;
584                 while (p && *p && g_ascii_isspace(*p))
585                         p++;
586                 if (p && *p && (*p == '-' || *p == '+'))
587                         p++;
588                 sig_digits = 0;
589                 while (p && *p && g_ascii_isdigit(*p)) {
590                         sig_digits++;
591                         p++;
592                 }
593                 if (p && *p && *p == '.')
594                         p++;
595                 while (p && *p && g_ascii_isdigit(*p))
596                         p++;
597                 ret = SR_OK;
598                 if (!p || !*p)
599                         val_exp = 0;
600                 else if (*p != 'e' && *p != 'E')
601                         ret = SR_ERR_DATA;
602                 else
603                         ret = sr_atoi(++p, &val_exp);
604         }
605         g_free(response);
606         if (ret != SR_OK)
607                 return ret;
608
609         /*
610          * Make sure we report "INFINITY" when meter displays "0L".
611          */
612         switch (mmode) {
613         case 7:
614         case 16:
615                 /* In resitance modes 0L reads as 1.20000E8 or 1.99999E8. */
616                 limit = 1.2e8;
617                 if (strcmp(devc->model->model, "GDM8255A") == 0)
618                         limit = 1.99999e8;
619                 if (info->d_value >= limit)
620                         info->d_value = +INFINITY;
621                 break;
622         case 13:
623                 /* In continuity mode 0L reads as 1.20000E3. */
624                 if (info->d_value >= 1.2e3)
625                         info->d_value = +INFINITY;
626                 break;
627         case 17:
628                 /* In diode mode 0L reads as 1.00000E0. */
629                 if (info->d_value == 1.0e0)
630                         info->d_value = +INFINITY;
631                 break;
632         }
633
634         /*
635          * Calculate 'digits' based on the result of the optional
636          * precision reading which was done at acquisition start.
637          * The GW-Instek manual gives the following information
638          * regarding the resolution:
639          *
640          * Type      Digit
641          * --------  ------
642          * Slow      5 1/2
643          * Medium    4 1/2
644          * Fast      3 1/2
645          */
646         digits = devc->model->digits;
647         if (devc->precision && *devc->precision) {
648                 if (g_str_has_prefix(devc->precision, "Slow"))
649                         digits = 6;
650                 else if (g_str_has_prefix(devc->precision, "Mid"))
651                         digits = 5;
652                 else if (g_str_has_prefix(devc->precision, "Fast"))
653                         digits = 4;
654                 else
655                         sr_info("Unknown precision: '%s'", devc->precision);
656         }
657
658         /*
659          * Fill in the 'analog' description: value, encoding, meaning.
660          * Callers will fill in the sample count, and channel name,
661          * and will send out the packet.
662          */
663         if (use_double) {
664                 analog->data = &info->d_value;
665                 analog->encoding->unitsize = sizeof(info->d_value);
666         } else {
667                 info->f_value = info->d_value;
668                 analog->data = &info->f_value;
669                 analog->encoding->unitsize = sizeof(info->f_value);
670         }
671         analog->encoding->digits = digits;
672         analog->meaning->mq = mq;
673         analog->meaning->mqflags = mqflag;
674         switch (mq) {
675         case SR_MQ_VOLTAGE:
676                 unit = SR_UNIT_VOLT;
677                 break;
678         case SR_MQ_CURRENT:
679                 unit = SR_UNIT_AMPERE;
680                 break;
681         case SR_MQ_RESISTANCE:
682         case SR_MQ_CONTINUITY:
683                 unit = SR_UNIT_OHM;
684                 break;
685         case SR_MQ_CAPACITANCE:
686                 unit = SR_UNIT_FARAD;
687                 break;
688         case SR_MQ_TEMPERATURE:
689                 switch (mmode) {
690                 case 15:
691                         unit = SR_UNIT_FAHRENHEIT;
692                         break;
693                 case 9:
694                 default:
695                         unit = SR_UNIT_CELSIUS;
696                 }
697                 break;
698         case SR_MQ_FREQUENCY:
699                 unit = SR_UNIT_HERTZ;
700                 break;
701         case SR_MQ_TIME:
702                 unit = SR_UNIT_SECOND;
703                 break;
704         default:
705                 return SR_ERR_NA;
706         }
707         analog->meaning->unit = unit;
708         analog->spec->spec_digits = digits;
709
710         return SR_OK;
711 }
712
713 /* Strictly speaking this is a timer controlled poll routine. */
714 SR_PRIV int scpi_dmm_receive_data(int fd, int revents, void *cb_data)
715 {
716         struct sr_dev_inst *sdi;
717         struct sr_scpi_dev_inst *scpi;
718         struct dev_context *devc;
719         struct scpi_dmm_acq_info *info;
720         gboolean sent_sample;
721         size_t ch;
722         struct sr_channel *channel;
723         int ret;
724
725         (void)fd;
726         (void)revents;
727
728         sdi = cb_data;
729         if (!sdi)
730                 return TRUE;
731         scpi = sdi->conn;
732         devc = sdi->priv;
733         if (!scpi || !devc)
734                 return TRUE;
735         info = &devc->run_acq_info;
736
737         sent_sample = FALSE;
738         ret = SR_OK;
739         for (ch = 0; ch < devc->num_channels; ch++) {
740                 /* Check the channel's enabled status. */
741                 channel = g_slist_nth_data(sdi->channels, ch);
742                 if (!channel->enabled)
743                         continue;
744
745                 /*
746                  * Prepare an analog measurement value. Note that digits
747                  * will get updated later.
748                  */
749                 info->packet.type = SR_DF_ANALOG;
750                 info->packet.payload = &info->analog[ch];
751                 sr_analog_init(&info->analog[ch], &info->encoding[ch],
752                         &info->meaning[ch], &info->spec[ch], 0);
753
754                 /* Just check OPC before sending another request. */
755                 scpi_dmm_cmd_delay(sdi->conn);
756
757                 /*
758                  * Have the model take and interpret a measurement. Lack
759                  * of support is pointless, failed retrieval/conversion
760                  * is considered fatal. The routine will fill in the
761                  * 'analog' details, except for channel name and sample
762                  * count (assume one value per channel).
763                  *
764                  * Note that non-zero non-negative return codes signal
765                  * that the channel's data shell get skipped in this
766                  * iteration over the channels. This copes with devices
767                  * or modes where channels may provide data at different
768                  * rates.
769                  */
770                 if (!devc->model->get_measurement) {
771                         ret = SR_ERR_NA;
772                         break;
773                 }
774                 ret = devc->model->get_measurement(sdi, ch);
775                 if (ret > 0)
776                         continue;
777                 if (ret != SR_OK)
778                         break;
779
780                 /* Send the packet that was filled in by the model's routine. */
781                 info->analog[ch].num_samples = 1;
782                 info->analog[ch].meaning->channels = g_slist_append(NULL, channel);
783                 sr_session_send(sdi, &info->packet);
784                 g_slist_free(info->analog[ch].meaning->channels);
785                 sent_sample = TRUE;
786         }
787         if (sent_sample)
788                 sr_sw_limits_update_samples_read(&devc->limits, 1);
789         if (ret != SR_OK) {
790                 /* Stop acquisition upon communication or data errors. */
791                 sr_dev_acquisition_stop(sdi);
792                 return TRUE;
793         }
794         if (sr_sw_limits_check(&devc->limits))
795                 sr_dev_acquisition_stop(sdi);
796
797         return TRUE;
798 }