diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 2902a800..2619ac49 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -69,6 +69,11 @@ typedef enum { HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24, } hackrf_vendor_request; +typedef enum { + USB_CONFIG_STANDARD = 0x1, + USB_CONFIG_CPLD_UPDATE = 0x2, +} hackrf_usb_configurations; + typedef enum { HACKRF_TRANSCEIVER_MODE_OFF = 0, HACKRF_TRANSCEIVER_MODE_RECEIVE = 1, @@ -233,6 +238,74 @@ static int prepare_transfers( } } +static int detach_kernel_drivers(libusb_device_handle* usb_device_handle) +{ + int i, result; + libusb_device* dev; + struct libusb_config_descriptor* config; + + dev = libusb_get_device(usb_device_handle); + result = libusb_get_active_config_descriptor(dev, &config); + if( result < 0 ) + { + return HACKRF_ERROR_LIBUSB; + } + + for(i=0; ibNumInterfaces; i++) + { + result = libusb_kernel_driver_active(usb_device_handle, i); + if( result < 0 ) + { + if( result == LIBUSB_ERROR_NOT_SUPPORTED ) { + return 0; + } + return HACKRF_ERROR_LIBUSB; + } else if( result == 1 ) { + result = libusb_detach_kernel_driver(usb_device_handle, i); + if( result != 0 ) + { + return HACKRF_ERROR_LIBUSB; + } + } + } + return HACKRF_SUCCESS; +} + +static int set_hackrf_configuration(libusb_device_handle* usb_device, int config) +{ + int result, curr_config; + result = libusb_get_configuration(usb_device, &curr_config); + if( result != 0 ) + { + libusb_close(usb_device); + return HACKRF_ERROR_LIBUSB; + } + + if(curr_config != config) + { + result = detach_kernel_drivers(usb_device); + if( result != 0 ) + { + libusb_close(usb_device); + return result; + } + result = libusb_set_configuration(usb_device, config); + if( result != 0 ) + { + libusb_close(usb_device); + return HACKRF_ERROR_LIBUSB; + } + } + + result = detach_kernel_drivers(usb_device); + if( result != 0 ) + { + libusb_close(usb_device); + return result; + } + return LIBUSB_SUCCESS; +} + #ifdef __cplusplus extern "C" { @@ -410,16 +483,15 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d //int speed = libusb_get_device_speed(usb_device); // TODO: Error or warning if not high speed USB? - - result = libusb_set_configuration(usb_device, 1); - if( result != 0 ) + + result = set_hackrf_configuration(usb_device, USB_CONFIG_STANDARD); + if( result != LIBUSB_SUCCESS ) { - libusb_close(usb_device); - return HACKRF_ERROR_LIBUSB; + return result; } result = libusb_claim_interface(usb_device, 0); - if( result != 0 ) + if( result != LIBUSB_SUCCESS ) { libusb_close(usb_device); return HACKRF_ERROR_LIBUSB; @@ -842,10 +914,13 @@ int ADDCALL hackrf_cpld_write(hackrf_device* device, return HACKRF_ERROR_LIBUSB; } - result = libusb_set_configuration(device->usb_device, 2); - if (result != LIBUSB_SUCCESS) { - return HACKRF_ERROR_LIBUSB; + result = set_hackrf_configuration(device->usb_device, USB_CONFIG_CPLD_UPDATE); + if( result != LIBUSB_SUCCESS ) + { + return result; } + result = libusb_set_configuration(device->usb_device, 2); + result = libusb_claim_interface(device->usb_device, 0); if (result != LIBUSB_SUCCESS) {