X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=src%2Fdevice.c;h=5a144d97ebccf3b160117b64f17c3be604e9367f;hp=34d80a9dadf45771b3751c1ba1a5917aba034900;hb=HEAD;hpb=712f981dffbcb19291e86f41d565bf4627f3a5f4 diff --git a/src/device.c b/src/device.c index 34d80a9d..5c681378 100644 --- a/src/device.c +++ b/src/device.c @@ -23,6 +23,7 @@ #include #include #include "libsigrok-internal.h" +#include "scpi.h" /** @cond PRIVATE */ #define LOG_PREFIX "device" @@ -61,12 +62,12 @@ SR_PRIV struct sr_channel *sr_channel_new(struct sr_dev_inst *sdi, { struct sr_channel *ch; - ch = g_malloc0(sizeof(struct sr_channel)); + ch = g_malloc0(sizeof(*ch)); ch->sdi = sdi; ch->index = index; ch->type = type; ch->enabled = enabled; - if (name) + if (name && *name) ch->name = g_strdup(name); sdi->channels = g_slist_append(sdi->channels, ch); @@ -91,7 +92,9 @@ SR_PRIV void sr_channel_free(struct sr_channel *ch) } /** - * Wrapper around @ref sr_channel_free(), suitable for glib iterators. + * Wrapper around sr_channel_free(), suitable for glib iterators. + * + * @private */ SR_PRIV void sr_channel_free_cb(void *p) { @@ -117,6 +120,8 @@ SR_API int sr_dev_channel_name_set(struct sr_channel *channel, { if (!channel) return SR_ERR_ARG; + if (!name || !*name) + return SR_ERR_ARG; g_free(channel->name); channel->name = g_strdup(name); @@ -200,9 +205,9 @@ SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi * @param[in] ch1 First channel. * @param[in] ch2 Second channel. * - * @return #TRUE upon differences or unexpected input, #FALSE otherwise. + * @return TRUE upon differences or unexpected input, FALSE otherwise. * - * @internal + * @private */ SR_PRIV gboolean sr_channels_differ(struct sr_channel *ch1, struct sr_channel *ch2) { @@ -226,9 +231,9 @@ SR_PRIV gboolean sr_channels_differ(struct sr_channel *ch1, struct sr_channel *c * @param[in] l1 First channel list. * @param[in] l2 Second channel list. * - * @return #TRUE upon differences or unexpected input, #FALSE otherwise. + * @return TRUE upon differences or unexpected input, FALSE otherwise. * - * @internal + * @private */ SR_PRIV gboolean sr_channel_lists_differ(GSList *l1, GSList *l2) { @@ -252,6 +257,62 @@ SR_PRIV gboolean sr_channel_lists_differ(GSList *l1, GSList *l2) return FALSE; } +/** + * Allocate and initialize a new channel group, and add it to sdi. + * + * @param[in] sdi The device instance the channel group is connected to. + * Optional, can be NULL. + * @param[in] name @copydoc sr_channel_group::name + * @param[in] priv @copydoc sr_channel_group::priv + * + * @return A pointer to a new struct sr_channel_group, NULL upon error. + * + * @private + */ +SR_PRIV struct sr_channel_group *sr_channel_group_new(struct sr_dev_inst *sdi, + const char *name, void *priv) +{ + struct sr_channel_group *cg; + + cg = g_malloc0(sizeof(*cg)); + if (name && *name) + cg->name = g_strdup(name); + cg->priv = priv; + + if (sdi) + sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); + + return cg; +} + +/** + * Release a previously allocated struct sr_channel_group. + * + * @param[in] cg Pointer to struct sr_channel_group. + * + * @private + */ +SR_PRIV void sr_channel_group_free(struct sr_channel_group *cg) +{ + if (!cg) + return; + + g_free(cg->name); + g_slist_free(cg->channels); + g_free(cg->priv); + g_free(cg); +} + +/** + * Wrapper around sr_channel_group_free(), suitable for glib iterators. + * + * @private + */ +SR_PRIV void sr_channel_group_free_cb(void *cg) +{ + return sr_channel_group_free(cg); +} + /** * Determine whether the specified device instance has the specified * capability. @@ -404,7 +465,7 @@ SR_API struct sr_dev_inst *sr_dev_inst_user_new(const char *vendor, { struct sr_dev_inst *sdi; - sdi = g_malloc0(sizeof(struct sr_dev_inst)); + sdi = g_malloc0(sizeof(*sdi)); sdi->vendor = g_strdup(vendor); sdi->model = g_strdup(model); @@ -417,6 +478,7 @@ SR_API struct sr_dev_inst *sr_dev_inst_user_new(const char *vendor, /** * Add a new channel to the specified device instance. * + * @param[in] sdi Device instance to use. Must not be NULL. * @param[in] index @copydoc sr_channel::index * @param[in] type @copydoc sr_channel::type * @param[in] name @copydoc sr_channel::name @@ -429,7 +491,8 @@ SR_API int sr_dev_inst_channel_add(struct sr_dev_inst *sdi, int index, int type, if (!sdi || sdi->inst_type != SR_INST_USER || index < 0) return SR_ERR_ARG; - sr_channel_new(sdi, index, type, TRUE, name); + if (!sr_channel_new(sdi, index, type, TRUE, name)) + return SR_ERR_DATA; return SR_OK; } @@ -444,7 +507,6 @@ SR_API int sr_dev_inst_channel_add(struct sr_dev_inst *sdi, int index, int type, SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) { struct sr_channel *ch; - struct sr_channel_group *cg; GSList *l; if (!sdi) @@ -455,15 +517,7 @@ SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) sr_channel_free(ch); } g_slist_free(sdi->channels); - - for (l = sdi->channel_groups; l; l = l->next) { - cg = l->data; - g_free(cg->name); - g_slist_free(cg->channels); - g_free(cg->priv); - g_free(cg); - } - g_slist_free(sdi->channel_groups); + g_slist_free_full(sdi->channel_groups, sr_channel_group_free_cb); if (sdi->session) sr_session_dev_remove(sdi->session, sdi); @@ -494,7 +548,7 @@ SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus, { struct sr_usb_dev_inst *udi; - udi = g_malloc0(sizeof(struct sr_usb_dev_inst)); + udi = g_malloc0(sizeof(*udi)); udi->bus = bus; udi->address = address; udi->devhdl = hdl; @@ -515,9 +569,18 @@ SR_PRIV void sr_usb_dev_inst_free(struct sr_usb_dev_inst *usb) g_free(usb); } +/** + * Wrapper for g_slist_free_full() convenience. + * + * @private + */ +SR_PRIV void sr_usb_dev_inst_free_cb(gpointer p) +{ + sr_usb_dev_inst_free(p); +} #endif -#ifdef HAVE_LIBSERIALPORT +#ifdef HAVE_SERIAL_COMM /** * Allocate and init a struct for a serial device instance. @@ -543,7 +606,7 @@ SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port, { struct sr_serial_dev_inst *serial; - serial = g_malloc0(sizeof(struct sr_serial_dev_inst)); + serial = g_malloc0(sizeof(*serial)); serial->port = g_strdup(port); if (serialcomm) serial->serialcomm = g_strdup(serialcomm); @@ -575,7 +638,7 @@ SR_PRIV struct sr_usbtmc_dev_inst *sr_usbtmc_dev_inst_new(const char *device) { struct sr_usbtmc_dev_inst *usbtmc; - usbtmc = g_malloc0(sizeof(struct sr_usbtmc_dev_inst)); + usbtmc = g_malloc0(sizeof(*usbtmc)); usbtmc->device = g_strdup(device); usbtmc->fd = -1; @@ -808,19 +871,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_SERIAL_COMM + 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; - +#ifdef HAVE_SERIAL_COMM 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); @@ -829,7 +897,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; @@ -847,10 +915,10 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi) if (b != usb->bus || a != usb->address) continue; - if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0) + 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(connection_id); + ((struct sr_dev_inst *)sdi)->connection_id = g_strdup(conn_id_usb); break; } @@ -858,6 +926,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; }