X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fcommon%2Fusb.c;h=bac420b31c31c758594af37ddf1aca78393f26b4;hb=3520422fc761d50830a45a43cd7d34cca589ad1b;hp=2dabfbee081c2d695df241521d7699725fca3be5;hpb=0c632d36be4b7b34addadf0649fea95173fe0f9a;p=libsigrok.git diff --git a/hardware/common/usb.c b/hardware/common/usb.c index 2dabfbee..bac420b3 100644 --- a/hardware/common/usb.c +++ b/hardware/common/usb.c @@ -1,5 +1,5 @@ /* - * This file is part of the sigrok project. + * This file is part of the libsigrok project. * * Copyright (C) 2012 Uwe Hermann * Copyright (C) 2012 Bert Vermeulen @@ -25,21 +25,37 @@ #include "libsigrok.h" #include "libsigrok-internal.h" -/* SR_HWCAP_CONN takes one of these: */ -#define CONN_USB_VIDPID "^([0-9a-z]{1,4})\\.([0-9a-z]{1,4})$" +/* SR_CONF_CONN takes one of these: */ +#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$" #define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$" -/* Message logging helpers with driver-specific prefix string. */ -#define DRIVER_LOG_DOMAIN "usb: " -#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) -#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args) -#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args) -#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args) -#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) -#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) - -SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) +/* Some USBTMC-specific enums, as defined in the USBTMC standard. */ +#define SUBCLASS_USBTMC 0x03 +#define USBTMC_USB488 0x01 + +/* Message logging helpers with subsystem-specific prefix string. */ +#define LOG_PREFIX "usb: " +#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) +#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) +#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) +#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) +#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args) + +/** + * Find USB devices according to a connection string. + * + * @param usb_ctx libusb context to use while scanning. + * @param conn Connection string specifying the device(s) to match. This + * can be of the form ".
", or ".". + * + * @return A GSList of struct sr_usb_dev_inst, with bus and address fields + * matching the device that matched the connection string. The GSList and + * its contents must be freed by the caller. + */ +SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn) { + struct sr_usb_dev_inst *usb; struct libusb_device **devlist; struct libusb_device_descriptor des; GSList *devices; @@ -51,18 +67,12 @@ SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) vid = pid = bus = addr = 0; reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL); if (g_regex_match(reg, conn, 0, &match)) { - /* Extract VID. */ - if ((mstr = g_match_info_fetch(match, 1))) { + if ((mstr = g_match_info_fetch(match, 1))) vid = strtoul(mstr, NULL, 16); - sr_spew("Extracted VID 0x%04x.", vid); - } g_free(mstr); - /* Extract PID. */ - if ((mstr = g_match_info_fetch(match, 2))) { + if ((mstr = g_match_info_fetch(match, 2))) pid = strtoul(mstr, NULL, 16); - sr_spew("Extracted PID 0x%04x.", pid); - } g_free(mstr); sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.", vid, pid); @@ -71,18 +81,12 @@ SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) g_regex_unref(reg); reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL); if (g_regex_match(reg, conn, 0, &match)) { - /* Extract bus. */ - if ((mstr = g_match_info_fetch(match, 1))) { - bus = strtoul(mstr, NULL, 16); - sr_spew("Extracted bus %d.", bus); - } + if ((mstr = g_match_info_fetch(match, 1))) + bus = strtoul(mstr, NULL, 10); g_free(mstr); - /* Extract address. */ - if ((mstr = g_match_info_fetch(match, 2))) { - addr = strtoul(mstr, NULL, 16); - sr_spew("Extracted address %d.", addr); - } + 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); @@ -92,7 +96,7 @@ SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) g_regex_unref(reg); if (vid + pid + bus + addr == 0) { - sr_err("Neither VID:PID nor bus.address was found."); + sr_err("Neither VID:PID nor bus.address was specified."); return NULL; } @@ -111,29 +115,25 @@ SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) libusb_get_device_list(usb_ctx, &devlist); for (i = 0; devlist[i]; i++) { if ((ret = libusb_get_device_descriptor(devlist[i], &des))) { - sr_err("Failed to get device descriptor: %d.", ret); + sr_err("Failed to get device descriptor: %s.", + libusb_error_name(ret)); continue; } - b = libusb_get_bus_number(devlist[i]); - a = libusb_get_device_address(devlist[i]); - - if (vid + pid && - (des.idVendor != vid || des.idProduct != pid)) { - sr_spew("VID:PID = %04x:%04x (%d.%d) doesn't match.", - des.idVendor, des.idProduct, b, a); + if (vid + pid && (des.idVendor != vid || des.idProduct != pid)) continue; - } - if (bus + addr && (b != bus || a != addr)) { - sr_spew("bus.address = %d.%d does not match.", b, a); + b = libusb_get_bus_number(devlist[i]); + a = libusb_get_device_address(devlist[i]); + if (bus + addr && (b != bus || a != addr)) continue; - } sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = " "%d.%d).", des.idVendor, des.idProduct, b, a); - devices = g_slist_append(devices, devlist[i]); + usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]), + libusb_get_device_address(devlist[i]), NULL); + devices = g_slist_append(devices, usb); } libusb_free_device_list(devlist, 1); @@ -142,13 +142,70 @@ SR_PRIV GSList *sr_usb_connect(libusb_context *usb_ctx, const char *conn) return devices; } +/** + * Find USB devices supporting the USBTMC class + * + * @param usb_ctx libusb context to use while scanning. + * + * @return A GSList of struct sr_usb_dev_inst, with bus and address fields + * indicating devices with USBTMC support. + */ +SR_PRIV GSList *sr_usb_find_usbtmc(libusb_context *usb_ctx) +{ + struct sr_usb_dev_inst *usb; + struct libusb_device **devlist; + struct libusb_device_descriptor des; + struct libusb_config_descriptor *confdes; + const struct libusb_interface_descriptor *intfdes; + GSList *devices; + int confidx, intfidx, ret, i; + + devices = NULL; + libusb_get_device_list(usb_ctx, &devlist); + for (i = 0; devlist[i]; i++) { + if ((ret = libusb_get_device_descriptor(devlist[i], &des))) { + sr_err("Failed to get device descriptor: %s.", + libusb_error_name(ret)); + continue; + } + + for (confidx = 0; confidx < des.bNumConfigurations; confidx++) { + if (libusb_get_config_descriptor(devlist[i], confidx, &confdes) != 0) { + sr_err("Failed to get configuration descriptor."); + break; + } + for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) { + intfdes = confdes->interface[intfidx].altsetting; + if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION + || intfdes->bInterfaceSubClass != SUBCLASS_USBTMC + || intfdes->bInterfaceProtocol != USBTMC_USB488) + continue; + sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, bus.address = " + "%d.%d).", des.idVendor, des.idProduct, + libusb_get_bus_number(devlist[i]), + libusb_get_device_address(devlist[i])); + + usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]), + libusb_get_device_address(devlist[i]), NULL); + devices = g_slist_append(devices, usb); + } + libusb_free_config_descriptor(confdes); + } + } + libusb_free_device_list(devlist, 1); + + sr_dbg("Found %d device(s).", g_slist_length(devices)); + + return devices; +} + SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb) { struct libusb_device **devlist; struct libusb_device_descriptor des; int ret, r, cnt, i, a, b; - sr_dbg("Trying to open USB device."); + sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address); if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) { sr_err("Failed to retrieve device list: %s.", @@ -166,11 +223,8 @@ SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb) b = libusb_get_bus_number(devlist[i]); a = libusb_get_device_address(devlist[i]); - - if (b != usb->bus || a != usb->address) { - sr_spew("bus.address = %d.%d does not match.", b, a); + if (b != usb->bus || a != usb->address) continue; - } if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) { sr_err("Failed to open device: %s.",