From 856d9a635453cd9a391df8b0c231824f4d4a4d9b Mon Sep 17 00:00:00 2001 From: Heikki Hannikainen Date: Tue, 24 Feb 2015 00:33:26 +0200 Subject: [PATCH] libhackrf: hackrf_device_list() API for device enumeration and opening of any device (with or without serial numbers). hackrf_info uses hackrf_device_list to list devices, with or without serial number API support. --- host/hackrf-tools/src/hackrf_info.c | 105 ++++++++++++---------- host/libhackrf/src/hackrf.c | 131 +++++++++++++++++++++++----- host/libhackrf/src/hackrf.h | 16 ++++ 3 files changed, 183 insertions(+), 69 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_info.c b/host/hackrf-tools/src/hackrf_info.c index 47ab9264..571c546b 100644 --- a/host/hackrf-tools/src/hackrf_info.c +++ b/host/hackrf-tools/src/hackrf_info.c @@ -33,6 +33,8 @@ int main(int argc, char** argv) 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 +42,68 @@ int main(int argc, char** argv) hackrf_error_name(result), result); return EXIT_FAILURE; } - - result = hackrf_open(NULL, &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"); + + 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; + } + printf("Found HackRF board %d:\n", i); + + 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); + return EXIT_FAILURE; + } + } + hackrf_exit(); return EXIT_SUCCESS; diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index a61b54f8..8c83298a 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -263,6 +263,66 @@ int ADDCALL hackrf_exit(void) #include #include +hackrf_device_list_t* ADDCALL hackrf_device_list() +{ + libusb_device_handle* usb_device = NULL; + hackrf_device_list_t* list = calloc(1, sizeof(*list)); + 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->product_ids = calloc(list->usb_devicecount, sizeof(int)); + list->usb_device_index = calloc(list->usb_devicecount, sizeof(int)); + + for (ssize_t 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->product_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->product_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; @@ -329,33 +389,10 @@ libusb_device_handle* hackrf_open_usb(const char* const desired_serial_number) return usb_device; } -int ADDCALL hackrf_open(const char* const desired_serial_number, hackrf_device** 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; - } - - if( desired_serial_number ) - { - usb_device = hackrf_open_usb(desired_serial_number); - } else { - 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? @@ -410,6 +447,52 @@ int ADDCALL hackrf_open(const char* const desired_serial_number, hackrf_device** return HACKRF_SUCCESS; } +int ADDCALL hackrf_open(const char* const desired_serial_number, hackrf_device** device) +{ + libusb_device_handle* usb_device; + + if( device == NULL ) + { + return HACKRF_ERROR_INVALID_PARAM; + } + + if( desired_serial_number ) + { + usb_device = hackrf_open_usb(desired_serial_number); + } else { + 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_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; + } + + if( libusb_open(list->usb_devices[idx], &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; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 6b615647..08afe3c9 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -91,6 +91,18 @@ typedef struct { uint32_t serial_no[4]; } read_partid_serialno_t; + +struct hackrf_device_list { + char **serial_numbers; + int *product_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,6 +112,10 @@ 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(const char* const desired_serial_number, hackrf_device** device); extern ADDAPI int ADDCALL hackrf_close(hackrf_device* device);