]> sigrok.org Git - libsigrok.git/blob - src/std.c
std: std_gvar_tuple_array/_rational: Fix GVariantBuilder type.
[libsigrok.git] / src / std.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de>
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 2 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 /**
21  * @file
22  *
23  * Standard API helper functions.
24  *
25  * @internal
26  */
27
28 /* Needed for gettimeofday(), at least on FreeBSD. */
29 #define _XOPEN_SOURCE 700
30
31 #include <config.h>
32 #include <string.h>
33 #include <math.h>
34 #include <sys/time.h>
35 #include <glib.h>
36 #include <libsigrok/libsigrok.h>
37 #include "libsigrok-internal.h"
38 #include "scpi.h"
39
40 #define LOG_PREFIX "std"
41
42 SR_PRIV const uint32_t NO_OPTS[1] = {};
43
44 /**
45  * Standard driver init() callback API helper.
46  *
47  * This function can be used to simplify most driver's init() API callback.
48  *
49  * Create a new 'struct drv_context' (drvc), assign sr_ctx to it, and
50  * then assign 'drvc' to the 'struct sr_dev_driver' (di) that is passed.
51  *
52  * @param[in] di The driver instance to use. Must not be NULL.
53  * @param[in] sr_ctx The libsigrok context to assign. May be NULL.
54  *
55  * @retval SR_OK Success.
56  * @retval SR_ERR_ARG Invalid argument.
57  */
58 SR_PRIV int std_init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
59 {
60         struct drv_context *drvc;
61
62         if (!di) {
63                 sr_err("%s: Invalid argument.", __func__);
64                 return SR_ERR_ARG;
65         }
66
67         drvc = g_malloc0(sizeof(struct drv_context));
68         drvc->sr_ctx = sr_ctx;
69         drvc->instances = NULL;
70         di->context = drvc;
71
72         return SR_OK;
73 }
74
75 /**
76  * Standard driver cleanup() callback API helper.
77  *
78  * This function can be used to simplify most driver's cleanup() API callback.
79  *
80  * Free all device instances by calling sr_dev_clear() and then release any
81  * resources allocated by std_init().
82  *
83  * @param[in] di The driver instance to use. Must not be NULL.
84  *
85  * @retval SR_OK Success.
86  * @retval SR_ERR_ARG Invalid argument.
87  * @retval other Other error.
88  */
89 SR_PRIV int std_cleanup(const struct sr_dev_driver *di)
90 {
91         int ret;
92
93         if (!di) {
94                 sr_err("%s: Invalid argument.", __func__);
95                 return SR_ERR_ARG;
96         }
97
98         ret = sr_dev_clear(di);
99         g_free(di->context);
100
101         return ret;
102 }
103
104 /**
105  * Dummmy driver dev_open() callback API helper.
106  *
107  * @param[in] sdi The device instance to use. May be NULL (unused).
108  *
109  * @retval SR_OK Success.
110  */
111 SR_PRIV int std_dummy_dev_open(struct sr_dev_inst *sdi)
112 {
113         (void)sdi;
114
115         return SR_OK;
116 }
117
118 /**
119  * Dummmy driver dev_close() callback API helper.
120  *
121  * @param[in] sdi The device instance to use. May be NULL (unused).
122  *
123  * @retval SR_OK Success.
124  */
125 SR_PRIV int std_dummy_dev_close(struct sr_dev_inst *sdi)
126 {
127         (void)sdi;
128
129         return SR_OK;
130 }
131
132 /**
133  * Dummmy driver dev_acquisition_start() callback API helper.
134  *
135  * @param[in] sdi The device instance to use. May be NULL (unused).
136  *
137  * @retval SR_OK Success.
138  */
139 SR_PRIV int std_dummy_dev_acquisition_start(const struct sr_dev_inst *sdi)
140 {
141         (void)sdi;
142
143         return SR_OK;
144 }
145
146 /**
147  * Dummmy driver dev_acquisition_stop() callback API helper.
148  *
149  * @param[in] sdi The device instance to use. May be NULL (unused).
150  *
151  * @retval SR_OK Success.
152  */
153 SR_PRIV int std_dummy_dev_acquisition_stop(struct sr_dev_inst *sdi)
154 {
155         (void)sdi;
156
157         return SR_OK;
158 }
159
160 /**
161  * Standard API helper for sending an SR_DF_HEADER packet.
162  *
163  * This function can be used to simplify most drivers'
164  * dev_acquisition_start() API callback.
165  *
166  * @param[in] sdi The device instance to use. Must not be NULL.
167  *
168  * @retval SR_OK Success.
169  * @retval SR_ERR_ARG Invalid argument.
170  * @retval other Other error.
171  */
172 SR_PRIV int std_session_send_df_header(const struct sr_dev_inst *sdi)
173 {
174         const char *prefix;
175         int ret;
176         struct sr_datafeed_packet packet;
177         struct sr_datafeed_header header;
178
179         if (!sdi) {
180                 sr_err("%s: Invalid argument.", __func__);
181                 return SR_ERR_ARG;
182         }
183
184         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
185
186         /* Send header packet to the session bus. */
187         packet.type = SR_DF_HEADER;
188         packet.payload = (uint8_t *)&header;
189         header.feed_version = 1;
190         gettimeofday(&header.starttime, NULL);
191
192         if ((ret = sr_session_send(sdi, &packet)) < 0) {
193                 sr_err("%s: Failed to send SR_DF_HEADER packet: %d.", prefix, ret);
194                 return ret;
195         }
196
197         return SR_OK;
198 }
199
200 /**
201  * Standard API helper for sending an SR_DF_END packet.
202  *
203  * This function can be used to simplify most drivers'
204  * dev_acquisition_stop() API callback.
205  *
206  * @param[in] sdi The device instance to use. Must not be NULL.
207  *
208  * @retval SR_OK Success.
209  * @retval SR_ERR_ARG Invalid argument.
210  * @retval other Other error.
211  */
212 SR_PRIV int std_session_send_df_end(const struct sr_dev_inst *sdi)
213 {
214         const char *prefix;
215         int ret;
216         struct sr_datafeed_packet packet;
217
218         if (!sdi) {
219                 sr_err("%s: Invalid argument.", __func__);
220                 return SR_ERR_ARG;
221         }
222
223         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
224
225         packet.type = SR_DF_END;
226         packet.payload = NULL;
227
228         if ((ret = sr_session_send(sdi, &packet)) < 0) {
229                 sr_err("%s: Failed to send SR_DF_END packet: %d.", prefix, ret);
230                 return ret;
231         }
232
233         return SR_OK;
234 }
235
236 /**
237  * Standard API helper for sending an SR_DF_FRAME_BEGIN packet.
238  *
239  * This function can be used to simplify most drivers'
240  * frame handling.
241  *
242  * @param[in] sdi The device instance to use. Must not be NULL.
243  *
244  * @retval SR_OK Success.
245  * @retval SR_ERR_ARG Invalid argument.
246  * @retval other Other error.
247  */
248 SR_PRIV int std_session_send_frame_begin(const struct sr_dev_inst *sdi)
249 {
250         const char *prefix;
251         int ret;
252         struct sr_datafeed_packet packet;
253
254         if (!sdi) {
255                 sr_err("%s: Invalid argument.", __func__);
256                 return SR_ERR_ARG;
257         }
258
259         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
260
261         packet.type = SR_DF_FRAME_BEGIN;
262         packet.payload = NULL;
263
264         if ((ret = sr_session_send(sdi, &packet)) < 0) {
265                 sr_err("%s: Failed to send SR_DF_FRAME_BEGIN packet: %d.", prefix, ret);
266                 return ret;
267         }
268
269         return SR_OK;
270 }
271
272 /**
273  * Standard API helper for sending an SR_DF_FRAME_END packet.
274  *
275  * This function can be used to simplify most drivers'
276  * frame handling.
277  *
278  * @param[in] sdi The device instance to use. Must not be NULL.
279  *
280  * @retval SR_OK Success.
281  * @retval SR_ERR_ARG Invalid argument.
282  * @retval other Other error.
283  */
284 SR_PRIV int std_session_send_frame_end(const struct sr_dev_inst *sdi)
285 {
286         const char *prefix;
287         int ret;
288         struct sr_datafeed_packet packet;
289
290         if (!sdi) {
291                 sr_err("%s: Invalid argument.", __func__);
292                 return SR_ERR_ARG;
293         }
294
295         prefix = (sdi->driver) ? sdi->driver->name : "unknown";
296
297         packet.type = SR_DF_FRAME_END;
298         packet.payload = NULL;
299
300         if ((ret = sr_session_send(sdi, &packet)) < 0) {
301                 sr_err("%s: Failed to send SR_DF_FRAME_END packet: %d.", prefix, ret);
302                 return ret;
303         }
304
305         return SR_OK;
306 }
307
308 #ifdef HAVE_SERIAL_COMM
309
310 /**
311  * Standard serial driver dev_open() callback API helper.
312  *
313  * This function can be used to implement the dev_open() driver API
314  * callback in drivers that use a serial port. The port is opened
315  * with the SERIAL_RDWR flag.
316  *
317  * @param[in] sdi The device instance to use. Must not be NULL.
318  *
319  * @retval SR_OK Success.
320  * @retval SR_ERR_ARG Invalid argument.
321  * @retval other Serial port open failed.
322  */
323 SR_PRIV int std_serial_dev_open(struct sr_dev_inst *sdi)
324 {
325         struct sr_serial_dev_inst *serial;
326
327         if (!sdi) {
328                 sr_err("%s: Invalid argument.", __func__);
329                 return SR_ERR_ARG;
330         }
331
332         serial = sdi->conn;
333
334         return serial_open(serial, SERIAL_RDWR);
335 }
336
337 /**
338  * Standard serial driver dev_close() callback API helper.
339  *
340  * This function can be used to implement the dev_close() driver API
341  * callback in drivers that use a serial port.
342  *
343  * @param[in] sdi The device instance to use. Must not be NULL.
344  *
345  * @retval SR_OK Success.
346  * @retval SR_ERR_ARG Invalid argument.
347  * @retval other Serial port close failed.
348  */
349 SR_PRIV int std_serial_dev_close(struct sr_dev_inst *sdi)
350 {
351         struct sr_serial_dev_inst *serial;
352
353         if (!sdi) {
354                 sr_err("%s: Invalid argument.", __func__);
355                 return SR_ERR_ARG;
356         }
357
358         serial = sdi->conn;
359
360         return serial_close(serial);
361 }
362
363 /**
364  * Standard serial driver dev_acquisition_stop() callback API helper.
365  *
366  * This function can be used to simplify most (serial port based) drivers'
367  * dev_acquisition_stop() API callback.
368  *
369  * @param[in] sdi The device instance for which acquisition should stop.
370  *                Must not be NULL.
371  *
372  * @retval SR_OK Success.
373  * @retval SR_ERR_ARG Invalid argument.
374  * @retval other Other error.
375  */
376 SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi)
377 {
378         struct sr_serial_dev_inst *serial;
379         const char *prefix;
380         int ret;
381
382         if (!sdi) {
383                 sr_err("%s: Invalid argument.", __func__);
384                 return SR_ERR_ARG;
385         }
386
387         serial = sdi->conn;
388         prefix = sdi->driver->name;
389
390         if ((ret = serial_source_remove(sdi->session, serial)) < 0) {
391                 sr_err("%s: Failed to remove source: %d.", prefix, ret);
392                 return ret;
393         }
394
395         if ((ret = sr_dev_close(sdi)) < 0) {
396                 sr_err("%s: Failed to close device: %d.", prefix, ret);
397                 return ret;
398         }
399
400         return std_session_send_df_end(sdi);
401 }
402
403 #endif
404
405 /**
406  * Standard driver dev_clear() callback API helper.
407  *
408  * Clear driver, this means, close all instances.
409  *
410  * This function can be used to implement the dev_clear() driver API
411  * callback. dev_close() is called before every sr_dev_inst is cleared.
412  *
413  * The only limitation is driver-specific device contexts (sdi->priv / devc).
414  * These are freed, but any dynamic allocation within structs stored
415  * there cannot be freed.
416  *
417  * @param[in] driver The driver which will have its instances released.
418  *                   Must not be NULL.
419  * @param[in] clear_private If not NULL, this points to a function called
420  *            with sdi->priv (devc) as argument. The function can then clear
421  *            any device instance-specific resources kept there.
422  *            It must NOT clear the struct pointed to by sdi->priv (devc),
423  *            since this function will always free it after clear_private()
424  *            has run.
425  *
426  * @retval SR_OK Success.
427  * @retval SR_ERR_ARG Invalid argument.
428  * @retval SR_ERR_BUG Implementation bug.
429  * @retval other Other error.
430  */
431 SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver,
432                 std_dev_clear_callback clear_private)
433 {
434         struct drv_context *drvc;
435         struct sr_dev_inst *sdi;
436         GSList *l;
437         int ret;
438
439         if (!driver) {
440                 sr_err("%s: Invalid argument.", __func__);
441                 return SR_ERR_ARG;
442         }
443
444         drvc = driver->context; /* Caller checked for context != NULL. */
445
446         ret = SR_OK;
447         for (l = drvc->instances; l; l = l->next) {
448                 if (!(sdi = l->data)) {
449                         sr_err("%s: Invalid device instance.", __func__);
450                         ret = SR_ERR_BUG;
451                         continue;
452                 }
453                 if (driver->dev_close)
454                         driver->dev_close(sdi);
455
456                 if (sdi->conn) {
457 #ifdef HAVE_SERIAL_COMM
458                         if (sdi->inst_type == SR_INST_SERIAL)
459                                 sr_serial_dev_inst_free(sdi->conn);
460 #endif
461 #ifdef HAVE_LIBUSB_1_0
462                         if (sdi->inst_type == SR_INST_USB)
463                                 sr_usb_dev_inst_free(sdi->conn);
464 #endif
465                         if (sdi->inst_type == SR_INST_SCPI)
466                                 sr_scpi_free(sdi->conn);
467                         if (sdi->inst_type == SR_INST_MODBUS)
468                                 sr_modbus_free(sdi->conn);
469                 }
470
471                 /* Clear driver-specific stuff, if any. */
472                 if (clear_private)
473                         clear_private(sdi->priv);
474
475                 /* Clear sdi->priv (devc). */
476                 g_free(sdi->priv);
477
478                 sr_dev_inst_free(sdi);
479         }
480
481         g_slist_free(drvc->instances);
482         drvc->instances = NULL;
483
484         return ret;
485 }
486
487 SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver)
488 {
489         return std_dev_clear_with_callback(driver, NULL);
490 }
491
492 /**
493  * Standard driver dev_list() callback API helper.
494  *
495  * This function can be used as the dev_list() callback by most drivers.
496  *
497  * Return the devices contained in the driver context instances list.
498  *
499  * @param[in] di The driver instance to use. Must not be NULL.
500  *
501  * @retval NULL Error, or the list is empty.
502  * @retval other The list of device instances of this driver.
503  */
504 SR_PRIV GSList *std_dev_list(const struct sr_dev_driver *di)
505 {
506         struct drv_context *drvc;
507
508         if (!di) {
509                 sr_err("%s: Invalid argument.", __func__);
510                 return NULL;
511         }
512
513         drvc = di->context;
514
515         return drvc->instances;
516 }
517
518 /**
519  * Standard driver scan() callback API helper.
520  *
521  * This function can be used to perform common tasks required by a driver's
522  * scan() callback. It will initialize the driver for each device on the list
523  * and add the devices on the list to the driver's device instance list.
524  * Usually it should be used as the last step in the scan() callback, right
525  * before returning.
526  *
527  * Note: This function can only be used if std_init() has been called
528  * previously by the driver.
529  *
530  * Example:
531  * @code{c}
532  * static GSList *scan(struct sr_dev_driver *di, GSList *options)
533  * {
534  *     struct GSList *device;
535  *     struct sr_dev_inst *sdi;
536  *
537  *     sdi = g_new0(sr_dev_inst, 1);
538  *     sdi->vendor = ...;
539  *     ...
540  *     devices = g_slist_append(devices, sdi);
541  *     ...
542  *     return std_scan_complete(di, devices);
543  * }
544  * @endcode
545  *
546  * @param[in] di The driver instance to use. Must not be NULL.
547  * @param[in] devices List of newly discovered devices (struct sr_dev_inst).
548  *                    May be NULL.
549  *
550  * @return The @p devices list.
551  */
552 SR_PRIV GSList *std_scan_complete(struct sr_dev_driver *di, GSList *devices)
553 {
554         struct drv_context *drvc;
555         GSList *l;
556
557         if (!di) {
558                 sr_err("Invalid driver instance (di), cannot complete scan.");
559                 return NULL;
560         }
561
562         drvc = di->context;
563
564         for (l = devices; l; l = l->next) {
565                 struct sr_dev_inst *sdi = l->data;
566                 if (!sdi) {
567                         sr_err("Invalid device instance, cannot complete scan.");
568                         return NULL;
569                 }
570                 sdi->driver = di;
571         }
572
573         drvc->instances = g_slist_concat(drvc->instances, g_slist_copy(devices));
574
575         return devices;
576 }
577
578 SR_PRIV int std_opts_config_list(uint32_t key, GVariant **data,
579         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg,
580         const uint32_t scanopts[], size_t scansize, const uint32_t drvopts[],
581         size_t drvsize, const uint32_t devopts[], size_t devsize)
582 {
583         switch (key) {
584         case SR_CONF_SCAN_OPTIONS:
585                 /* Always return scanopts, regardless of sdi or cg. */
586                 if (!scanopts || scanopts == NO_OPTS)
587                         return SR_ERR_ARG;
588                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
589                         scanopts, scansize, sizeof(uint32_t));
590                 break;
591         case SR_CONF_DEVICE_OPTIONS:
592                 if (!sdi) {
593                         /* sdi == NULL: return drvopts. */
594                         if (!drvopts || drvopts == NO_OPTS)
595                                 return SR_ERR_ARG;
596                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
597                                 drvopts, drvsize, sizeof(uint32_t));
598                 } else if (sdi && !cg) {
599                         /* sdi != NULL, cg == NULL: return devopts. */
600                         if (!devopts || devopts == NO_OPTS)
601                                 return SR_ERR_ARG;
602                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
603                                 devopts, devsize, sizeof(uint32_t));
604                 } else {
605                         /*
606                          * Note: sdi != NULL, cg != NULL is not handled by
607                          * this function since it's very driver-specific.
608                          */
609                         sr_err("%s: %s: sdi/cg != NULL: not handling.",
610                                sdi->driver->name, __func__);
611                         return SR_ERR_ARG;
612                 }
613                 break;
614         default:
615                 return SR_ERR_NA;
616         }
617
618         return SR_OK;
619 }
620
621 SR_PRIV GVariant *std_gvar_tuple_array(const uint64_t a[][2], unsigned int n)
622 {
623         unsigned int i;
624         GVariant *rational[2];
625         GVariantBuilder gvb;
626
627         g_variant_builder_init(&gvb, G_VARIANT_TYPE_TUPLE);
628
629         for (i = 0; i < n; i++) {
630                 rational[0] = g_variant_new_uint64(a[i][0]);
631                 rational[1] = g_variant_new_uint64(a[i][1]);
632
633                 /* FIXME: Valgrind reports a memory leak here. */
634                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
635         }
636
637         return g_variant_builder_end(&gvb);
638 }
639
640 SR_PRIV GVariant *std_gvar_tuple_rational(const struct sr_rational *r, unsigned int n)
641 {
642         unsigned int i;
643         GVariant *rational[2];
644         GVariantBuilder gvb;
645
646         g_variant_builder_init(&gvb, G_VARIANT_TYPE_TUPLE);
647
648         for (i = 0; i < n; i++) {
649                 rational[0] = g_variant_new_uint64(r[i].p);
650                 rational[1] = g_variant_new_uint64(r[i].q);
651
652                 /* FIXME: Valgrind reports a memory leak here. */
653                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
654         }
655
656         return g_variant_builder_end(&gvb);
657 }
658
659 static GVariant *samplerate_helper(const uint64_t samplerates[], unsigned int n, const char *str)
660 {
661         GVariant *gvar;
662         GVariantBuilder gvb;
663
664         g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
665         gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
666                         n, sizeof(uint64_t));
667         g_variant_builder_add(&gvb, "{sv}", str, gvar);
668
669         return g_variant_builder_end(&gvb);
670 }
671
672 SR_PRIV GVariant *std_gvar_samplerates(const uint64_t samplerates[], unsigned int n)
673 {
674         return samplerate_helper(samplerates, n, "samplerates");
675 }
676
677 SR_PRIV GVariant *std_gvar_samplerates_steps(const uint64_t samplerates[], unsigned int n)
678 {
679         return samplerate_helper(samplerates, n, "samplerate-steps");
680 }
681
682 SR_PRIV GVariant *std_gvar_min_max_step(double min, double max, double step)
683 {
684         GVariantBuilder gvb;
685
686         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
687
688         g_variant_builder_add_value(&gvb, g_variant_new_double(min));
689         g_variant_builder_add_value(&gvb, g_variant_new_double(max));
690         g_variant_builder_add_value(&gvb, g_variant_new_double(step));
691
692         return g_variant_builder_end(&gvb);
693 }
694
695 SR_PRIV GVariant *std_gvar_min_max_step_array(const double a[3])
696 {
697         unsigned int i;
698         GVariantBuilder gvb;
699
700         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
701
702         for (i = 0; i < 3; i++)
703                 g_variant_builder_add_value(&gvb, g_variant_new_double(a[i]));
704
705         return g_variant_builder_end(&gvb);
706 }
707
708 SR_PRIV GVariant *std_gvar_min_max_step_thresholds(const double min, const double max, const double step)
709 {
710         double d, v;
711         GVariant *gvar, *range[2];
712         GVariantBuilder gvb;
713
714         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
715
716         for (d = min; d <= max; d += step) {
717                 /*
718                  * We will never see exactly 0.0 because of the error we're
719                  * accumulating, so catch the "zero" value and force it to be 0.
720                  */
721                 v = ((d > (-step / 2)) && (d < (step / 2))) ? 0 : d;
722
723                 range[0] = g_variant_new_double(v);
724                 range[1] = g_variant_new_double(v);
725
726                 gvar = g_variant_new_tuple(range, 2);
727                 g_variant_builder_add_value(&gvb, gvar);
728         }
729
730         return g_variant_builder_end(&gvb);
731 }
732
733 SR_PRIV GVariant *std_gvar_tuple_u64(uint64_t low, uint64_t high)
734 {
735         GVariant *range[2];
736
737         range[0] = g_variant_new_uint64(low);
738         range[1] = g_variant_new_uint64(high);
739
740         return g_variant_new_tuple(range, 2);
741 }
742
743 SR_PRIV GVariant *std_gvar_tuple_double(double low, double high)
744 {
745         GVariant *range[2];
746
747         range[0] = g_variant_new_double(low);
748         range[1] = g_variant_new_double(high);
749
750         return g_variant_new_tuple(range, 2);
751 }
752
753 SR_PRIV GVariant *std_gvar_array_i32(const int32_t a[], unsigned int n)
754 {
755         return g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
756                                 a, n, sizeof(int32_t));
757 }
758
759 SR_PRIV GVariant *std_gvar_array_u32(const uint32_t a[], unsigned int n)
760 {
761         return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
762                                 a, n, sizeof(uint32_t));
763 }
764
765 SR_PRIV GVariant *std_gvar_array_u64(const uint64_t a[], unsigned int n)
766 {
767         return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64,
768                                 a, n, sizeof(uint64_t));
769 }
770
771 SR_PRIV GVariant *std_gvar_array_str(const char *a[], unsigned int n)
772 {
773         GVariant *gvar;
774         GVariantBuilder *builder;
775         unsigned int i;
776
777         builder = g_variant_builder_new(G_VARIANT_TYPE ("as"));
778
779         for (i = 0; i < n; i++)
780                 g_variant_builder_add(builder, "s", a[i]);
781
782         gvar = g_variant_new("as", builder);
783         g_variant_builder_unref(builder);
784
785         return gvar;
786 }
787
788 SR_PRIV GVariant *std_gvar_thresholds(const double a[][2], unsigned int n)
789 {
790         unsigned int i;
791         GVariant *gvar, *range[2];
792         GVariantBuilder gvb;
793
794         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
795
796         for (i = 0; i < n; i++) {
797                 range[0] = g_variant_new_double(a[i][0]);
798                 range[1] = g_variant_new_double(a[i][1]);
799                 gvar = g_variant_new_tuple(range, 2);
800                 g_variant_builder_add_value(&gvb, gvar);
801         }
802
803         return g_variant_builder_end(&gvb);
804 }
805
806 /* Return the index of 'data' in the array 'arr' (or -1). */
807 static int find_in_array(GVariant *data, const GVariantType *type,
808                          const void *arr, unsigned int n)
809 {
810         const char * const *sarr;
811         const char *s;
812         const uint64_t *u64arr;
813         const uint8_t *u8arr;
814         uint64_t u64;
815         uint8_t u8;
816         unsigned int i;
817
818         if (!g_variant_is_of_type(data, type))
819                 return -1;
820
821         switch (g_variant_classify(data)) {
822         case G_VARIANT_CLASS_STRING:
823                 s = g_variant_get_string(data, NULL);
824                 sarr = arr;
825
826                 for (i = 0; i < n; i++)
827                         if (!strcmp(s, sarr[i]))
828                                 return i;
829                 break;
830         case G_VARIANT_CLASS_UINT64:
831                 u64 = g_variant_get_uint64(data);
832                 u64arr = arr;
833
834                 for (i = 0; i < n; i++)
835                         if (u64 == u64arr[i])
836                                 return i;
837                 break;
838         case G_VARIANT_CLASS_BYTE:
839                 u8 = g_variant_get_byte(data);
840                 u8arr = arr;
841
842                 for (i = 0; i < n; i++)
843                         if (u8 == u8arr[i])
844                                 return i;
845         default:
846                 break;
847         }
848
849         return -1;
850 }
851
852 SR_PRIV int std_str_idx(GVariant *data, const char *a[], unsigned int n)
853 {
854         return find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
855 }
856
857 SR_PRIV int std_u64_idx(GVariant *data, const uint64_t a[], unsigned int n)
858 {
859         return find_in_array(data, G_VARIANT_TYPE_UINT64, a, n);
860 }
861
862 SR_PRIV int std_u8_idx(GVariant *data, const uint8_t a[], unsigned int n)
863 {
864         return find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
865 }
866
867 SR_PRIV int std_str_idx_s(const char *s, const char *a[], unsigned int n)
868 {
869         int idx;
870         GVariant *data;
871
872         data = g_variant_new_string(s);
873         idx = find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
874         g_variant_unref(data);
875
876         return idx;
877 }
878
879 SR_PRIV int std_u8_idx_s(uint8_t b, const uint8_t a[], unsigned int n)
880 {
881         int idx;
882         GVariant *data;
883
884         data = g_variant_new_byte(b);
885         idx = find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
886         g_variant_unref(data);
887
888         return idx;
889 }
890
891 SR_PRIV int std_u64_tuple_idx(GVariant *data, const uint64_t a[][2], unsigned int n)
892 {
893         unsigned int i;
894         uint64_t low, high;
895
896         g_variant_get(data, "(tt)", &low, &high);
897
898         for (i = 0; i < n; i++)
899                 if (a[i][0] == low && a[i][1] == high)
900                         return i;
901
902         return -1;
903 }
904
905 SR_PRIV int std_double_tuple_idx(GVariant *data, const double a[][2], unsigned int n)
906 {
907         unsigned int i;
908         double low, high;
909
910         g_variant_get(data, "(dd)", &low, &high);
911
912         for (i = 0; i < n; i++)
913                 if ((fabs(a[i][0] - low) < 0.1) && ((fabs(a[i][1] - high) < 0.1)))
914                         return i;
915
916         return -1;
917 }
918
919 SR_PRIV int std_double_tuple_idx_d0(const double d, const double a[][2], unsigned int n)
920 {
921         unsigned int i;
922
923         for (i = 0; i < n; i++)
924                 if (d == a[i][0])
925                         return i;
926
927         return -1;
928 }
929
930 SR_PRIV int std_cg_idx(const struct sr_channel_group *cg, struct sr_channel_group *a[], unsigned int n)
931 {
932         unsigned int i;
933
934         for (i = 0; i < n; i++)
935                 if (cg == a[i])
936                         return i;
937
938         return -1;
939 }
940
941 SR_PRIV int std_dummy_set_params(struct sr_serial_dev_inst *serial,
942         int baudrate, int bits, int parity, int stopbits,
943         int flowcontrol, int rts, int dtr)
944 {
945         (void)serial;
946         (void)baudrate;
947         (void)bits;
948         (void)parity;
949         (void)stopbits;
950         (void)flowcontrol;
951         (void)rts;
952         (void)dtr;
953
954         return SR_OK;
955 }
956