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