From 5abc39c53aff9744290fc3bddf0e95dcd685dc8e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 24 Dec 2021 09:56:52 +0000 Subject: [PATCH] Add USB requests and host support to set TX/RX shortfall limits. This adds `-T` and `-R` options to `hackrf_debug`, which set the TX underrun and RX overrun limits in bytes. --- firmware/hackrf_usb/hackrf_usb.c | 2 + firmware/hackrf_usb/usb_api_transceiver.c | 28 ++++++++++++ firmware/hackrf_usb/usb_api_transceiver.h | 4 ++ host/hackrf-tools/src/hackrf_debug.c | 39 +++++++++++++++-- host/libhackrf/src/hackrf.c | 52 +++++++++++++++++++++++ host/libhackrf/src/hackrf.h | 2 + 6 files changed, 124 insertions(+), 3 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index f34318f5..6dc6433a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -116,6 +116,8 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_operacake_get_mode, usb_vendor_request_operacake_set_dwell_times, usb_vendor_request_get_m0_state, + usb_vendor_request_set_tx_underrun_limit, + usb_vendor_request_set_rx_overrun_limit, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index c5e0a43f..f0f9b137 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -238,6 +238,8 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( } static volatile hw_sync_mode_t _hw_sync_mode = HW_SYNC_MODE_OFF; +static volatile uint32_t _tx_underrun_limit; +static volatile uint32_t _rx_overrun_limit; void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode) { _hw_sync_mode = new_hw_sync_mode; @@ -288,12 +290,14 @@ void transceiver_startup(const transceiver_mode_t mode) { led_on(LED2); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX); m0_state.mode = M0_MODE_RX; + m0_state.shortfall_limit = _rx_overrun_limit; break; case TRANSCEIVER_MODE_TX: led_off(LED2); led_on(LED3); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX); m0_state.mode = M0_MODE_TX; + m0_state.shortfall_limit = _tx_underrun_limit; break; default: break; @@ -338,6 +342,30 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode( } } +usb_request_status_t usb_vendor_request_set_tx_underrun_limit( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value; + _tx_underrun_limit = value; + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} + +usb_request_status_t usb_vendor_request_set_rx_overrun_limit( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value; + _rx_overrun_limit = value; + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} + void transceiver_bulk_transfer_complete(void *user_data, unsigned int bytes_transferred) { (void) user_data; diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index 126e2f7a..ef865b63 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -62,6 +62,10 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_request_status_t usb_vendor_request_set_hw_sync_mode( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_set_tx_underrun_limit( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_set_rx_overrun_limit( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); void request_transceiver_mode(transceiver_mode_t mode); void transceiver_startup(transceiver_mode_t mode); diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index 0077a3ec..38e832bd 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -405,6 +405,8 @@ static void usage() { printf("\t-s, --si5351c: target SI5351C\n"); printf("\t-f, --rffc5072: target RFFC5072\n"); printf("\t-S, --state: display M0 state\n"); + printf("\t-T, --tx-underrun-limit : set TX underrun limit in bytes (0 for no limit)\n"); + printf("\t-R, --rx-overrun-limit : set RX overrun limit in bytes (0 for no limit)\n"); printf("\t-u, --ui <1/0>: enable/disable UI\n"); printf("\nExamples:\n"); printf("\thackrf_debug --si5351c -n 0 -r # reads from si5351c register 0\n"); @@ -425,6 +427,8 @@ static struct option long_options[] = { { "si5351c", no_argument, 0, 's' }, { "rffc5072", no_argument, 0, 'f' }, { "state", no_argument, 0, 'S' }, + { "tx-underrun-limit", required_argument, 0, 'T' }, + { "rx-overrun-limit", required_argument, 0, 'R' }, { "ui", required_argument, 0, 'u' }, { 0, 0, 0, 0 }, }; @@ -443,6 +447,10 @@ int main(int argc, char** argv) { const char* serial_number = NULL; bool set_ui = false; uint32_t ui_enable; + uint32_t tx_limit; + uint32_t rx_limit; + bool set_tx_limit = false; + bool set_rx_limit = false; int result = hackrf_init(); if(result) { @@ -450,7 +458,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfSh?u:", long_options, &option_index)) != EOF ) { + while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfST:R:h?u:", long_options, &option_index)) != EOF ) { switch( opt ) { case 'n': result = parse_int(optarg, ®ister_number); @@ -473,6 +481,15 @@ int main(int argc, char** argv) { dump_state = true; break; + case 'T': + set_tx_limit = true; + result = parse_int(optarg, &tx_limit); + break; + case 'R': + set_rx_limit = true; + result = parse_int(optarg, &rx_limit); + break; + case 'd': serial_number = optarg; break; @@ -541,13 +558,13 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - if(!(write || read || dump_config || dump_state || set_ui)) { + if(!(write || read || dump_config || dump_state || set_tx_limit || set_rx_limit || set_ui)) { fprintf(stderr, "Specify read, write, or config option.\n"); usage(); return EXIT_FAILURE; } - if(part == PART_NONE && !set_ui && !dump_state) { + if(part == PART_NONE && !set_ui && !dump_state && !set_tx_limit && !set_rx_limit) { fprintf(stderr, "Specify a part to read, write, or print config from.\n"); usage(); return EXIT_FAILURE; @@ -575,6 +592,22 @@ int main(int argc, char** argv) { si5351c_read_configuration(device); } + if (set_tx_limit) { + result = hackrf_set_tx_underrun_limit(device, tx_limit); + if(result != HACKRF_SUCCESS) { + printf("hackrf_set_tx_underrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result); + return EXIT_FAILURE; + } + } + + if (set_rx_limit) { + result = hackrf_set_rx_overrun_limit(device, rx_limit); + if(result != HACKRF_SUCCESS) { + printf("hackrf_set_rx_overrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result); + return EXIT_FAILURE; + } + } + if(dump_state) { hackrf_m0_state state; result = hackrf_get_m0_state(device, &state); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 07ac2c70..0ad5557b 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -93,6 +93,8 @@ typedef enum { HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39, HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES = 40, HACKRF_VENDOR_REQUEST_GET_M0_STATE = 41, + HACKRF_VENDOR_REQUEST_SET_TX_UNDERRUN_LIMIT = 42, + HACKRF_VENDOR_REQUEST_SET_RX_OVERRUN_LIMIT = 43, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -1033,6 +1035,56 @@ int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* state) } } +int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value) +{ + USB_API_REQUIRED(device, 0x0106) + int result; + + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SET_TX_UNDERRUN_LIMIT, + value & 0xffff, + value >> 16, + NULL, + 0, + 0 + ); + + if( result != 0 ) + { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + +int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value) +{ + USB_API_REQUIRED(device, 0x0106) + int result; + + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SET_RX_OVERRUN_LIMIT, + value & 0xffff, + value >> 16, + NULL, + 0, + 0 + ); + + if( result != 0 ) + { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + int ADDCALL hackrf_spiflash_erase(hackrf_device* device) { int result; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 5bd23aed..bd74857d 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -210,6 +210,8 @@ extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_b extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device); extern ADDAPI int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* value); +extern ADDAPI int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value); +extern ADDAPI int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value); /* return HACKRF_TRUE if success */ extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device);