X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fdevice.c;h=e7be567d20ad705ffdd3da315198e37494d2684b;hb=f083ae63c7355b9b1d99775785b99b6fa91cd48a;hp=6fcad410f2bc3802f979f7bb2f9687b755861940;hpb=56c8dd821e7d8ab3602e5fd001f56d91d7b42df3;p=libsigrok.git diff --git a/src/device.c b/src/device.c index 6fcad410..e7be567d 100644 --- a/src/device.c +++ b/src/device.c @@ -18,10 +18,12 @@ */ #include -#include #include +#include +#include #include #include "libsigrok-internal.h" +#include "scpi.h" /** @cond PRIVATE */ #define LOG_PREFIX "device" @@ -73,6 +75,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 +161,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 +190,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 +453,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); @@ -714,19 +809,24 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi) #ifdef HAVE_LIBUSB_1_0 struct drv_context *drvc; int cnt, i, a, b; - char connection_id[64]; + char conn_id_usb[64]; struct sr_usb_dev_inst *usb; struct libusb_device **devlist; #endif +#ifdef HAVE_LIBSERIALPORT + struct sr_serial_dev_inst *serial; +#endif + + struct sr_scpi_dev_inst *scpi; + char *conn_id_scpi; + if (!sdi) return NULL; #ifdef HAVE_LIBSERIALPORT - struct sr_serial_dev_inst *serial; - if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_SERIAL)) { - /* connection_id isn't populated, let's do that here. */ + /* connection_id isn't populated, let's do that for serial devices. */ serial = sdi->conn; ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(serial->port); @@ -735,7 +835,7 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi) #ifdef HAVE_LIBUSB_1_0 if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_USB)) { - /* connection_id isn't populated, let's do that here. */ + /* connection_id isn't populated, let's do that for USB devices. */ drvc = sdi->driver->context; usb = sdi->conn; @@ -753,8 +853,10 @@ 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)); - ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(connection_id); + if (usb_get_port_path(devlist[i], conn_id_usb, sizeof(conn_id_usb)) < 0) + continue; + + ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(conn_id_usb); break; } @@ -762,6 +864,15 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi) } #endif + if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_SCPI)) { + /* connection_id isn't populated, let's do that for SCPI devices. */ + + scpi = sdi->conn; + sr_scpi_connection_id(scpi, &conn_id_scpi); + ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(conn_id_scpi); + g_free(conn_id_scpi); + } + return sdi->connection_id; }