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