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