X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fstd.c;h=5748ba02eb9c62b869c693f60eac2d5942aa6ed2;hb=54d471f4980f1b975188b5e8bdf5aa90acd3cece;hp=f68cc12bd8954c29c684043fe368ef514427dca5;hpb=12852b0337fd802ac0f9c51a39a173636685ef18;p=libsigrok.git diff --git a/src/std.c b/src/std.c index f68cc12b..5748ba02 100644 --- a/src/std.c +++ b/src/std.c @@ -93,6 +93,62 @@ SR_PRIV int std_cleanup(const struct sr_dev_driver *di) return ret; } +/** + * Dummmy driver dev_open() callback API helper. + * + * @param[in] sdi The device instance to use. May be NULL (unused). + * + * @retval SR_OK Success. + */ +SR_PRIV int std_dummy_dev_open(struct sr_dev_inst *sdi) +{ + (void)sdi; + + return SR_OK; +} + +/** + * Dummmy driver dev_close() callback API helper. + * + * @param[in] sdi The device instance to use. May be NULL (unused). + * + * @retval SR_OK Success. + */ +SR_PRIV int std_dummy_dev_close(struct sr_dev_inst *sdi) +{ + (void)sdi; + + return SR_OK; +} + +/** + * Dummmy driver dev_acquisition_start() callback API helper. + * + * @param[in] sdi The device instance to use. May be NULL (unused). + * + * @retval SR_OK Success. + */ +SR_PRIV int std_dummy_dev_acquisition_start(const struct sr_dev_inst *sdi) +{ + (void)sdi; + + return SR_OK; +} + +/** + * Dummmy driver dev_acquisition_stop() callback API helper. + * + * @param[in] sdi The device instance to use. May be NULL (unused). + * + * @retval SR_OK Success. + */ +SR_PRIV int std_dummy_dev_acquisition_stop(struct sr_dev_inst *sdi) +{ + (void)sdi; + + return SR_OK; +} + /** * Standard API helper for sending an SR_DF_HEADER packet. * @@ -277,23 +333,25 @@ 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. * @retval SR_ERR_BUG Implementation bug. * @retval other Other error. */ -SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver, +SR_PRIV int std_dev_clear_with_callback(const struct sr_dev_driver *driver, std_dev_clear_callback clear_private) { struct drv_context *drvc; @@ -332,12 +390,13 @@ SR_PRIV int std_dev_clear(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); } @@ -348,6 +407,11 @@ SR_PRIV int std_dev_clear(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. * @@ -433,3 +497,133 @@ 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); +}