]> sigrok.org Git - libsigrok.git/blob - src/std.c
Backport recent changes from mainline.
[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         return std_session_send_df_end(sdi);
396 }
397
398 #endif
399
400 /**
401  * Standard driver dev_clear() callback API helper.
402  *
403  * Clear driver, this means, close all instances.
404  *
405  * This function can be used to implement the dev_clear() driver API
406  * callback. dev_close() is called before every sr_dev_inst is cleared.
407  *
408  * The only limitation is driver-specific device contexts (sdi->priv / devc).
409  * These are freed, but any dynamic allocation within structs stored
410  * there cannot be freed.
411  *
412  * @param[in] driver The driver which will have its instances released.
413  *                   Must not be NULL.
414  * @param[in] clear_private If not NULL, this points to a function called
415  *            with sdi->priv (devc) as argument. The function can then clear
416  *            any device instance-specific resources kept there.
417  *            It must NOT clear the struct pointed to by sdi->priv (devc),
418  *            since this function will always free it after clear_private()
419  *            has run.
420  *
421  * @retval SR_OK Success.
422  * @retval SR_ERR_ARG Invalid argument.
423  * @retval SR_ERR_BUG Implementation bug.
424  * @retval other Other error.
425  */
426 SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver,
427                 std_dev_clear_callback clear_private)
428 {
429         struct drv_context *drvc;
430         struct sr_dev_inst *sdi;
431         GSList *l;
432         int ret;
433
434         if (!driver) {
435                 sr_err("%s: Invalid argument.", __func__);
436                 return SR_ERR_ARG;
437         }
438
439         drvc = driver->context; /* Caller checked for context != NULL. */
440
441         ret = SR_OK;
442         for (l = drvc->instances; l; l = l->next) {
443                 if (!(sdi = l->data)) {
444                         sr_err("%s: Invalid device instance.", __func__);
445                         ret = SR_ERR_BUG;
446                         continue;
447                 }
448                 if (driver->dev_close)
449                         driver->dev_close(sdi);
450
451                 if (sdi->conn) {
452 #ifdef HAVE_SERIAL_COMM
453                         if (sdi->inst_type == SR_INST_SERIAL)
454                                 sr_serial_dev_inst_free(sdi->conn);
455 #endif
456 #ifdef HAVE_LIBUSB_1_0
457                         if (sdi->inst_type == SR_INST_USB)
458                                 sr_usb_dev_inst_free(sdi->conn);
459 #endif
460                         if (sdi->inst_type == SR_INST_SCPI)
461                                 sr_scpi_free(sdi->conn);
462                         if (sdi->inst_type == SR_INST_MODBUS)
463                                 sr_modbus_free(sdi->conn);
464                 }
465
466                 /* Clear driver-specific stuff, if any. */
467                 if (clear_private)
468                         clear_private(sdi->priv);
469
470                 /* Clear sdi->priv (devc). */
471                 g_free(sdi->priv);
472
473                 sr_dev_inst_free(sdi);
474         }
475
476         g_slist_free(drvc->instances);
477         drvc->instances = NULL;
478
479         return ret;
480 }
481
482 SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver)
483 {
484         return std_dev_clear_with_callback(driver, NULL);
485 }
486
487 /**
488  * Standard driver dev_list() callback API helper.
489  *
490  * This function can be used as the dev_list() callback by most drivers.
491  *
492  * Return the devices contained in the driver context instances list.
493  *
494  * @param[in] di The driver instance to use. Must not be NULL.
495  *
496  * @retval NULL Error, or the list is empty.
497  * @retval other The list of device instances of this driver.
498  */
499 SR_PRIV GSList *std_dev_list(const struct sr_dev_driver *di)
500 {
501         struct drv_context *drvc;
502
503         if (!di) {
504                 sr_err("%s: Invalid argument.", __func__);
505                 return NULL;
506         }
507
508         drvc = di->context;
509
510         return drvc->instances;
511 }
512
513 /**
514  * Standard driver scan() callback API helper.
515  *
516  * This function can be used to perform common tasks required by a driver's
517  * scan() callback. It will initialize the driver for each device on the list
518  * and add the devices on the list to the driver's device instance list.
519  * Usually it should be used as the last step in the scan() callback, right
520  * before returning.
521  *
522  * Note: This function can only be used if std_init() has been called
523  * previously by the driver.
524  *
525  * Example:
526  * @code{c}
527  * static GSList *scan(struct sr_dev_driver *di, GSList *options)
528  * {
529  *     struct GSList *device;
530  *     struct sr_dev_inst *sdi;
531  *
532  *     sdi = g_new0(sr_dev_inst, 1);
533  *     sdi->vendor = ...;
534  *     ...
535  *     devices = g_slist_append(devices, sdi);
536  *     ...
537  *     return std_scan_complete(di, devices);
538  * }
539  * @endcode
540  *
541  * @param[in] di The driver instance to use. Must not be NULL.
542  * @param[in] devices List of newly discovered devices (struct sr_dev_inst).
543  *                    May be NULL.
544  *
545  * @return The @p devices list.
546  */
547 SR_PRIV GSList *std_scan_complete(struct sr_dev_driver *di, GSList *devices)
548 {
549         struct drv_context *drvc;
550         GSList *l;
551
552         if (!di) {
553                 sr_err("Invalid driver instance (di), cannot complete scan.");
554                 return NULL;
555         }
556
557         drvc = di->context;
558
559         for (l = devices; l; l = l->next) {
560                 struct sr_dev_inst *sdi = l->data;
561                 if (!sdi) {
562                         sr_err("Invalid device instance, cannot complete scan.");
563                         return NULL;
564                 }
565                 sdi->driver = di;
566         }
567
568         drvc->instances = g_slist_concat(drvc->instances, g_slist_copy(devices));
569
570         return devices;
571 }
572
573 SR_PRIV int std_opts_config_list(uint32_t key, GVariant **data,
574         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg,
575         const uint32_t scanopts[], size_t scansize, const uint32_t drvopts[],
576         size_t drvsize, const uint32_t devopts[], size_t devsize)
577 {
578         switch (key) {
579         case SR_CONF_SCAN_OPTIONS:
580                 /* Always return scanopts, regardless of sdi or cg. */
581                 if (!scanopts || scanopts == NO_OPTS)
582                         return SR_ERR_ARG;
583                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
584                         scanopts, scansize, sizeof(uint32_t));
585                 break;
586         case SR_CONF_DEVICE_OPTIONS:
587                 if (!sdi) {
588                         /* sdi == NULL: return drvopts. */
589                         if (!drvopts || drvopts == NO_OPTS)
590                                 return SR_ERR_ARG;
591                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
592                                 drvopts, drvsize, sizeof(uint32_t));
593                 } else if (sdi && !cg) {
594                         /* sdi != NULL, cg == NULL: return devopts. */
595                         if (!devopts || devopts == NO_OPTS)
596                                 return SR_ERR_ARG;
597                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
598                                 devopts, devsize, sizeof(uint32_t));
599                 } else {
600                         /*
601                          * Note: sdi != NULL, cg != NULL is not handled by
602                          * this function since it's very driver-specific.
603                          */
604                         sr_err("%s: %s: sdi/cg != NULL: not handling.",
605                                sdi->driver->name, __func__);
606                         return SR_ERR_ARG;
607                 }
608                 break;
609         default:
610                 return SR_ERR_NA;
611         }
612
613         return SR_OK;
614 }
615
616 SR_PRIV GVariant *std_gvar_tuple_array(const uint64_t a[][2], unsigned int n)
617 {
618         unsigned int i;
619         GVariant *rational[2];
620         GVariantBuilder gvb;
621
622         g_variant_builder_init(&gvb, G_VARIANT_TYPE_TUPLE);
623
624         for (i = 0; i < n; i++) {
625                 rational[0] = g_variant_new_uint64(a[i][0]);
626                 rational[1] = g_variant_new_uint64(a[i][1]);
627
628                 /* FIXME: Valgrind reports a memory leak here. */
629                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
630         }
631
632         return g_variant_builder_end(&gvb);
633 }
634
635 SR_PRIV GVariant *std_gvar_tuple_rational(const struct sr_rational *r, unsigned int n)
636 {
637         unsigned int i;
638         GVariant *rational[2];
639         GVariantBuilder gvb;
640
641         g_variant_builder_init(&gvb, G_VARIANT_TYPE_TUPLE);
642
643         for (i = 0; i < n; i++) {
644                 rational[0] = g_variant_new_uint64(r[i].p);
645                 rational[1] = g_variant_new_uint64(r[i].q);
646
647                 /* FIXME: Valgrind reports a memory leak here. */
648                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
649         }
650
651         return g_variant_builder_end(&gvb);
652 }
653
654 static GVariant *samplerate_helper(const uint64_t samplerates[], unsigned int n, const char *str)
655 {
656         GVariant *gvar;
657         GVariantBuilder gvb;
658
659         g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
660         gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
661                         n, sizeof(uint64_t));
662         g_variant_builder_add(&gvb, "{sv}", str, gvar);
663
664         return g_variant_builder_end(&gvb);
665 }
666
667 SR_PRIV GVariant *std_gvar_samplerates(const uint64_t samplerates[], unsigned int n)
668 {
669         return samplerate_helper(samplerates, n, "samplerates");
670 }
671
672 SR_PRIV GVariant *std_gvar_samplerates_steps(const uint64_t samplerates[], unsigned int n)
673 {
674         return samplerate_helper(samplerates, n, "samplerate-steps");
675 }
676
677 SR_PRIV GVariant *std_gvar_min_max_step(double min, double max, double step)
678 {
679         GVariantBuilder gvb;
680
681         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
682
683         g_variant_builder_add_value(&gvb, g_variant_new_double(min));
684         g_variant_builder_add_value(&gvb, g_variant_new_double(max));
685         g_variant_builder_add_value(&gvb, g_variant_new_double(step));
686
687         return g_variant_builder_end(&gvb);
688 }
689
690 SR_PRIV GVariant *std_gvar_min_max_step_array(const double a[3])
691 {
692         unsigned int i;
693         GVariantBuilder gvb;
694
695         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
696
697         for (i = 0; i < 3; i++)
698                 g_variant_builder_add_value(&gvb, g_variant_new_double(a[i]));
699
700         return g_variant_builder_end(&gvb);
701 }
702
703 SR_PRIV GVariant *std_gvar_min_max_step_thresholds(const double min, const double max, const double step)
704 {
705         double d, v;
706         GVariant *gvar, *range[2];
707         GVariantBuilder gvb;
708
709         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
710
711         for (d = min; d <= max; d += step) {
712                 /*
713                  * We will never see exactly 0.0 because of the error we're
714                  * accumulating, so catch the "zero" value and force it to be 0.
715                  */
716                 v = ((d > (-step / 2)) && (d < (step / 2))) ? 0 : d;
717
718                 range[0] = g_variant_new_double(v);
719                 range[1] = g_variant_new_double(v);
720
721                 gvar = g_variant_new_tuple(range, 2);
722                 g_variant_builder_add_value(&gvb, gvar);
723         }
724
725         return g_variant_builder_end(&gvb);
726 }
727
728 SR_PRIV GVariant *std_gvar_tuple_u64(uint64_t low, uint64_t high)
729 {
730         GVariant *range[2];
731
732         range[0] = g_variant_new_uint64(low);
733         range[1] = g_variant_new_uint64(high);
734
735         return g_variant_new_tuple(range, 2);
736 }
737
738 SR_PRIV GVariant *std_gvar_tuple_double(double low, double high)
739 {
740         GVariant *range[2];
741
742         range[0] = g_variant_new_double(low);
743         range[1] = g_variant_new_double(high);
744
745         return g_variant_new_tuple(range, 2);
746 }
747
748 SR_PRIV GVariant *std_gvar_array_i32(const int32_t a[], unsigned int n)
749 {
750         return g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
751                                 a, n, sizeof(int32_t));
752 }
753
754 SR_PRIV GVariant *std_gvar_array_u32(const uint32_t a[], unsigned int n)
755 {
756         return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
757                                 a, n, sizeof(uint32_t));
758 }
759
760 SR_PRIV GVariant *std_gvar_array_u64(const uint64_t a[], unsigned int n)
761 {
762         return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64,
763                                 a, n, sizeof(uint64_t));
764 }
765
766 SR_PRIV GVariant *std_gvar_array_str(const char *a[], unsigned int n)
767 {
768         GVariant *gvar;
769         GVariantBuilder *builder;
770         unsigned int i;
771
772         builder = g_variant_builder_new(G_VARIANT_TYPE ("as"));
773
774         for (i = 0; i < n; i++)
775                 g_variant_builder_add(builder, "s", a[i]);
776
777         gvar = g_variant_new("as", builder);
778         g_variant_builder_unref(builder);
779
780         return gvar;
781 }
782
783 SR_PRIV GVariant *std_gvar_thresholds(const double a[][2], unsigned int n)
784 {
785         unsigned int i;
786         GVariant *gvar, *range[2];
787         GVariantBuilder gvb;
788
789         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
790
791         for (i = 0; i < n; i++) {
792                 range[0] = g_variant_new_double(a[i][0]);
793                 range[1] = g_variant_new_double(a[i][1]);
794                 gvar = g_variant_new_tuple(range, 2);
795                 g_variant_builder_add_value(&gvb, gvar);
796         }
797
798         return g_variant_builder_end(&gvb);
799 }
800
801 /* Return the index of 'data' in the array 'arr' (or -1). */
802 static int find_in_array(GVariant *data, const GVariantType *type,
803                          const void *arr, unsigned int n)
804 {
805         const char * const *sarr;
806         const char *s;
807         const uint64_t *u64arr;
808         const uint8_t *u8arr;
809         uint64_t u64;
810         uint8_t u8;
811         unsigned int i;
812
813         if (!g_variant_is_of_type(data, type))
814                 return -1;
815
816         switch (g_variant_classify(data)) {
817         case G_VARIANT_CLASS_STRING:
818                 s = g_variant_get_string(data, NULL);
819                 sarr = arr;
820
821                 for (i = 0; i < n; i++)
822                         if (!strcmp(s, sarr[i]))
823                                 return i;
824                 break;
825         case G_VARIANT_CLASS_UINT64:
826                 u64 = g_variant_get_uint64(data);
827                 u64arr = arr;
828
829                 for (i = 0; i < n; i++)
830                         if (u64 == u64arr[i])
831                                 return i;
832                 break;
833         case G_VARIANT_CLASS_BYTE:
834                 u8 = g_variant_get_byte(data);
835                 u8arr = arr;
836
837                 for (i = 0; i < n; i++)
838                         if (u8 == u8arr[i])
839                                 return i;
840         default:
841                 break;
842         }
843
844         return -1;
845 }
846
847 SR_PRIV int std_str_idx(GVariant *data, const char *a[], unsigned int n)
848 {
849         return find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
850 }
851
852 SR_PRIV int std_u64_idx(GVariant *data, const uint64_t a[], unsigned int n)
853 {
854         return find_in_array(data, G_VARIANT_TYPE_UINT64, a, n);
855 }
856
857 SR_PRIV int std_u8_idx(GVariant *data, const uint8_t a[], unsigned int n)
858 {
859         return find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
860 }
861
862 SR_PRIV int std_str_idx_s(const char *s, const char *a[], unsigned int n)
863 {
864         int idx;
865         GVariant *data;
866
867         data = g_variant_new_string(s);
868         idx = find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
869         g_variant_unref(data);
870
871         return idx;
872 }
873
874 SR_PRIV int std_u8_idx_s(uint8_t b, const uint8_t a[], unsigned int n)
875 {
876         int idx;
877         GVariant *data;
878
879         data = g_variant_new_byte(b);
880         idx = find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
881         g_variant_unref(data);
882
883         return idx;
884 }
885
886 SR_PRIV int std_u64_tuple_idx(GVariant *data, const uint64_t a[][2], unsigned int n)
887 {
888         unsigned int i;
889         uint64_t low, high;
890
891         g_variant_get(data, "(tt)", &low, &high);
892
893         for (i = 0; i < n; i++)
894                 if (a[i][0] == low && a[i][1] == high)
895                         return i;
896
897         return -1;
898 }
899
900 SR_PRIV int std_double_tuple_idx(GVariant *data, const double a[][2], unsigned int n)
901 {
902         unsigned int i;
903         double low, high;
904
905         g_variant_get(data, "(dd)", &low, &high);
906
907         for (i = 0; i < n; i++)
908                 if ((fabs(a[i][0] - low) < 0.1) && ((fabs(a[i][1] - high) < 0.1)))
909                         return i;
910
911         return -1;
912 }
913
914 SR_PRIV int std_double_tuple_idx_d0(const double d, const double a[][2], unsigned int n)
915 {
916         unsigned int i;
917
918         for (i = 0; i < n; i++)
919                 if (d == a[i][0])
920                         return i;
921
922         return -1;
923 }
924
925 SR_PRIV int std_cg_idx(const struct sr_channel_group *cg, struct sr_channel_group *a[], unsigned int n)
926 {
927         unsigned int i;
928
929         for (i = 0; i < n; i++)
930                 if (cg == a[i])
931                         return i;
932
933         return -1;
934 }
935
936 SR_PRIV int std_dummy_set_params(struct sr_serial_dev_inst *serial,
937         int baudrate, int bits, int parity, int stopbits,
938         int flowcontrol, int rts, int dtr)
939 {
940         (void)serial;
941         (void)baudrate;
942         (void)bits;
943         (void)parity;
944         (void)stopbits;
945         (void)flowcontrol;
946         (void)rts;
947         (void)dtr;
948
949         return SR_OK;
950 }
951