* @internal
*/
+/* Needed for gettimeofday(), at least on FreeBSD. */
+#define _XOPEN_SOURCE 700
+
#include <config.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
#include <glib.h>
#include <libsigrok/libsigrok.h>
#include "libsigrok-internal.h"
return SR_OK;
}
+/**
+ * Standard API helper for sending an SR_DF_FRAME_BEGIN packet.
+ *
+ * This function can be used to simplify most drivers'
+ * frame handling.
+ *
+ * @param[in] sdi The device instance to use. Must not be NULL.
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid argument.
+ * @retval other Other error.
+ */
+SR_PRIV int std_session_send_frame_begin(const struct sr_dev_inst *sdi)
+{
+ const char *prefix;
+ int ret;
+ struct sr_datafeed_packet packet;
+
+ if (!sdi) {
+ sr_err("%s: Invalid argument.", __func__);
+ return SR_ERR_ARG;
+ }
+
+ prefix = (sdi->driver) ? sdi->driver->name : "unknown";
+
+ sr_dbg("%s: Sending SR_DF_FRAME_BEGIN packet.", prefix);
+
+ packet.type = SR_DF_FRAME_BEGIN;
+ packet.payload = NULL;
+
+ if ((ret = sr_session_send(sdi, &packet)) < 0) {
+ sr_err("%s: Failed to send SR_DF_FRAME_BEGIN packet: %d.", prefix, ret);
+ return ret;
+ }
+
+ return SR_OK;
+}
+
+/**
+ * Standard API helper for sending an SR_DF_FRAME_END packet.
+ *
+ * This function can be used to simplify most drivers'
+ * frame handling.
+ *
+ * @param[in] sdi The device instance to use. Must not be NULL.
+ *
+ * @retval SR_OK Success.
+ * @retval SR_ERR_ARG Invalid argument.
+ * @retval other Other error.
+ */
+SR_PRIV int std_session_send_frame_end(const struct sr_dev_inst *sdi)
+{
+ const char *prefix;
+ int ret;
+ struct sr_datafeed_packet packet;
+
+ if (!sdi) {
+ sr_err("%s: Invalid argument.", __func__);
+ return SR_ERR_ARG;
+ }
+
+ prefix = (sdi->driver) ? sdi->driver->name : "unknown";
+
+ sr_dbg("%s: Sending SR_DF_FRAME_END packet.", prefix);
+
+ packet.type = SR_DF_FRAME_END;
+ packet.payload = NULL;
+
+ if ((ret = sr_session_send(sdi, &packet)) < 0) {
+ sr_err("%s: Failed to send SR_DF_FRAME_END packet: %d.", prefix, ret);
+ return ret;
+ }
+
+ return SR_OK;
+}
+
#ifdef HAVE_LIBSERIALPORT
/**
return SR_OK;
}
+
+SR_PRIV GVariant *std_gvar_tuple_array(const uint64_t a[][2], unsigned int n)
+{
+ unsigned int i;
+ GVariant *rational[2];
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ for (i = 0; i < n; i++) {
+ rational[0] = g_variant_new_uint64(a[i][0]);
+ rational[1] = g_variant_new_uint64(a[i][1]);
+
+ /* FIXME: Valgrind reports a memory leak here. */
+ g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
+ }
+
+ return g_variant_builder_end(&gvb);
+}
+
+SR_PRIV GVariant *std_gvar_tuple_rational(const struct sr_rational *r, unsigned int n)
+{
+ unsigned int i;
+ GVariant *rational[2];
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ for (i = 0; i < n; i++) {
+ rational[0] = g_variant_new_uint64(r[i].p);
+ rational[1] = g_variant_new_uint64(r[i].q);
+
+ /* FIXME: Valgrind reports a memory leak here. */
+ g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
+ }
+
+ return g_variant_builder_end(&gvb);
+}
+
+static GVariant *samplerate_helper(const uint64_t samplerates[], unsigned int n, const char *str)
+{
+ GVariant *gvar;
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
+ gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
+ n, sizeof(uint64_t));
+ g_variant_builder_add(&gvb, "{sv}", str, gvar);
+
+ return g_variant_builder_end(&gvb);
+}
+
+SR_PRIV GVariant *std_gvar_samplerates(const uint64_t samplerates[], unsigned int n)
+{
+ return samplerate_helper(samplerates, n, "samplerates");
+}
+
+SR_PRIV GVariant *std_gvar_samplerates_steps(const uint64_t samplerates[], unsigned int n)
+{
+ return samplerate_helper(samplerates, n, "samplerate-steps");
+}
+
+SR_PRIV GVariant *std_gvar_min_max_step(double min, double max, double step)
+{
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ g_variant_builder_add_value(&gvb, g_variant_new_double(min));
+ g_variant_builder_add_value(&gvb, g_variant_new_double(max));
+ g_variant_builder_add_value(&gvb, g_variant_new_double(step));
+
+ return g_variant_builder_end(&gvb);
+}
+
+SR_PRIV GVariant *std_gvar_min_max_step_array(const double a[3])
+{
+ unsigned int i;
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ for (i = 0; i < 3; i++)
+ g_variant_builder_add_value(&gvb, g_variant_new_double(a[i]));
+
+ return g_variant_builder_end(&gvb);
+}
+
+SR_PRIV GVariant *std_gvar_min_max_step_thresholds(const double min, const double max, const double step)
+{
+ double d;
+ GVariant *gvar, *range[2];
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ for (d = min; d <= max; d += step) {
+ range[0] = g_variant_new_double(d);
+ range[1] = g_variant_new_double(d);
+
+ gvar = g_variant_new_tuple(range, 2);
+ g_variant_builder_add_value(&gvb, gvar);
+ }
+
+ return g_variant_builder_end(&gvb);
+}
+
+SR_PRIV GVariant *std_gvar_tuple_u64(uint64_t low, uint64_t high)
+{
+ GVariant *range[2];
+
+ range[0] = g_variant_new_uint64(low);
+ range[1] = g_variant_new_uint64(high);
+
+ return g_variant_new_tuple(range, 2);
+}
+
+SR_PRIV GVariant *std_gvar_tuple_double(double low, double high)
+{
+ GVariant *range[2];
+
+ range[0] = g_variant_new_double(low);
+ range[1] = g_variant_new_double(high);
+
+ return g_variant_new_tuple(range, 2);
+}
+
+SR_PRIV GVariant *std_gvar_array_i32(const int32_t *a, unsigned int n)
+{
+ return g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
+ a, n, sizeof(int32_t));
+}
+
+SR_PRIV GVariant *std_gvar_array_u32(const uint32_t *a, unsigned int n)
+{
+ return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+ a, n, sizeof(uint32_t));
+}
+
+SR_PRIV GVariant *std_gvar_array_u64(const uint64_t *a, unsigned int n)
+{
+ return g_variant_new_fixed_array(G_VARIANT_TYPE_UINT64,
+ a, n, sizeof(uint64_t));
+}
+
+SR_PRIV GVariant *std_gvar_array_str(const char *a[], unsigned int n)
+{
+ GVariant *gvar;
+ GVariantBuilder *builder;
+ unsigned int i;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE ("as"));
+
+ for (i = 0; i < n; i++)
+ g_variant_builder_add(builder, "s", a[i]);
+
+ gvar = g_variant_new("as", builder);
+ g_variant_builder_unref(builder);
+
+ return gvar;
+}
+
+SR_PRIV GVariant *std_gvar_thresholds(const double a[][2], unsigned int n)
+{
+ unsigned int i;
+ GVariant *gvar, *range[2];
+ GVariantBuilder gvb;
+
+ g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
+
+ for (i = 0; i < n; i++) {
+ range[0] = g_variant_new_double(a[i][0]);
+ range[1] = g_variant_new_double(a[i][1]);
+ gvar = g_variant_new_tuple(range, 2);
+ g_variant_builder_add_value(&gvb, gvar);
+ }
+
+ return g_variant_builder_end(&gvb);
+}
+
+/* Return the index of 'data' in the array 'arr' (or -1). */
+static int find_in_array(GVariant *data, const GVariantType *type,
+ const void *arr, unsigned int n)
+{
+ const char * const *sarr;
+ const char *s;
+ const uint64_t *u64arr;
+ const uint8_t *u8arr;
+ uint64_t u64;
+ uint8_t u8;
+ unsigned int i;
+
+ if (!g_variant_is_of_type(data, type))
+ return -1;
+
+ switch (g_variant_classify(data)) {
+ case G_VARIANT_CLASS_STRING:
+ s = g_variant_get_string(data, NULL);
+ sarr = arr;
+
+ for (i = 0; i < n; i++)
+ if (!strcmp(s, sarr[i]))
+ return i;
+ break;
+ case G_VARIANT_CLASS_UINT64:
+ u64 = g_variant_get_uint64(data);
+ u64arr = arr;
+
+ for (i = 0; i < n; i++)
+ if (u64 == u64arr[i])
+ return i;
+ break;
+ case G_VARIANT_CLASS_BYTE:
+ u8 = g_variant_get_byte(data);
+ u8arr = arr;
+
+ for (i = 0; i < n; i++)
+ if (u8 == u8arr[i])
+ return i;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+SR_PRIV int std_str_idx(GVariant *data, const char *a[], unsigned int n)
+{
+ return find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
+}
+
+SR_PRIV int std_u64_idx(GVariant *data, const uint64_t a[], unsigned int n)
+{
+ return find_in_array(data, G_VARIANT_TYPE_UINT64, a, n);
+}
+
+SR_PRIV int std_u8_idx(GVariant *data, const uint8_t a[], unsigned int n)
+{
+ return find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
+}
+
+SR_PRIV int std_str_idx_s(const char *s, const char *a[], unsigned int n)
+{
+ int idx;
+ GVariant *data;
+
+ data = g_variant_new_string(s);
+ idx = find_in_array(data, G_VARIANT_TYPE_STRING, a, n);
+ g_variant_unref(data);
+
+ return idx;
+}
+
+SR_PRIV int std_u8_idx_s(uint8_t b, const uint8_t a[], unsigned int n)
+{
+ int idx;
+ GVariant *data;
+
+ data = g_variant_new_byte(b);
+ idx = find_in_array(data, G_VARIANT_TYPE_BYTE, a, n);
+ g_variant_unref(data);
+
+ return idx;
+}
+
+SR_PRIV int std_u64_tuple_idx(GVariant *data, const uint64_t a[][2], unsigned int n)
+{
+ unsigned int i;
+ uint64_t low, high;
+
+ g_variant_get(data, "(tt)", &low, &high);
+
+ for (i = 0; i < n; i++)
+ if (a[i][0] == low && a[i][1] == high)
+ return i;
+
+ return -1;
+}
+
+SR_PRIV int std_double_tuple_idx(GVariant *data, const double a[][2], unsigned int n)
+{
+ unsigned int i;
+ double low, high;
+
+ g_variant_get(data, "(dd)", &low, &high);
+
+ for (i = 0; i < n; i++)
+ if ((fabs(a[i][0] - low) < 0.1) && ((fabs(a[i][1] - high) < 0.1)))
+ return i;
+
+ return -1;
+}
+
+SR_PRIV int std_double_tuple_idx_d0(const double d, const double a[][2], unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ if (d == a[i][0])
+ return i;
+
+ return -1;
+}
+
+SR_PRIV int std_cg_idx(const struct sr_channel_group *cg, struct sr_channel_group *a[], unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ if (cg == a[i])
+ return i;
+
+ return -1;
+}