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  */
std_init(struct sr_dev_driver * di,struct sr_context * sr_ctx)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  */
std_cleanup(const struct sr_dev_driver * di)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  */
std_dummy_dev_open(struct sr_dev_inst * sdi)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  */
std_dummy_dev_close(struct sr_dev_inst * sdi)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  */
std_dummy_dev_acquisition_start(const struct sr_dev_inst * sdi)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  */
std_dummy_dev_acquisition_stop(struct sr_dev_inst * sdi)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  */
std_session_send_df_header(const struct sr_dev_inst * sdi)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  */
std_session_send_df_end(const struct sr_dev_inst * sdi)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  */
std_session_send_frame_begin(const struct sr_dev_inst * sdi)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  */
std_session_send_frame_end(const struct sr_dev_inst * sdi)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  */
std_serial_dev_open(struct sr_dev_inst * sdi)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  */
std_serial_dev_close(struct sr_dev_inst * sdi)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  */
std_serial_dev_acquisition_stop(struct sr_dev_inst * sdi)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  */
std_dev_clear_with_callback(const struct sr_dev_driver * driver,std_dev_clear_callback clear_private)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 
std_dev_clear(const struct sr_dev_driver * driver)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  */
std_dev_list(const struct sr_dev_driver * di)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  */
std_scan_complete(struct sr_dev_driver * di,GSList * devices)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 
std_opts_config_list(uint32_t key,GVariant ** data,const struct sr_dev_inst * sdi,const struct sr_channel_group * cg,const uint32_t scanopts[],size_t scansize,const uint32_t drvopts[],size_t drvsize,const uint32_t devopts[],size_t devsize)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 
std_gvar_tuple_array(const uint64_t a[][2],unsigned int n)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 
std_gvar_tuple_rational(const struct sr_rational * r,unsigned int n)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 
samplerate_helper(const uint64_t samplerates[],unsigned int n,const char * str)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 
std_gvar_samplerates(const uint64_t samplerates[],unsigned int n)667 SR_PRIV GVariant *std_gvar_samplerates(const uint64_t samplerates[], unsigned int n)
668 {
669 	return samplerate_helper(samplerates, n, "samplerates");
670 }
671 
std_gvar_samplerates_steps(const uint64_t samplerates[],unsigned int n)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 
std_gvar_min_max_step(double min,double max,double step)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 
std_gvar_min_max_step_array(const double a[3])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 
std_gvar_min_max_step_thresholds(const double min,const double max,const double step)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 
std_gvar_tuple_u64(uint64_t low,uint64_t high)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 
std_gvar_tuple_double(double low,double high)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 
std_gvar_array_i32(const int32_t a[],unsigned int n)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 
std_gvar_array_u32(const uint32_t a[],unsigned int n)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 
std_gvar_array_u64(const uint64_t a[],unsigned int n)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 
std_gvar_array_str(const char * a[],unsigned int n)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 
std_gvar_thresholds(const double a[][2],unsigned int n)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). */
find_in_array(GVariant * data,const GVariantType * type,const void * arr,unsigned int n)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 
std_str_idx(GVariant * data,const char * a[],unsigned int n)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 
std_u64_idx(GVariant * data,const uint64_t a[],unsigned int n)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 
std_u8_idx(GVariant * data,const uint8_t a[],unsigned int n)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 
std_str_idx_s(const char * s,const char * a[],unsigned int n)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 
std_u8_idx_s(uint8_t b,const uint8_t a[],unsigned int n)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 
std_u64_tuple_idx(GVariant * data,const uint64_t a[][2],unsigned int n)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 
std_double_tuple_idx(GVariant * data,const double a[][2],unsigned int n)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 
std_double_tuple_idx_d0(const double d,const double a[][2],unsigned int n)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 
std_cg_idx(const struct sr_channel_group * cg,struct sr_channel_group * a[],unsigned int n)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 
std_dummy_set_params(struct sr_serial_dev_inst * serial,int baudrate,int bits,int parity,int stopbits,int flowcontrol,int rts,int dtr)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 
952