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