Merge pull request #158 from hessu/feature/multidev

Multiple device support - fixes issue #87
This commit is contained in:
Dominic Spill
2015-05-29 17:13:03 +01:00
9 changed files with 379 additions and 74 deletions

View File

@ -32,6 +32,9 @@
#include "usb.h"
#include "usb_standard_request.h"
#include <rom_iap.h>
#include "usb_descriptor.h"
#include "usb_device.h"
#include "usb_endpoint.h"
#include "usb_api_board_info.h"
@ -183,6 +186,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<USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) {
const uint_fast8_t nibble = (iap_cmd_res.status_res.iap_result[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 +219,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();

View File

@ -22,6 +22,7 @@
#include <stdint.h>
#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
};

View File

@ -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[];

View File

@ -80,6 +80,7 @@ static void usage()
{
printf("Usage:\n");
printf("\t-x <filename>: XSVF file to be written to CPLD.\n");
printf("\t-d <serialnumber>: 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);

View File

@ -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;

View File

@ -89,6 +89,7 @@ static void usage()
printf("\t-l, --length <n>: number of bytes to read (default: 0)\n");
printf("\t-r <filename>: Read data into file.\n");
printf("\t-w <filename>: Write data from file.\n");
printf("\t-d <serialnumber>: 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);

View File

@ -422,6 +422,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 <filename> # Receive data into file.\n");
printf("\t-t <filename> # Transmit data from file.\n");
printf("\t-w # Receive data into file with WAV header and automatic name.\n");
@ -477,6 +478,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 +488,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 +507,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);
@ -776,7 +782,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();

View File

@ -240,6 +240,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,28 +264,149 @@ 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?
@ -336,6 +461,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;
@ -1341,6 +1533,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) {

View File

@ -69,6 +69,12 @@ 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,
@ -91,6 +97,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 +118,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 +187,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) */