X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fstd.c;h=119b301ee0d9083312d3eb043de901bd5f5aeb54;hb=f272d7ddc0ac67f07ae3e2ac13e0d8f386232d41;hp=915a245594e82449c937a845fbd767a33cfe827e;hpb=6e43c3d5318a8ff320bf6539a9efe7f0b8497e2f;p=libsigrok.git diff --git a/src/std.c b/src/std.c index 915a2455..119b301e 100644 --- a/src/std.c +++ b/src/std.c @@ -333,16 +333,18 @@ SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi) * This function can be used to implement the dev_clear() driver API * callback. dev_close() is called before every sr_dev_inst is cleared. * - * The only limitation is driver-specific device contexts (sdi->priv). + * The only limitation is driver-specific device contexts (sdi->priv / devc). * These are freed, but any dynamic allocation within structs stored * there cannot be freed. * * @param[in] driver The driver which will have its instances released. * Must not be NULL. * @param[in] clear_private If not NULL, this points to a function called - * with sdi->priv as argument. The function can then clear + * with sdi->priv (devc) as argument. The function can then clear * any device instance-specific resources kept there. - * It must also clear the struct pointed to by sdi->priv. + * It must NOT clear the struct pointed to by sdi->priv (devc), + * since this function will always free it after clear_private() + * has run. * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid argument. @@ -388,12 +390,13 @@ SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver, if (sdi->inst_type == SR_INST_MODBUS) sr_modbus_free(sdi->conn); } + + /* Clear driver-specific stuff, if any. */ if (clear_private) - /* The helper function is responsible for freeing - * its own sdi->priv! */ clear_private(sdi->priv); - else - g_free(sdi->priv); + + /* Clear sdi->priv (devc). */ + g_free(sdi->priv); sr_dev_inst_free(sdi); } @@ -404,6 +407,11 @@ SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver, return ret; } +SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver) +{ + return std_dev_clear_with_callback(driver, NULL); +} + /** * Standard driver dev_list() callback API helper. * @@ -489,3 +497,170 @@ SR_PRIV GSList *std_scan_complete(struct sr_dev_driver *di, GSList *devices) return devices; } + +SR_PRIV int 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) +{ + switch (key) { + case SR_CONF_SCAN_OPTIONS: + /* Always return scanopts, regardless of sdi or cg. */ + if (!scanopts) + return SR_ERR_ARG; + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + scanopts, scansize, sizeof(uint32_t)); + break; + case SR_CONF_DEVICE_OPTIONS: + if (!sdi) { + /* sdi == NULL: return drvopts. */ + if (!drvopts) + return SR_ERR_ARG; + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + drvopts, drvsize, sizeof(uint32_t)); + } else if (sdi && !cg) { + /* sdi != NULL, cg == NULL: return devopts. */ + if (!devopts) + return SR_ERR_ARG; + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + devopts, devsize, sizeof(uint32_t)); + } else { + /* + * Note: sdi != NULL, cg != NULL is not handled by + * this function since it's very driver-specific. + */ + sr_err("%s: %s: sdi/cg != NULL: not handling.", + sdi->driver->name, __func__); + return SR_ERR_ARG; + } + break; + default: + return SR_ERR_NA; + } + + 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_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)); +}