diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 8ce6c943..bad03a40 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -345,7 +345,9 @@ extern "C" typedef enum { TRANSCEIVER_MODE_OFF = 0, TRANSCEIVER_MODE_RX = 1, - TRANSCEIVER_MODE_TX = 2 + TRANSCEIVER_MODE_TX = 2, + TRANSCEIVER_MODE_SS = 3, + TRANSCEIVER_MODE_CPLD_UPDATE = 4 } transceiver_mode_t; void delay(uint32_t duration); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 42fc4482..c5ccb6ad 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -32,6 +32,9 @@ #include "usb.h" #include "usb_standard_request.h" +#include +#include "usb_descriptor.h" + #include "usb_device.h" #include "usb_endpoint.h" #include "usb_api_board_info.h" @@ -96,6 +99,11 @@ usb_request_status_t usb_vendor_request_set_transceiver_mode( set_transceiver_mode(endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; + case TRANSCEIVER_MODE_CPLD_UPDATE: + usb_endpoint_init(&usb_endpoint_bulk_out); + start_cpld_update = true; + usb_transfer_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; default: return USB_REQUEST_STATUS_STALL; } @@ -183,6 +191,31 @@ void usb_configuration_changed( } } +void usb_set_descriptor_by_serial_number(void) +{ + iap_cmd_res_t iap_cmd_res; + + /* Read IAP Serial Number Identification */ + iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO; + iap_cmd_call(&iap_cmd_res); + + if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) { + usb_descriptor_string_serial_number[0] = USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN; + usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; + + /* 32 characters of serial number, convert to UTF-16LE */ + for (size_t i=0; i> 3] >> (28 - (i & 7) * 4)) & 0xf; + const char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble); + usb_descriptor_string_serial_number[2 + i * 2] = c; + usb_descriptor_string_serial_number[3 + i * 2] = 0x00; + } + } else { + usb_descriptor_string_serial_number[0] = 2; + usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; + } +} + int main(void) { pin_setup(); enable_1v8_power(); @@ -191,6 +224,8 @@ int main(void) { #endif cpu_clock_init(); + usb_set_descriptor_by_serial_number(); + usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 88818529..ff770b24 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -22,6 +22,7 @@ #include #include "usb_type.h" +#include "usb_descriptor.h" #define USB_VENDOR_ID (0x1D50) @@ -57,7 +58,7 @@ uint8_t usb_descriptor_device[] = { USB_WORD(0x0100), // bcdDevice 0x01, // iManufacturer 0x02, // iProduct - 0x00, // iSerialNumber + 0x05, // iSerialNumber 0x02 // bNumConfigurations }; @@ -329,12 +330,14 @@ uint8_t usb_descriptor_string_config2_description[] = { 'e', 0x00, }; -uint8_t* const usb_descriptor_strings[] = { +uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN]; + +uint8_t* usb_descriptor_strings[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, usb_descriptor_string_product, usb_descriptor_string_config1_description, usb_descriptor_string_config2_description, - + usb_descriptor_string_serial_number, 0, // TERMINATOR }; diff --git a/firmware/hackrf_usb/usb_descriptor.h b/firmware/hackrf_usb/usb_descriptor.h index 11e274a7..bffa9bf7 100644 --- a/firmware/hackrf_usb/usb_descriptor.h +++ b/firmware/hackrf_usb/usb_descriptor.h @@ -30,6 +30,9 @@ extern uint8_t usb_descriptor_configuration_cpld_update_high_speed[]; extern uint8_t usb_descriptor_string_languages[]; extern uint8_t usb_descriptor_string_manufacturer[]; extern uint8_t usb_descriptor_string_product[]; + +#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32 +#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN (USB_DESCRIPTOR_STRING_SERIAL_LEN*2 + 2) /* UTF-16LE */ extern uint8_t usb_descriptor_string_serial_number[]; extern uint8_t* usb_descriptor_strings[]; diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 874163f8..52350c32 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -5,6 +5,7 @@ project (hackrf_all) add_subdirectory(libhackrf) add_subdirectory(hackrf-tools) +add_subdirectory(misc) ######################################################################## # Create uninstall target diff --git a/host/hackrf-tools/src/hackrf_cpldjtag.c b/host/hackrf-tools/src/hackrf_cpldjtag.c index b4fb5d26..b76c9349 100644 --- a/host/hackrf-tools/src/hackrf_cpldjtag.c +++ b/host/hackrf-tools/src/hackrf_cpldjtag.c @@ -80,6 +80,7 @@ static void usage() { printf("Usage:\n"); printf("\t-x : XSVF file to be written to CPLD.\n"); + printf("\t-d : Serial number of device, if multiple devices\n"); } int main(int argc, char** argv) @@ -88,6 +89,7 @@ int main(int argc, char** argv) uint32_t length = 0; uint32_t total_length = 0; const char* path = NULL; + const char* serial_number = NULL; hackrf_device* device = NULL; int result = HACKRF_SUCCESS; int option_index = 0; @@ -95,13 +97,17 @@ int main(int argc, char** argv) ssize_t bytes_read; uint8_t* pdata = &data[0]; - while ((opt = getopt_long(argc, argv, "x:", long_options, + while ((opt = getopt_long(argc, argv, "x:d:", long_options, &option_index)) != EOF) { switch (opt) { case 'x': path = optarg; break; + case 'd': + serial_number = optarg; + break; + default: usage(); return EXIT_FAILURE; @@ -158,7 +164,7 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - result = hackrf_open(&device); + result = hackrf_open_by_serial(serial_number, &device); if (result != HACKRF_SUCCESS) { fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); diff --git a/host/hackrf-tools/src/hackrf_info.c b/host/hackrf-tools/src/hackrf_info.c index d83b9696..99b86d3b 100644 --- a/host/hackrf-tools/src/hackrf_info.c +++ b/host/hackrf-tools/src/hackrf_info.c @@ -28,11 +28,12 @@ int main(int argc, char** argv) { - hackrf_device* device = NULL; int result = HACKRF_SUCCESS; uint8_t board_id = BOARD_ID_INVALID; char version[255 + 1]; read_partid_serialno_t read_partid_serialno; + hackrf_device_list_t *list; + int i; result = hackrf_init(); if (result != HACKRF_SUCCESS) { @@ -40,55 +41,71 @@ int main(int argc, char** argv) hackrf_error_name(result), result); return EXIT_FAILURE; } - - result = hackrf_open(&device); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_open() failed: %s (%d)\n", - hackrf_error_name(result), result); - return EXIT_FAILURE; - } - - printf("Found HackRF board.\n"); - - result = hackrf_board_id_read(device, &board_id); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_board_id_read() failed: %s (%d)\n", - hackrf_error_name(result), result); - return EXIT_FAILURE; - } - printf("Board ID Number: %d (%s)\n", board_id, - hackrf_board_id_name(board_id)); - - result = hackrf_version_string_read(device, &version[0], 255); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_version_string_read() failed: %s (%d)\n", - hackrf_error_name(result), result); - return EXIT_FAILURE; - } - printf("Firmware Version: %s\n", version); - - result = hackrf_board_partid_serialno_read(device, &read_partid_serialno); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_board_partid_serialno_read() failed: %s (%d)\n", - hackrf_error_name(result), result); - return EXIT_FAILURE; - } - printf("Part ID Number: 0x%08x 0x%08x\n", - read_partid_serialno.part_id[0], - read_partid_serialno.part_id[1]); - printf("Serial Number: 0x%08x 0x%08x 0x%08x 0x%08x\n", - read_partid_serialno.serial_no[0], - read_partid_serialno.serial_no[1], - read_partid_serialno.serial_no[2], - read_partid_serialno.serial_no[3]); - result = hackrf_close(device); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_close() failed: %s (%d)\n", - hackrf_error_name(result), result); + list = hackrf_device_list(); + + if (list->devicecount < 1 ) { + printf("No HackRF boards found.\n"); return EXIT_FAILURE; } + + for (i = 0; i < list->devicecount; i++) { + if (i > 0) + printf("\n"); + + printf("Found HackRF board %d:\n", i); + + if (list->serial_numbers[i]) + printf("USB descriptor string: %s\n", list->serial_numbers[i]); + hackrf_device* device = NULL; + result = hackrf_device_list_open(list, i, &device); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_open() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + + result = hackrf_board_id_read(device, &board_id); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_board_id_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + printf("Board ID Number: %d (%s)\n", board_id, + hackrf_board_id_name(board_id)); + + result = hackrf_version_string_read(device, &version[0], 255); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_version_string_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + printf("Firmware Version: %s\n", version); + + result = hackrf_board_partid_serialno_read(device, &read_partid_serialno); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_board_partid_serialno_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + printf("Part ID Number: 0x%08x 0x%08x\n", + read_partid_serialno.part_id[0], + read_partid_serialno.part_id[1]); + printf("Serial Number: 0x%08x 0x%08x 0x%08x 0x%08x\n", + read_partid_serialno.serial_no[0], + read_partid_serialno.serial_no[1], + read_partid_serialno.serial_no[2], + read_partid_serialno.serial_no[3]); + + result = hackrf_close(device); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_close() failed: %s (%d)\n", + hackrf_error_name(result), result); + } + } + + hackrf_device_list_free(list); hackrf_exit(); return EXIT_SUCCESS; diff --git a/host/hackrf-tools/src/hackrf_spiflash.c b/host/hackrf-tools/src/hackrf_spiflash.c index ba2c224e..f210f370 100644 --- a/host/hackrf-tools/src/hackrf_spiflash.c +++ b/host/hackrf-tools/src/hackrf_spiflash.c @@ -89,6 +89,7 @@ static void usage() printf("\t-l, --length : number of bytes to read (default: 0)\n"); printf("\t-r : Read data into file.\n"); printf("\t-w : Write data from file.\n"); + printf("\t-d : Serial number of device, if multiple devices\n"); } int main(int argc, char** argv) @@ -99,6 +100,7 @@ int main(int argc, char** argv) uint32_t tmp_length; uint16_t xfer_len = 0; const char* path = NULL; + const char* serial_number = NULL; hackrf_device* device = NULL; int result = HACKRF_SUCCESS; int option_index = 0; @@ -108,7 +110,7 @@ int main(int argc, char** argv) bool read = false; bool write = false; - while ((opt = getopt_long(argc, argv, "a:l:r:w:", long_options, + while ((opt = getopt_long(argc, argv, "a:l:r:w:d:", long_options, &option_index)) != EOF) { switch (opt) { case 'a': @@ -128,6 +130,10 @@ int main(int argc, char** argv) write = true; path = optarg; break; + + case 'd': + serial_number = optarg; + break; default: fprintf(stderr, "opt error: %d\n", opt); @@ -213,7 +219,7 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - result = hackrf_open(&device); + result = hackrf_open_by_serial(serial_number, &device); if (result != HACKRF_SUCCESS) { fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index bd9bdb78..64bd0083 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -168,13 +168,6 @@ t_wav_file_hdr wave_file_hdr = } }; -typedef enum { - TRANSCEIVER_MODE_OFF = 0, - TRANSCEIVER_MODE_RX = 1, - TRANSCEIVER_MODE_TX = 2, - TRANSCEIVER_MODE_SS = 3 - -} transceiver_mode_t; static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_RX; #define U64TOA_MAX_DIGIT (31) @@ -422,6 +415,7 @@ int tx_callback(hackrf_transfer* transfer) { static void usage() { printf("Usage:\n"); + printf("\t[-d serial_number] # Serial number of desired HackRF.\n"); printf("\t-r # Receive data into file.\n"); printf("\t-t # Transmit data from file.\n"); printf("\t-w # Receive data into file with WAV header and automatic name.\n"); @@ -477,6 +471,7 @@ int main(int argc, char** argv) { char path_file[PATH_FILE_MAX_LEN]; char date_time[DATE_TIME_MAX_LEN]; const char* path = NULL; + const char* serial_number = NULL; int result; time_t rawtime; struct tm * timeinfo; @@ -486,7 +481,7 @@ int main(int argc, char** argv) { float time_diff; unsigned int lna_gain=8, vga_gain=20, txvga_gain=0; - while( (opt = getopt(argc, argv, "wr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:")) != EOF ) + while( (opt = getopt(argc, argv, "wr:t:f:i:o:m:a:p:s:n:b:l:g:x:c:d:")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) @@ -505,6 +500,10 @@ int main(int argc, char** argv) { path = optarg; break; + case 'd': + serial_number = optarg; + break; + case 'f': automatic_tuning = true; result = parse_u64(optarg, &freq_hz); @@ -782,7 +781,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - result = hackrf_open(&device); + result = hackrf_open_by_serial(serial_number, &device); if( result != HACKRF_SUCCESS ) { printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); usage(); diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index 4f1ec642..8b003941 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -94,21 +94,3 @@ add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake ) endif() - -######################################################################## -# Install udev rules -######################################################################## -option(INSTALL_UDEV_RULES "Install udev rules for HackRF" OFF) -if (INSTALL_UDEV_RULES) - if (NOT UDEV_INSTALL_DIR) - set (UDEV_INSTALL_DIR "/etc/udev/rules.d") - endif (NOT UDEV_INSTALL_DIR) - - install ( - FILES 53-hackrf.rules - DESTINATION ${UDEV_INSTALL_DIR} - COMPONENT "udev" - ) -else (INSTALL_UDEV_RULES) - message (STATUS "Udev rules not being installed, install them with -DINSTALL_UDEV_RULES=ON") -endif (INSTALL_UDEV_RULES) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 85de4506..4471cace 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,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 +#include + +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; iusb_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 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) { diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 1c8bc1a0..503e4ec3 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -69,12 +69,26 @@ enum hackrf_board_id { BOARD_ID_INVALID = 0xFF, }; +enum hackrf_usb_board_id { + USB_BOARD_ID_JAWBREAKER = 0x604B, + USB_BOARD_ID_HACKRF_ONE = 0x6089, + USB_BOARD_ID_INVALID = 0xFFFF, +}; + enum rf_path_filter { RF_PATH_FILTER_BYPASS = 0, RF_PATH_FILTER_LOW_PASS = 1, RF_PATH_FILTER_HIGH_PASS = 2, }; +typedef enum { + TRANSCEIVER_MODE_OFF = 0, + TRANSCEIVER_MODE_RX = 1, + TRANSCEIVER_MODE_TX = 2, + TRANSCEIVER_MODE_SS = 3, + TRANSCEIVER_MODE_CPLD_UPDATE = 4 +} transceiver_mode_t; + typedef struct hackrf_device hackrf_device; typedef struct { @@ -91,6 +105,18 @@ typedef struct { uint32_t serial_no[4]; } read_partid_serialno_t; + +struct hackrf_device_list { + char **serial_numbers; + enum hackrf_usb_board_id *usb_board_ids; + int *usb_device_index; + int devicecount; + + void **usb_devices; + int usb_devicecount; +}; +typedef struct hackrf_device_list hackrf_device_list_t; + typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer); #ifdef __cplusplus @@ -100,8 +126,13 @@ extern "C" extern ADDAPI int ADDCALL hackrf_init(); extern ADDAPI int ADDCALL hackrf_exit(); + +extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list(); +extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device); +extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list); extern ADDAPI int ADDCALL hackrf_open(hackrf_device** device); +extern ADDAPI int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device); extern ADDAPI int ADDCALL hackrf_close(hackrf_device* device); extern ADDAPI int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx); @@ -164,6 +195,7 @@ extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode); extern ADDAPI 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); extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_filter path); /* Compute nearest freq for bw filter (manual filter) */ diff --git a/host/misc/CMakeLists.txt b/host/misc/CMakeLists.txt new file mode 100644 index 00000000..f728056f --- /dev/null +++ b/host/misc/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 2.8) +add_subdirectory(udev) diff --git a/host/misc/udev/53-hackrf.rules.in b/host/misc/udev/53-hackrf.rules.in new file mode 100644 index 00000000..951c424d --- /dev/null +++ b/host/misc/udev/53-hackrf.rules.in @@ -0,0 +1,6 @@ +# HackRF Jawbreaker +ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", SYMLINK+="hackrf-jawbreaker-%k", MODE="660", GROUP="@HACKRF_GROUP@" +# HackRF One +ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", SYMLINK+="hackrf-one-%k", MODE="660", GROUP="@HACKRF_GROUP@" +# HackRF DFU +ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", SYMLINK+="nxp-dfu-%k", MODE="660", GROUP="@HACKRF_GROUP@" diff --git a/host/misc/udev/CMakeLists.txt b/host/misc/udev/CMakeLists.txt new file mode 100644 index 00000000..1d65e63f --- /dev/null +++ b/host/misc/udev/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 2.8) + +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + SET(SYSTEM_IS_LINUX TRUE) + SET(UDEV_OPTION_DEFAULT ON) +else() + SET(SYSTEM_IS_LINUX FALSE) + SET(UDEV_OPTION_DEFAULT OFF) +endif() + +option(INSTALL_UDEV_RULES + "Install udev rules for the HackRF" + ${UDEV_OPTION_DEFAULT} +) + +set(UDEV_RULES_PATH + "/etc/udev/rules.d" + CACHE STRING + "Target directory for udev rule installation. Ensure you have permissions to write to this directory." +) + +if(SYSTEM_IS_LINUX) + if(INSTALL_UDEV_RULES) + if(NOT DEFINED UDEV_RULES_GROUP) + foreach(group usb plugdev) + execute_process(COMMAND "getent" group "${group}" + RESULT_VARIABLE _GETENT_RESULT + OUTPUT_QUIET + ERROR_QUIET) + if(NOT _GETENT_RESULT) + message(STATUS "Setting udev rule group to - ${group}") + set(UDEV_RULES_GROUP ${group}) + break() + endif(NOT _GETENT_RESULT) + endforeach(group) + endif(NOT DEFINED UDEV_RULES_GROUP) + if(DEFINED UDEV_RULES_GROUP) + set(HACKRF_GROUP "${UDEV_RULES_GROUP}" + CACHE STRING "Group to associate HackRF devices with in udev rules") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/53-hackrf.rules.in + ${CMAKE_CURRENT_BINARY_DIR}/53-hackrf.rules + @ONLY + ) + message(STATUS "HackRF udev rules will be installed to '${UDEV_RULES_PATH}' upon running 'make install'") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/53-hackrf.rules + DESTINATION ${UDEV_RULES_PATH} + COMPONENT "udev_rules") + else(UDEV_RULES_GROUP) + message(STATUS "HackRF udev rules will not be installed because no suitable group was found") + message(STATUS "A group can be specified with -DUDEV_RULES_GROUP=") + endif(DEFINED UDEV_RULES_GROUP) + else(INSTALL_UDEV_RULES) + message(STATUS + "HackRF udev rules will not be installed because INSTALL_UDEV_RULES=OFF" + ) + endif(INSTALL_UDEV_RULES) +else(SYSTEM_IS_LINUX) + if(INSTALL_UDEV_RULES) + message(STATUS "udev rules not supported on this platform. Hide this message via -DINSTALL_UDEV_RULES=Off") + endif(INSTALL_UDEV_RULES) +endif(SYSTEM_IS_LINUX)