#include "libsigrok-internal.h"
/* SR_CONF_CONN takes one of these: */
-#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
+#define CONN_USB_VIDPID "^([0-9a-fA-F]{4})\\.([0-9a-fA-F]{4})$"
#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
#define LOG_PREFIX "usb"
#endif
/** Custom GLib event source for libusb I/O.
- * @internal
*/
struct usb_source {
GSource base;
pollfd = g_ptr_array_index(usource->pollfds, i);
revents |= pollfd->revents;
}
- if (revents != 0)
- sr_spew("%s: revents 0x%.2X", __func__, revents);
- else
- sr_spew("%s: timed out", __func__);
if (!callback) {
sr_err("Callback not set, cannot dispatch event.");
return G_SOURCE_REMOVE;
}
- keep = (*(sr_receive_data_callback)callback)(-1, revents, user_data);
+ keep = (*SR_RECEIVE_DATA_CALLBACK(callback))(-1, revents, user_data);
if (G_LIKELY(keep) && G_LIKELY(!g_source_is_destroyed(source))) {
if (usource->timeout_us >= 0)
usource = user_data;
+ if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
+ return;
+
pollfd = g_slice_new(GPollFD);
-#ifdef G_OS_WIN32
+#ifdef _WIN32
events = G_IO_IN;
#endif
pollfd->fd = (gintptr)fd;
pollfd->revents = 0;
g_ptr_array_add(usource->pollfds, pollfd);
- g_source_add_poll((GSource *)usource, pollfd);
+ g_source_add_poll(&usource->base, pollfd);
}
/** Callback invoked when a libusb FD should be removed from the poll set.
usource = user_data;
+ if (G_UNLIKELY(g_source_is_destroyed(&usource->base)))
+ return;
+
/* It's likely that the removed poll FD is at the end.
*/
for (i = usource->pollfds->len; G_LIKELY(i > 0); i--) {
pollfd = g_ptr_array_index(usource->pollfds, i - 1);
if ((libusb_os_handle)pollfd->fd == fd) {
- g_source_remove_poll((GSource *)usource, pollfd);
+ g_source_remove_poll(&usource->base, pollfd);
g_ptr_array_remove_index_fast(usource->pollfds, i - 1);
return;
}
if ((mstr = g_match_info_fetch(match, 2)))
pid = strtoul(mstr, NULL, 16);
g_free(mstr);
- sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
- vid, pid);
+ /* Trying to find USB device via VID:PID. */
} else {
g_match_info_unref(match);
g_regex_unref(reg);
if ((mstr = g_match_info_fetch(match, 2)))
addr = strtoul(mstr, NULL, 10);
g_free(mstr);
- sr_dbg("Trying to find USB device with bus.address = "
- "%d.%d.", bus, addr);
+ /* Trying to find USB device via bus.address. */
}
}
g_match_info_unref(match);
return NULL;
}
- if (bus > 64) {
+ if (bus > 255) {
sr_err("Invalid bus specified: %d.", bus);
return NULL;
}
sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
"%d.%d).", des.idVendor, des.idProduct, b, a);
- usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
- libusb_get_device_address(devlist[i]), NULL);
+ usb = sr_usb_dev_inst_new(b, a, NULL);
devices = g_slist_append(devices, usb);
}
libusb_free_device_list(devlist, 1);
- sr_dbg("Found %d device(s).", g_slist_length(devices));
-
+ /* No log message for #devices found (caller will log that). */
+
return devices;
}
if (!source)
return SR_ERR;
- g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
+ g_source_set_callback(source, G_SOURCE_FUNC(cb), cb_data, NULL);
ret = sr_session_source_add_internal(session, ctx->libusb_ctx, source);
g_source_unref(source);
/*
* FreeBSD requires that devices prior to calling libusb_get_port_numbers()
* have been opened with libusb_open().
+ * This apparently also applies to some Mac OS X versions.
*/
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__APPLE__)
struct libusb_device_handle *devh;
if (libusb_open(dev, &devh) != 0)
return SR_ERR;
#endif
n = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__APPLE__)
libusb_close(devh);
#endif
-/* Workaround FreeBSD libusb_get_port_numbers() returning 0. */
-#ifdef __FreeBSD__
+/* Workaround FreeBSD / Mac OS X libusb_get_port_numbers() returning 0. */
+#if defined(__FreeBSD__) || defined(__APPLE__)
if (n == 0) {
port_numbers[0] = libusb_get_device_address(dev);
n = 1;
return SR_OK;
}
+
+/**
+ * Check the USB configuration to determine if this device has a given
+ * manufacturer and product string.
+ *
+ * @return TRUE if the device's configuration profile strings
+ * configuration, FALSE otherwise.
+ */
+SR_PRIV gboolean usb_match_manuf_prod(libusb_device *dev,
+ const char *manufacturer, const char *product)
+{
+ struct libusb_device_descriptor des;
+ struct libusb_device_handle *hdl;
+ gboolean ret;
+ unsigned char strdesc[64];
+
+ hdl = NULL;
+ ret = FALSE;
+ while (!ret) {
+ /* Assume the FW has not been loaded, unless proven wrong. */
+ libusb_get_device_descriptor(dev, &des);
+
+ if (libusb_open(dev, &hdl) != 0)
+ break;
+
+ if (libusb_get_string_descriptor_ascii(hdl,
+ des.iManufacturer, strdesc, sizeof(strdesc)) < 0)
+ break;
+ if (strcmp((const char *)strdesc, manufacturer))
+ break;
+
+ if (libusb_get_string_descriptor_ascii(hdl,
+ des.iProduct, strdesc, sizeof(strdesc)) < 0)
+ break;
+ if (strcmp((const char *)strdesc, product))
+ break;
+
+ ret = TRUE;
+ }
+ if (hdl)
+ libusb_close(hdl);
+
+ return ret;
+}