Fix GitHub issue #163 - Detach the kernel driver automatically

This commit is contained in:
Dominic Spill
2015-06-26 17:50:27 +01:00
parent a1b8535ac0
commit 1acd6a6ad6

View File

@ -69,6 +69,11 @@ typedef enum {
HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24, HACKRF_VENDOR_REQUEST_SET_FREQ_EXPLICIT = 24,
} hackrf_vendor_request; } hackrf_vendor_request;
typedef enum {
USB_CONFIG_STANDARD = 0x1,
USB_CONFIG_CPLD_UPDATE = 0x2,
} hackrf_usb_configurations;
typedef enum { typedef enum {
HACKRF_TRANSCEIVER_MODE_OFF = 0, HACKRF_TRANSCEIVER_MODE_OFF = 0,
HACKRF_TRANSCEIVER_MODE_RECEIVE = 1, 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; i<config->bNumInterfaces; 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 #ifdef __cplusplus
extern "C" 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); //int speed = libusb_get_device_speed(usb_device);
// TODO: Error or warning if not high speed USB? // TODO: Error or warning if not high speed USB?
result = libusb_set_configuration(usb_device, 1); result = set_hackrf_configuration(usb_device, USB_CONFIG_STANDARD);
if( result != 0 ) if( result != LIBUSB_SUCCESS )
{ {
libusb_close(usb_device); return result;
return HACKRF_ERROR_LIBUSB;
} }
result = libusb_claim_interface(usb_device, 0); result = libusb_claim_interface(usb_device, 0);
if( result != 0 ) if( result != LIBUSB_SUCCESS )
{ {
libusb_close(usb_device); libusb_close(usb_device);
return HACKRF_ERROR_LIBUSB; return HACKRF_ERROR_LIBUSB;
@ -842,10 +914,13 @@ int ADDCALL hackrf_cpld_write(hackrf_device* device,
return HACKRF_ERROR_LIBUSB; return HACKRF_ERROR_LIBUSB;
} }
result = libusb_set_configuration(device->usb_device, 2); result = set_hackrf_configuration(device->usb_device, USB_CONFIG_CPLD_UPDATE);
if (result != LIBUSB_SUCCESS) { if( result != LIBUSB_SUCCESS )
return HACKRF_ERROR_LIBUSB; {
return result;
} }
result = libusb_set_configuration(device->usb_device, 2);
result = libusb_claim_interface(device->usb_device, 0); result = libusb_claim_interface(device->usb_device, 0);
if (result != LIBUSB_SUCCESS) { if (result != LIBUSB_SUCCESS) {