static int lusb_open(void **driver, struct bladerf_devinfo *info_in, struct bladerf_devinfo *info_out) { int status; struct bladerf_lusb *lusb = NULL; libusb_context *context; /* Initialize libusb for device tree walking */ status = libusb_init(&context); if (status) { log_error("Could not initialize libusb: %s\n", libusb_error_name(status)); return error_conv(status); } /* We can only print this out when log output is enabled, or else we'll * get snagged by -Werror=unused-but-set-variable */ # ifdef LOGGING_ENABLED { char buf[64]; get_libusb_version(buf, sizeof(buf)); log_verbose("Using libusb version: %s\n", buf); } # endif status = find_and_open_device(context, info_in, &lusb, info_out); if (status != 0) { libusb_exit(context); if (status == BLADERF_ERR_NODEV) { log_debug("No devices available on the libusb backend.\n"); } else { log_debug("Failed to open bladeRF on libusb backend: %s\n", bladerf_strerror(status)); } } else { assert(lusb != NULL); /* Cosmin and Marian from Null Team (null.ro) and YateBTS(.com) found * that it is possible to recover from "Issue #95: Not enough bandwidth * for altsetting" by performing a USB port reset prior to actually * trying to use the device. */ # if ENABLE_USB_DEV_RESET_ON_OPEN if (bladerf_usb_reset_device_on_open) { status = reset_and_reopen(context, &lusb, info_out); } # endif if (status == 0) { *driver = (void *) lusb; } } return status; }
static int reset_and_reopen(libusb_context *context, struct bladerf_lusb **dev, struct bladerf_devinfo *info) { int status; status = libusb_reset_device((*dev)->handle); if (status == 0) { log_verbose("USB port reset succeeded for bladeRF %s\n", info->serial); return 0; } else if (status == LIBUSB_ERROR_NO_DEVICE) { struct bladerf_devinfo new_info; /* The reset has caused the device to drop out and re-enumerate. * * We'll find it again via the info we gathered about it via its * serial number, which is now stored in the devinfo */ log_verbose("Re-scan required after port reset for bladeRF %s\n", info->serial); libusb_release_interface((*dev)->handle, 0); libusb_close((*dev)->handle); #if 1 == BLADERF_OS_WINDOWS ReleaseMutex((*dev)->mutex); #endif // BLADERF_OS_WINDOWS *dev = NULL; memcpy(&new_info, info, sizeof(new_info)); new_info.usb_bus = DEVINFO_BUS_ANY; new_info.usb_addr = DEVINFO_ADDR_ANY; status = find_and_open_device(context, &new_info, dev, info); } else { status = BLADERF_ERR_IO; log_verbose("Port reset failed for bladerf %s: %s\n", info->serial, libusb_error_name(status)); } return status; }