From e41314f130784454df1c55484fbfec53f8a40508 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Mon, 9 Aug 2021 22:51:30 +0100 Subject: [PATCH] operacake: add API function to set port dwell times --- firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_operacake.c | 32 +++++++++++++ firmware/hackrf_usb/usb_api_operacake.h | 3 ++ host/hackrf-tools/src/hackrf_operacake.c | 57 +++++++++++++++++++++++- host/libhackrf/src/hackrf.c | 38 ++++++++++++++++ host/libhackrf/src/hackrf.h | 7 +++ 6 files changed, 137 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 8e3e2840..b2062314 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -113,6 +113,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_set_ui_enable, usb_vendor_request_operacake_set_mode, usb_vendor_request_operacake_get_mode, + usb_vendor_request_operacake_set_dwell_times, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/usb_api_operacake.c b/firmware/hackrf_usb/usb_api_operacake.c index a04beab2..00374522 100644 --- a/firmware/hackrf_usb/usb_api_operacake.c +++ b/firmware/hackrf_usb/usb_api_operacake.c @@ -24,6 +24,8 @@ #include #include +#include +#include usb_request_status_t usb_vendor_request_operacake_get_boards( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -118,3 +120,33 @@ usb_request_status_t usb_vendor_request_operacake_get_mode( } return USB_REQUEST_STATUS_OK; } + +static struct operacake_dwell_times dwell_times[SCT_EVENT_COUNT]; +usb_request_status_t usb_vendor_request_operacake_set_dwell_times( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) +{ + uint16_t count; + uint32_t dwell; + uint8_t port; + + if (stage == USB_TRANSFER_STAGE_SETUP) { + count = endpoint->setup.length / 5; + if((count == 0) || (count > SCT_EVENT_COUNT)) { + return USB_REQUEST_STATUS_STALL; + } + usb_transfer_schedule_block(endpoint->out, &data, + endpoint->setup.length, NULL, NULL); + } else if (stage == USB_TRANSFER_STAGE_DATA) { + count = endpoint->setup.length / 5; + + for(int i = 0; i < count; i++) { + dwell = data[(i*5)+0] | (data[(i*5)+1] << 8) | (data[(i*5)+2] << 16) | (data[(i*5)+3] << 24); + port = data[(i*5)+4]; + dwell_times[i].dwell = dwell; + dwell_times[i].port = port; + } + operacake_sctimer_set_dwell_times(dwell_times, count); + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} diff --git a/firmware/hackrf_usb/usb_api_operacake.h b/firmware/hackrf_usb/usb_api_operacake.h index d41d4b12..c39cebee 100644 --- a/firmware/hackrf_usb/usb_api_operacake.h +++ b/firmware/hackrf_usb/usb_api_operacake.h @@ -43,4 +43,7 @@ usb_request_status_t usb_vendor_request_operacake_set_mode( usb_request_status_t usb_vendor_request_operacake_get_mode( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_operacake_set_dwell_times( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); + #endif /* end of include guard: __USB_API_OPERACAKE_H__ */ diff --git a/host/hackrf-tools/src/hackrf_operacake.c b/host/hackrf-tools/src/hackrf_operacake.c index ae71a1c4..e222e20d 100644 --- a/host/hackrf-tools/src/hackrf_operacake.c +++ b/host/hackrf-tools/src/hackrf_operacake.c @@ -51,6 +51,7 @@ static void usage() { printf("\t-a : set port A connection\n"); printf("\t-b : set port B connection\n"); printf("\t-f : automatically assign for range in MHz\n"); + printf("\t-t : in time-switching mode, dwell on for samples. This argument can be repeated to specify a list of ports.\n"); printf("\t-l, --list: list available operacake boards\n"); printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\n"); } @@ -82,6 +83,17 @@ int parse_uint16(char* const s, uint16_t* const value) { } } +int parse_uint32(char* const s, uint32_t* const value) { + char* s_end = s; + const long long_value = strtol(s, &s_end, 10); + if( (s != s_end) && (*s_end == 0) ) { + *value = (uint32_t)long_value; + return HACKRF_SUCCESS; + } else { + return HACKRF_ERROR_INVALID_PARAM; + } +} + int parse_port(char* str, uint8_t* port) { uint16_t tmp_port; int result; @@ -142,6 +154,23 @@ int parse_range(char* s, hackrf_oc_range* range) { return result; } +int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) { + int result; + char port[16]; + float dwell; + + // Read dwell as a float here to support scientific notation (e.g: 1e6) + if (sscanf(s, "%15[^:]:%f", port, &dwell) == 2) { + result = parse_port(port, &dwell_time->port); + if (result != HACKRF_SUCCESS) + return result; + + dwell_time->dwell = (uint32_t)dwell; + return HACKRF_SUCCESS; + } + return HACKRF_ERROR_INVALID_PARAM; +} + int main(int argc, char** argv) { int opt; const char* serial_number = NULL; @@ -159,7 +188,9 @@ int main(int argc, char** argv) { hackrf_device* device = NULL; int option_index = 0; hackrf_oc_range ranges[MAX_FREQ_RANGES]; + hackrf_operacake_dwell_time dwell_times[HACKRF_OPERACAKE_MAX_DWELL_TIMES]; uint8_t range_idx = 0; + uint8_t dwell_idx = 0; int result = hackrf_init(); if( result ) { @@ -167,7 +198,7 @@ int main(int argc, char** argv) { return -1; } - while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:hg?", long_options, &option_index)) != EOF ) { + while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:hg?", long_options, &option_index)) != EOF ) { switch( opt ) { case 'd': serial_number = optarg; @@ -224,6 +255,22 @@ int main(int argc, char** argv) { range_idx++; break; + case 't': + if(HACKRF_OPERACAKE_MAX_DWELL_TIMES == dwell_idx) { + fprintf(stderr, + "argument error: specify a maximum of %u dwell times.\n", + HACKRF_OPERACAKE_MAX_DWELL_TIMES); + usage(); + return EXIT_FAILURE; + } + result = parse_dwell(optarg, &dwell_times[dwell_idx]); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "failed to parse dwell time\n"); + return EXIT_FAILURE; + } + dwell_idx++; + break; + case 'a': result = parse_port(optarg, &port_a); if (result != HACKRF_SUCCESS) { @@ -417,6 +464,14 @@ int main(int argc, char** argv) { } } + if(dwell_idx) { + result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx); + if( result ) { + printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result); + return -1; + } + } + result = hackrf_close(device); if( result ) { printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 15549d4e..489af183 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -91,6 +91,7 @@ typedef enum { HACKRF_VENDOR_REQUEST_UI_ENABLE = 37, HACKRF_VENDOR_REQUEST_OPERACAKE_SET_MODE = 38, HACKRF_VENDOR_REQUEST_OPERACAKE_GET_MODE = 39, + HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES = 40, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -2289,6 +2290,43 @@ int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges, } } +#define DWELL_TIME_SIZE 5 +static uint8_t dwell_data[DWELL_TIME_SIZE*HACKRF_OPERACAKE_MAX_DWELL_TIMES]; +int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count) +{ + USB_API_REQUIRED(device, 0x0105) + + if (count > HACKRF_OPERACAKE_MAX_DWELL_TIMES) { + return HACKRF_ERROR_INVALID_PARAM; + } + + int i; + for (i = 0; i < count; i++) { + *(uint32_t*)&dwell_data[i*DWELL_TIME_SIZE] = TO_LE(dwell_times[i].dwell); + dwell_data[(i*DWELL_TIME_SIZE)+4] = dwell_times[i].port; + } + + int data_len = count * DWELL_TIME_SIZE; + int result; + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_OPERACAKE_SET_DWELL_TIMES, + 0, + 0, + dwell_data, + data_len, + 0 + ); + + if (result < data_len) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value) { USB_API_REQUIRED(device, 0x0103) diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 7055fdff..ae5fe1b1 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -52,6 +52,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #define MAX_SWEEP_RANGES 10 #define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF #define HACKRF_OPERACAKE_MAX_BOARDS 8 +#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16 enum hackrf_error { HACKRF_SUCCESS = 0, @@ -138,6 +139,11 @@ typedef struct { uint32_t serial_no[4]; } read_partid_serialno_t; +typedef struct { + uint32_t dwell; + uint8_t port; +} hackrf_operacake_dwell_time; + struct hackrf_device_list { char **serial_numbers; @@ -260,6 +266,7 @@ extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device, uint8_t address, uint8_t port_a, uint8_t port_b); +extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count); extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);