]> sigrok.org Git - libsigrok.git/blobdiff - src/device.c
ols: drop wrong usage of macro
[libsigrok.git] / src / device.c
index 1394fb3be34b6aa874dab6e15e111a5d01d58a66..34d80a9dadf45771b3751c1ba1a5917aba034900 100644 (file)
@@ -18,8 +18,9 @@
  */
 
 #include <config.h>
-#include <stdio.h>
 #include <glib.h>
+#include <stdio.h>
+#include <string.h>
 #include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
 
@@ -73,6 +74,30 @@ SR_PRIV struct sr_channel *sr_channel_new(struct sr_dev_inst *sdi,
        return ch;
 }
 
+/**
+ * Release a previously allocated struct sr_channel.
+ *
+ * @param[in] ch Pointer to struct sr_channel.
+ *
+ * @private
+ */
+SR_PRIV void sr_channel_free(struct sr_channel *ch)
+{
+       if (!ch)
+               return;
+       g_free(ch->name);
+       g_free(ch->priv);
+       g_free(ch);
+}
+
+/**
+ * Wrapper around @ref sr_channel_free(), suitable for glib iterators.
+ */
+SR_PRIV void sr_channel_free_cb(void *p)
+{
+       sr_channel_free(p);
+}
+
 /**
  * Set the name of the specified channel.
  *
@@ -135,10 +160,18 @@ SR_API int sr_dev_channel_enable(struct sr_channel *channel, gboolean state)
        return SR_OK;
 }
 
-/* Returns the next enabled channel, wrapping around if necessary. */
-/** @private */
+/**
+ * Returns the next enabled channel, wrapping around if necessary.
+ *
+ * @param[in] sdi The device instance the channel is connected to.
+ *                Must not be NULL.
+ * @param[in] cur_channel The current channel.
+ *
+ * @return A pointer to the next enabled channel of this device.
+ *
+ * @private
+ */
 SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi,
-
                struct sr_channel *cur_channel)
 {
        struct sr_channel *next_channel;
@@ -156,6 +189,69 @@ SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi
        return next_channel;
 }
 
+/**
+ * Compare two channels, return whether they differ.
+ *
+ * The channels' names and types are checked. The enabled state is not
+ * considered a condition for difference. The test is motivated by the
+ * desire to detect changes in the configuration of acquisition setups
+ * between re-reads of an input file.
+ *
+ * @param[in] ch1 First channel.
+ * @param[in] ch2 Second channel.
+ *
+ * @return #TRUE upon differences or unexpected input, #FALSE otherwise.
+ *
+ * @internal
+ */
+SR_PRIV gboolean sr_channels_differ(struct sr_channel *ch1, struct sr_channel *ch2)
+{
+       if (!ch1 || !ch2)
+               return TRUE;
+
+       if (ch1->type != ch2->type)
+               return TRUE;
+       if (strcmp(ch1->name, ch2->name))
+               return TRUE;
+
+       return FALSE;
+}
+
+/**
+ * Compare two channel lists, return whether they differ.
+ *
+ * Listing the same set of channels but in a different order is considered
+ * a difference in the lists.
+ *
+ * @param[in] l1 First channel list.
+ * @param[in] l2 Second channel list.
+ *
+ * @return #TRUE upon differences or unexpected input, #FALSE otherwise.
+ *
+ * @internal
+ */
+SR_PRIV gboolean sr_channel_lists_differ(GSList *l1, GSList *l2)
+{
+       struct sr_channel *ch1, *ch2;
+
+       while (l1 && l2) {
+               ch1 = l1->data;
+               ch2 = l2->data;
+               l1 = l1->next;
+               l2 = l2->next;
+               if (!ch1 || !ch2)
+                       return TRUE;
+               if (sr_channels_differ(ch1, ch2))
+                       return TRUE;
+               if (ch1->index != ch2->index)
+                       return TRUE;
+       }
+       if (l1 || l2)
+               return TRUE;
+
+       return FALSE;
+}
+
 /**
  * Determine whether the specified device instance has the specified
  * capability.
@@ -356,9 +452,7 @@ SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi)
 
        for (l = sdi->channels; l; l = l->next) {
                ch = l->data;
-               g_free(ch->name);
-               g_free(ch->priv);
-               g_free(ch);
+               sr_channel_free(ch);
        }
        g_slist_free(sdi->channels);
 
@@ -529,8 +623,6 @@ SR_API GSList *sr_dev_list(const struct sr_dev_driver *driver)
  */
 SR_API int sr_dev_clear(const struct sr_dev_driver *driver)
 {
-       int ret;
-
        if (!driver) {
                sr_err("Invalid driver.");
                return SR_ERR_ARG;
@@ -548,12 +640,7 @@ SR_API int sr_dev_clear(const struct sr_dev_driver *driver)
 
        /* No log message here, too verbose and not very useful. */
 
-       if (driver->dev_clear)
-               ret = driver->dev_clear(driver);
-       else
-               ret = std_dev_clear(driver, NULL);
-
-       return ret;
+       return driver->dev_clear(driver);
 }
 
 /**
@@ -617,8 +704,6 @@ SR_API int sr_dev_open(struct sr_dev_inst *sdi)
  */
 SR_API int sr_dev_close(struct sr_dev_inst *sdi)
 {
-       int ret;
-
        if (!sdi || !sdi->driver || !sdi->driver->dev_close)
                return SR_ERR_ARG;
 
@@ -632,9 +717,7 @@ SR_API int sr_dev_close(struct sr_dev_inst *sdi)
 
        sr_dbg("%s: Closing device instance.", sdi->driver->name);
 
-       ret = sdi->driver->dev_close(sdi);
-
-       return ret;
+       return sdi->driver->dev_close(sdi);
 }
 
 /**
@@ -764,7 +847,9 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi)
                        if (b != usb->bus || a != usb->address)
                                continue;
 
-                       usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
+                       if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
+                               continue;
+
                        ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(connection_id);
                        break;
                }