Merge pull request #185 from dominicgs/remove-kernel-driver

Fix GitHub issue #163 - Detach the kernel driver automatically
This commit is contained in:
Michael Ossmann
2015-06-29 12:00:58 -06:00

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,72 @@ static int prepare_transfers(
} }
} }
static int detach_kernel_drivers(libusb_device_handle* usb_device_handle)
{
int i, num_interfaces, 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;
}
num_interfaces = config->bNumInterfaces;
libusb_free_config_descriptor(config);
for(i=0; i<num_interfaces; 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 )
{
return HACKRF_ERROR_LIBUSB;
}
if(curr_config != config)
{
result = detach_kernel_drivers(usb_device);
if( result != 0 )
{
return result;
}
result = libusb_set_configuration(usb_device, config);
if( result != 0 )
{
return HACKRF_ERROR_LIBUSB;
}
}
result = detach_kernel_drivers(usb_device);
if( result != 0 )
{
return result;
}
return LIBUSB_SUCCESS;
}
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -410,16 +481,16 @@ 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); libusb_close(usb_device);
return HACKRF_ERROR_LIBUSB; return result;
} }
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,9 +913,10 @@ 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_claim_interface(device->usb_device, 0); result = libusb_claim_interface(device->usb_device, 0);