Add USB API versioning

This commit is contained in:
Dominic Spill
2017-01-30 18:30:17 -07:00
parent 4ca37b8174
commit 255b7b4705
8 changed files with 133 additions and 68 deletions

View File

@ -55,7 +55,7 @@ uint8_t usb_descriptor_device[] = {
USB_MAX_PACKET0, // bMaxPacketSize0 USB_MAX_PACKET0, // bMaxPacketSize0
USB_WORD(USB_VENDOR_ID), // idVendor USB_WORD(USB_VENDOR_ID), // idVendor
USB_WORD(USB_PRODUCT_ID), // idProduct USB_WORD(USB_PRODUCT_ID), // idProduct
USB_WORD(0x0101), // bcdDevice USB_WORD(0x0102), // bcdDevice
0x01, // iManufacturer 0x01, // iManufacturer
0x02, // iProduct 0x02, // iProduct
0x04, // iSerialNumber 0x04, // iSerialNumber

View File

@ -31,6 +31,7 @@ int main(void)
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
uint8_t board_id = BOARD_ID_INVALID; uint8_t board_id = BOARD_ID_INVALID;
char version[255 + 1]; char version[255 + 1];
uint16_t usb_version;
read_partid_serialno_t read_partid_serialno; read_partid_serialno_t read_partid_serialno;
uint8_t operacakes[8]; uint8_t operacakes[8];
hackrf_device_list_t *list; hackrf_device_list_t *list;
@ -55,10 +56,11 @@ int main(void)
if (i > 0) if (i > 0)
printf("\n"); printf("\n");
printf("Found HackRF board %d:\n", i); printf("Found HackRF\n");
printf("Index: %d\n", i);
if (list->serial_numbers[i]) if (list->serial_numbers[i])
printf("USB descriptor string: %s\n", list->serial_numbers[i]); printf("Serial number: %s\n", list->serial_numbers[i]);
device = NULL; device = NULL;
result = hackrf_device_list_open(list, i, &device); result = hackrf_device_list_open(list, i, &device);
@ -83,7 +85,15 @@ int main(void)
hackrf_error_name(result), result); hackrf_error_name(result), result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Firmware Version: %s\n", version);
result = hackrf_usb_api_version_read(device, &usb_version);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_usb_api_version_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("Firmware Version: %s (API:%x.%02x)\n", version,
(usb_version>>8)&0xFF, usb_version&0xFF);
result = hackrf_board_partid_serialno_read(device, &read_partid_serialno); result = hackrf_board_partid_serialno_read(device, &read_partid_serialno);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
@ -101,16 +111,17 @@ int main(void)
read_partid_serialno.serial_no[3]); read_partid_serialno.serial_no[3]);
result = hackrf_get_operacake_boards(device, &operacakes[0]); result = hackrf_get_operacake_boards(device, &operacakes[0]);
if (result != HACKRF_SUCCESS) { if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) {
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n", fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result), result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
for(j=0; j<8; j++) { if(result == HACKRF_SUCCESS) {
if(operacakes[j] == 0) for(j=0; j<8; j++) {
break; if(operacakes[j] == 0)
printf("Operacake found, address: 0x%02x\n", operacakes[j]); break;
printf("Operacake found, address: 0x%02x\n", operacakes[j]);
}
} }
result = hackrf_close(device); result = hackrf_close(device);

View File

@ -39,14 +39,14 @@ static void usage() {
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n"); printf("\t-o, --address <n>: specify a particular operacake by address [default: 0x00]\n");
printf("\t-a <n>: set port A connection\n"); printf("\t-a <n>: set port A connection\n");
printf("\t-b <n>: set port B connection\n"); printf("\t-b <n>: set port B connection\n");
printf("\t-v, --verbose: verbose, list available operacake boards\n"); printf("\t-l, --list: list available operacake boards\n");
} }
static struct option long_options[] = { static struct option long_options[] = {
{ "device", no_argument, 0, 'd' }, { "device", no_argument, 0, 'd' },
{ "serial", no_argument, 0, 's' }, { "serial", no_argument, 0, 's' },
{ "address", no_argument, 0, 'o' }, { "address", no_argument, 0, 'o' },
{ "verbose", no_argument, 0, 'v' }, { "list", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' }, { "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 },
}; };
@ -69,8 +69,10 @@ int main(int argc, char** argv) {
int operacake_address = 0; int operacake_address = 0;
int port_a = 0; int port_a = 0;
int port_b = 0; int port_b = 0;
int verbose = 0; bool set_ports = false;
bool list = false;
uint8_t operacakes[8]; uint8_t operacakes[8];
uint8_t operacake_count = 0;
int i = 0; int i = 0;
hackrf_device* device = NULL; hackrf_device* device = NULL;
int option_index = 0; int option_index = 0;
@ -81,7 +83,7 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
while( (opt = getopt_long(argc, argv, "d:s:o:a:b:vh?", long_options, &option_index)) != EOF ) { while( (opt = getopt_long(argc, argv, "d:s:o:a:b:lh?", long_options, &option_index)) != EOF ) {
switch( opt ) { switch( opt ) {
case 'd': case 'd':
device_index = atoi(optarg); device_index = atoi(optarg);
@ -93,6 +95,7 @@ int main(int argc, char** argv) {
case 'o': case 'o':
operacake_address = atoi(optarg); operacake_address = atoi(optarg);
set_ports = true;
break; break;
case 'a': case 'a':
@ -103,8 +106,8 @@ int main(int argc, char** argv) {
port_b = atoi(optarg); port_b = atoi(optarg);
break; break;
case 'v': case 'l':
verbose = 1; list = true;
break; break;
case 'h': case 'h':
case '?': case '?':
@ -123,6 +126,12 @@ int main(int argc, char** argv) {
} }
} }
if(!(list || set_ports)) {
fprintf(stderr, "Specify either list or address option.\n");
usage();
return EXIT_FAILURE;
}
if(serial_number != NULL) { if(serial_number != NULL) {
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
} else { } else {
@ -139,20 +148,31 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
if(verbose) { if(list) {
hackrf_get_operacake_boards(device, operacakes); result = hackrf_get_operacake_boards(device, operacakes);
printf("Operacakes found:\n"); if (result != HACKRF_SUCCESS) {
for(i=0; i<8; i++) { fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
if(operacakes[i] !=0) hackrf_error_name(result), result);
printf("%d\n", operacakes[i]); return EXIT_FAILURE;
} }
printf("Operacakes found: ");
for(i=0; i<8; i++) {
if(operacakes[i] !=0) {
printf("\n%d", operacakes[i]);
operacake_count++;
}
}
if(!operacake_count)
printf("None");
printf("\n"); printf("\n");
} }
result = hackrf_set_operacake_ports(device, operacake_address, port_a, port_b); if(set_ports) {
if( result ) { result = hackrf_set_operacake_ports(device, operacake_address, port_a, port_b);
printf("hackrf_set_operacake_ports() failed: %s (%d)\n", hackrf_error_name(result), result); if( result ) {
return -1; printf("hackrf_set_operacake_ports() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
} }
result = hackrf_close(device); result = hackrf_close(device);
@ -160,8 +180,6 @@ int main(int argc, char** argv) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1; return -1;
} }
hackrf_exit(); hackrf_exit();
return 0; return 0;
} }

View File

@ -118,6 +118,7 @@ int main(int argc, char** argv)
bool write = false; bool write = false;
bool verbose = false; bool verbose = false;
bool reset = false; bool reset = false;
uint16_t usb_api;
while ((opt = getopt_long(argc, argv, "a:l:r:w:d:vRh?", long_options, while ((opt = getopt_long(argc, argv, "a:l:r:w:d:vRh?", long_options,
&option_index)) != EOF) { &option_index)) != EOF) {
@ -309,13 +310,22 @@ int main(int argc, char** argv)
} }
} }
if (fd != NULL) {
fclose(fd);
fd = NULL;
}
if(reset) { if(reset) {
result = hackrf_reset(device); result = hackrf_reset(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_reset() failed: %s (%d)\n", if (result == HACKRF_ERROR_USB_API_VERSION) {
hackrf_error_name(result), result); hackrf_usb_api_version_read(device, &usb_api);
fclose(fd); fprintf(stderr, "Reset is not supported by firmware API %x.%02x\n",
fd = NULL; (usb_api>>8)&0xFF, usb_api&0xFF);
} else {
fprintf(stderr, "hackrf_reset() failed: %s (%d)\n",
hackrf_error_name(result), result);
}
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -324,16 +334,9 @@ int main(int argc, char** argv)
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result), result);
fclose(fd);
fd = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
hackrf_exit(); hackrf_exit();
if (fd != NULL) {
fclose(fd);
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -448,7 +448,7 @@ int main(int argc, char** argv) {
result |= hackrf_set_lna_gain(device, lna_gain); result |= hackrf_set_lna_gain(device, lna_gain);
result |= hackrf_start_rx(device, rx_callback, NULL); result |= hackrf_start_rx(device, rx_callback, NULL);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result); fprintf(stderr, "hackrf_start_rx() failed: %s (%d)\n", hackrf_error_name(result), result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -457,7 +457,6 @@ int main(int argc, char** argv) {
if( result != HACKRF_SUCCESS ) { if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n", fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result), result);
usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -961,12 +961,10 @@ int main(int argc, char** argv) {
} }
} }
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", hw_sync);
hw_sync);
result = hackrf_set_hw_sync_mode(device, hw_sync ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF); result = hackrf_set_hw_sync_mode(device, hw_sync ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF);
if( result != HACKRF_SUCCESS ) { if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result); fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -1012,6 +1012,27 @@ int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version,
} }
} }
extern ADDAPI int ADDCALL hackrf_usb_api_version_read(hackrf_device* device,
uint16_t* version)
{
int result;
libusb_device* dev;
struct libusb_device_descriptor desc;
dev = libusb_get_device(device->usb_device);
result = libusb_get_device_descriptor(dev, &desc);
if (result < 0)
return HACKRF_ERROR_LIBUSB;
*version = desc.bcdDevice;
return HACKRF_SUCCESS;
}
#define USB_API_REQUIRED(device, version) \
uint16_t usb_version = 0; \
hackrf_usb_api_version_read(device, &usb_version); \
if(usb_version < version) \
return HACKRF_ERROR_USB_API_VERSION;
typedef struct { typedef struct {
uint32_t freq_mhz; /* From 0 to 6000+MHz */ uint32_t freq_mhz; /* From 0 to 6000+MHz */
uint32_t freq_hz; /* From 0 to 999999Hz */ uint32_t freq_hz; /* From 0 to 999999Hz */
@ -1577,26 +1598,6 @@ int ADDCALL hackrf_close(hackrf_device* device)
return result1; return result1;
} }
int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value) {
int result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE,
value,
0,
NULL,
0,
0
);
if( result != 0 )
{
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}
const char* ADDCALL hackrf_error_name(enum hackrf_error errcode) const char* ADDCALL hackrf_error_name(enum hackrf_error errcode)
{ {
switch(errcode) switch(errcode)
@ -1634,6 +1635,9 @@ const char* ADDCALL hackrf_error_name(enum hackrf_error errcode)
case HACKRF_ERROR_STREAMING_EXIT_CALLED: case HACKRF_ERROR_STREAMING_EXIT_CALLED:
return "HACKRF_ERROR_STREAMING_EXIT_CALLED"; return "HACKRF_ERROR_STREAMING_EXIT_CALLED";
case HACKRF_ERROR_USB_API_VERSION:
return "feature not supported by installed firmware";
case HACKRF_ERROR_OTHER: case HACKRF_ERROR_OTHER:
return "HACKRF_ERROR_OTHER"; return "HACKRF_ERROR_OTHER";
@ -1744,9 +1748,33 @@ uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz)
return p->bandwidth_hz; return p->bandwidth_hz;
} }
/* All features below require USB API version 0x1002 or higher) */
int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value) {
USB_API_REQUIRED(device, 0x0102)
int result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_SET_HW_SYNC_MODE,
value,
0,
NULL,
0,
0
);
if( result != 0 )
{
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}
/* Initialise sweep mode with alist of frequencies and dwell time in samples */ /* Initialise sweep mode with alist of frequencies and dwell time in samples */
int ADDCALL hackrf_init_sweep(hackrf_device* device, uint16_t* frequency_list, int length, uint32_t dwell_time) int ADDCALL hackrf_init_sweep(hackrf_device* device, uint16_t* frequency_list, int length, uint32_t dwell_time)
{ {
USB_API_REQUIRED(device, 0x0102)
int result, i; int result, i;
int size = length * sizeof(frequency_list[0]); int size = length * sizeof(frequency_list[0]);
@ -1776,6 +1804,7 @@ int ADDCALL hackrf_init_sweep(hackrf_device* device, uint16_t* frequency_list, i
*/ */
int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards) int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards)
{ {
USB_API_REQUIRED(device, 0x0102)
int result; int result;
result = libusb_control_transfer( result = libusb_control_transfer(
device->usb_device, device->usb_device,
@ -1802,6 +1831,7 @@ int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
uint8_t port_a, uint8_t port_a,
uint8_t port_b) uint8_t port_b)
{ {
USB_API_REQUIRED(device, 0x0102)
int result; int result;
/* Error checking */ /* Error checking */
if((port_a > OPERACAKE_PB4) || (port_b > OPERACAKE_PB4)) { if((port_a > OPERACAKE_PB4) || (port_b > OPERACAKE_PB4)) {
@ -1831,6 +1861,7 @@ int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
} }
int ADDCALL hackrf_reset(hackrf_device* device) { int ADDCALL hackrf_reset(hackrf_device* device) {
USB_API_REQUIRED(device, 0x0102)
int result = libusb_control_transfer( int result = libusb_control_transfer(
device->usb_device, device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,

View File

@ -59,6 +59,7 @@ enum hackrf_error {
HACKRF_ERROR_STREAMING_THREAD_ERR = -1002, HACKRF_ERROR_STREAMING_THREAD_ERR = -1002,
HACKRF_ERROR_STREAMING_STOPPED = -1003, HACKRF_ERROR_STREAMING_STOPPED = -1003,
HACKRF_ERROR_STREAMING_EXIT_CALLED = -1004, HACKRF_ERROR_STREAMING_EXIT_CALLED = -1004,
HACKRF_ERROR_USB_API_VERSION = -1005,
HACKRF_ERROR_OTHER = -9999, HACKRF_ERROR_OTHER = -9999,
}; };
@ -170,6 +171,7 @@ extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device,
extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value); extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value);
extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length); extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length);
extern ADDAPI int ADDCALL hackrf_usb_api_version_read(hackrf_device* device, uint16_t* version);
extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz);
extern ADDAPI int ADDCALL hackrf_set_freq_explicit(hackrf_device* device, extern ADDAPI int ADDCALL hackrf_set_freq_explicit(hackrf_device* device,
@ -198,9 +200,6 @@ extern ADDAPI int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t
/* antenna port power control */ /* antenna port power control */
extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value); extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value);
/* set hardware sync mode */
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode); 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_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_usb_board_id_name(enum hackrf_usb_board_id usb_board_id);
@ -210,6 +209,12 @@ extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_fil
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz); extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz);
/* Compute best default value depending on sample rate (auto filter) */ /* Compute best default value depending on sample rate (auto filter) */
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz); extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz);
/* All features below require USB API version 0x1002 or higher) */
/* set hardware sync mode */
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
/* Start scan mode */ /* Start scan mode */
extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device, extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
uint16_t* frequency_list, uint16_t* frequency_list,