]> sigrok.org Git - libsigrok.git/blobdiff - src/std.c
drivers: Factor out std_gvar_tuple_{array,rational}().
[libsigrok.git] / src / std.c
index 915a245594e82449c937a845fbd767a33cfe827e..c6ff4ccef96cc07d758b13f4936db374eb2631f2 100644 (file)
--- 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,84 @@ 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);
+}