X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fcommon%2Fusb.c;h=c3279d0ae1ef58640013483f9b6711deca9be15a;hb=102f12396660e0784134bccce5cc0679db325751;hp=efe4eb432a1444c854da118a3a15945707a0c40a;hpb=1953564a96798bc298d1c94eb90c129adbde1c9e;p=libsigrok.git diff --git a/hardware/common/usb.c b/hardware/common/usb.c index efe4eb43..c3279d0a 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 @@ -26,21 +26,10 @@ #include "libsigrok-internal.h" /* SR_CONF_CONN takes one of these: */ -#define CONN_USB_VIDPID "^([0-9a-z]{1,4})\\.([0-9a-z]{1,4})$" +#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$" #define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$" -/* Some USBTMC-specific enums, as defined in the USBTMC standard. */ -#define SUBCLASS_USBTMC 0x03 -#define USBTMC_USB488 0x01 - -/* 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) +#define LOG_PREFIX "usb" /** * Find USB devices according to a connection string. @@ -82,11 +71,11 @@ SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn) reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL); if (g_regex_match(reg, conn, 0, &match)) { if ((mstr = g_match_info_fetch(match, 1))) - bus = strtoul(mstr, NULL, 16); + bus = strtoul(mstr, NULL, 10); g_free(mstr); if ((mstr = g_match_info_fetch(match, 2))) - addr = strtoul(mstr, NULL, 16); + addr = strtoul(mstr, NULL, 10); g_free(mstr); sr_dbg("Trying to find USB device with bus.address = " "%d.%d.", bus, addr); @@ -142,63 +131,6 @@ SR_PRIV GSList *sr_usb_find(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; @@ -243,3 +175,97 @@ SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb) return ret; } + +#ifdef _WIN32 +static gpointer usb_thread(gpointer data) +{ + struct sr_context *ctx = data; + + while (ctx->usb_thread_running) { + g_mutex_lock(&ctx->usb_mutex); + libusb_wait_for_event(ctx->libusb_ctx, NULL); + SetEvent(ctx->usb_event); + g_mutex_unlock(&ctx->usb_mutex); + g_thread_yield(); + } + + return NULL; +} + +static int usb_callback(int fd, int revents, void *cb_data) +{ + struct sr_context *ctx = cb_data; + int ret; + + g_mutex_lock(&ctx->usb_mutex); + ret = ctx->usb_cb(fd, revents, ctx->usb_cb_data); + + if (ctx->usb_thread_running) { + ResetEvent(ctx->usb_event); + g_mutex_unlock(&ctx->usb_mutex); + } + + return ret; +} +#endif + +SR_PRIV int usb_source_add(struct sr_session *session, struct sr_context *ctx, + int timeout, sr_receive_data_callback cb, void *cb_data) +{ + if (ctx->usb_source_present) { + sr_err("A USB event source is already present."); + return SR_ERR; + } + +#ifdef _WIN32 + ctx->usb_event = CreateEvent(NULL, TRUE, FALSE, NULL); + g_mutex_init(&ctx->usb_mutex); + ctx->usb_thread_running = TRUE; + ctx->usb_thread = g_thread_new("usb", usb_thread, ctx); + ctx->usb_pollfd.fd = ctx->usb_event; + ctx->usb_pollfd.events = G_IO_IN; + ctx->usb_cb = cb; + ctx->usb_cb_data = cb_data; + sr_session_source_add_pollfd(session, &ctx->usb_pollfd, timeout, + usb_callback, ctx); +#else + const struct libusb_pollfd **lupfd; + unsigned int i; + + lupfd = libusb_get_pollfds(ctx->libusb_ctx); + for (i = 0; lupfd[i]; i++) + sr_session_source_add(session, lupfd[i]->fd, lupfd[i]->events, + timeout, cb, cb_data); + free(lupfd); +#endif + ctx->usb_source_present = TRUE; + + return SR_OK; +} + +SR_PRIV int usb_source_remove(struct sr_session *session, struct sr_context *ctx) +{ + if (!ctx->usb_source_present) + return SR_OK; + +#ifdef _WIN32 + ctx->usb_thread_running = FALSE; + g_mutex_unlock(&ctx->usb_mutex); + libusb_unlock_events(ctx->libusb_ctx); + g_thread_join(ctx->usb_thread); + g_mutex_clear(&ctx->usb_mutex); + sr_session_source_remove_pollfd(session, &ctx->usb_pollfd); + CloseHandle(ctx->usb_event); +#else + const struct libusb_pollfd **lupfd; + unsigned int i; + + lupfd = libusb_get_pollfds(ctx->libusb_ctx); + for (i = 0; lupfd[i]; i++) + sr_session_source_remove(session, lupfd[i]->fd); + free(lupfd); +#endif + ctx->usb_source_present = FALSE; + + return SR_OK; +}