This commit is contained in:
Chris Kuethe
2015-07-08 11:44:33 -07:00
15 changed files with 547 additions and 121 deletions

View File

@@ -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,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
extern "C"
{
@@ -240,6 +311,10 @@ extern "C"
int ADDCALL hackrf_init(void)
{
if (g_libusb_context != NULL) {
return HACKRF_SUCCESS;
}
const int libusb_error = libusb_init(&g_libusb_context);
if( libusb_error != 0 )
{
@@ -260,41 +335,162 @@ int ADDCALL hackrf_exit(void)
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_open(hackrf_device** device)
#include <stdio.h>
#include <string.h>
hackrf_device_list_t* ADDCALL hackrf_device_list()
{
ssize_t i;
libusb_device_handle* usb_device = NULL;
hackrf_device_list_t* list = calloc(1, sizeof(*list));
if ( list == NULL )
return NULL;
list->usb_devicecount = libusb_get_device_list(g_libusb_context, (libusb_device ***)&list->usb_devices);
list->serial_numbers = calloc(list->usb_devicecount, sizeof(void *));
list->usb_board_ids = calloc(list->usb_devicecount, sizeof(enum hackrf_usb_board_id));
list->usb_device_index = calloc(list->usb_devicecount, sizeof(int));
if ( list->serial_numbers == NULL || list->usb_board_ids == NULL || list->usb_device_index == NULL) {
hackrf_device_list_free(list);
return NULL;
}
for (i=0; i<list->usb_devicecount; i++) {
struct libusb_device_descriptor device_descriptor;
libusb_get_device_descriptor(list->usb_devices[i], &device_descriptor);
if( device_descriptor.idVendor == hackrf_usb_vid ) {
if( (device_descriptor.idProduct == hackrf_one_usb_pid) || (device_descriptor.idProduct == hackrf_jawbreaker_usb_pid) ) {
int idx = list->devicecount++;
list->usb_board_ids[idx] = device_descriptor.idProduct;
list->usb_device_index[idx] = i;
const uint_fast8_t serial_descriptor_index = device_descriptor.iSerialNumber;
if( serial_descriptor_index > 0 ) {
if( libusb_open(list->usb_devices[i], &usb_device) != 0 ) {
usb_device = NULL;
continue;
}
char serial_number[64];
const int serial_number_length = libusb_get_string_descriptor_ascii(usb_device, serial_descriptor_index, (unsigned char*)serial_number, sizeof(serial_number));
if( serial_number_length == 32 ) {
serial_number[32] = 0;
list->serial_numbers[idx] = strdup(serial_number);
}
libusb_close(usb_device);
usb_device = NULL;
}
}
}
}
return list;
}
void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list)
{
int i;
libusb_free_device_list((libusb_device **)list->usb_devices, 1);
for (i = 0; i < list->devicecount; i++) {
if (list->serial_numbers[i])
free(list->serial_numbers[i]);
}
free(list->serial_numbers);
free(list->usb_board_ids);
free(list->usb_device_index);
free(list);
}
libusb_device_handle* hackrf_open_usb(const char* const desired_serial_number)
{
libusb_device_handle* usb_device = NULL;
libusb_device** devices = NULL;
const ssize_t list_length = libusb_get_device_list(g_libusb_context, &devices);
int match_len = 0;
ssize_t i;
printf("Number of USB devices: %ld\n", list_length);
if( desired_serial_number ) {
/* If a shorter serial number is specified, only match against the suffix.
* Should probably complain if the match is not unique, currently doesn't.
*/
match_len = strlen(desired_serial_number);
if ( match_len > 32 )
return NULL;
}
for (i=0; i<list_length; i++) {
struct libusb_device_descriptor device_descriptor;
libusb_get_device_descriptor(devices[i], &device_descriptor);
if( device_descriptor.idVendor == hackrf_usb_vid ) {
if( (device_descriptor.idProduct == hackrf_one_usb_pid) || (device_descriptor.idProduct == hackrf_jawbreaker_usb_pid) ) {
printf("USB device %4x:%4x:", device_descriptor.idVendor, device_descriptor.idProduct);
if( desired_serial_number != NULL ) {
const uint_fast8_t serial_descriptor_index = device_descriptor.iSerialNumber;
if( serial_descriptor_index > 0 ) {
if( libusb_open(devices[i], &usb_device) != 0 ) {
usb_device = NULL;
continue;
}
char serial_number[64];
const int serial_number_length = libusb_get_string_descriptor_ascii(usb_device, serial_descriptor_index, (unsigned char*)serial_number, sizeof(serial_number));
if( serial_number_length == 32 ) {
serial_number[32] = 0;
printf(" %s", serial_number);
if( strncmp(serial_number + 32-match_len, desired_serial_number, match_len) == 0 ) {
printf(" match\n");
break;
} else {
printf(" skip\n");
libusb_close(usb_device);
usb_device = NULL;
}
} else {
printf(" wrong length of serial number: %d\n", serial_number_length);
libusb_close(usb_device);
usb_device = NULL;
}
}
} else {
printf(" default\n");
libusb_open(devices[i], &usb_device);
break;
}
}
}
}
libusb_free_device_list(devices, 1);
return usb_device;
}
static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** device)
{
int result;
libusb_device_handle* usb_device;
hackrf_device* lib_device;
if( device == NULL )
{
return HACKRF_ERROR_INVALID_PARAM;
}
// TODO: Do proper scanning of available devices, searching for
// unit serial number (if specified?).
usb_device = libusb_open_device_with_vid_pid(g_libusb_context, hackrf_usb_vid, hackrf_one_usb_pid);
if( usb_device == NULL )
{
usb_device = libusb_open_device_with_vid_pid(g_libusb_context, hackrf_usb_vid, hackrf_jawbreaker_usb_pid);
}
if( usb_device == NULL )
{
return HACKRF_ERROR_NOT_FOUND;
}
//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;
@@ -336,6 +532,73 @@ int ADDCALL hackrf_open(hackrf_device** device)
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_open(hackrf_device** device)
{
libusb_device_handle* usb_device;
if( device == NULL )
{
return HACKRF_ERROR_INVALID_PARAM;
}
usb_device = libusb_open_device_with_vid_pid(g_libusb_context, hackrf_usb_vid, hackrf_one_usb_pid);
if( usb_device == NULL )
{
usb_device = libusb_open_device_with_vid_pid(g_libusb_context, hackrf_usb_vid, hackrf_jawbreaker_usb_pid);
}
if( usb_device == NULL )
{
return HACKRF_ERROR_NOT_FOUND;
}
return hackrf_open_setup(usb_device, device);
}
int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device)
{
libusb_device_handle* usb_device;
if( desired_serial_number == NULL )
{
return hackrf_open(device);
}
if( device == NULL )
{
return HACKRF_ERROR_INVALID_PARAM;
}
usb_device = hackrf_open_usb(desired_serial_number);
if( usb_device == NULL )
{
return HACKRF_ERROR_NOT_FOUND;
}
return hackrf_open_setup(usb_device, device);
}
int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device)
{
libusb_device_handle* usb_device;
if( device == NULL || list == NULL || idx < 0 || idx >= list->devicecount )
{
return HACKRF_ERROR_INVALID_PARAM;
}
int i = list->usb_device_index[idx];
if( libusb_open(list->usb_devices[i], &usb_device) != 0 ) {
usb_device = NULL;
return HACKRF_ERROR_LIBUSB;
}
return hackrf_open_setup(usb_device, device);
}
int ADDCALL hackrf_set_transceiver_mode(hackrf_device* device, hackrf_transceiver_mode value)
{
int result;
@@ -644,22 +907,12 @@ int ADDCALL hackrf_cpld_write(hackrf_device* device,
{
const unsigned int chunk_size = 512;
unsigned int i;
int transferred = 0;
int result = libusb_release_interface(device->usb_device, 0);
if (result != LIBUSB_SUCCESS) {
return HACKRF_ERROR_LIBUSB;
}
result = libusb_set_configuration(device->usb_device, 2);
if (result != LIBUSB_SUCCESS) {
return HACKRF_ERROR_LIBUSB;
}
result = libusb_claim_interface(device->usb_device, 0);
if (result != LIBUSB_SUCCESS) {
return HACKRF_ERROR_LIBUSB;
}
int result, transferred = 0;
result = hackrf_set_transceiver_mode(device, TRANSCEIVER_MODE_CPLD_UPDATE);
if (result != 0)
return result;
for (i = 0; i < total_length; i += chunk_size)
{
result = libusb_bulk_transfer(
@@ -1343,6 +1596,24 @@ const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id)
}
}
extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name(enum hackrf_usb_board_id usb_board_id)
{
switch(usb_board_id)
{
case USB_BOARD_ID_JAWBREAKER:
return "Jawbreaker";
case USB_BOARD_ID_HACKRF_ONE:
return "HackRF One";
case USB_BOARD_ID_INVALID:
return "Invalid Board ID";
default:
return "Unknown Board ID";
}
}
const char* ADDCALL hackrf_filter_path_name(const enum rf_path_filter path)
{
switch(path) {