From 173612ac77215e0fb5d9d8db7fa9b9ae04bcbd2e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 18 Dec 2022 07:22:17 -0500 Subject: [PATCH] add --led option to hackrf_debug and corresponding changes to libhackrf and firmware --- firmware/common/hackrf_core.c | 11 +++++++++++ firmware/common/hackrf_core.h | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_register.c | 11 +++++++++++ firmware/hackrf_usb/usb_api_register.h | 3 +++ firmware/hackrf_usb/usb_descriptor.c | 2 +- host/hackrf-tools/src/hackrf_debug.c | 25 ++++++++++++++++++++++--- host/libhackrf/CMakeLists.txt | 2 +- host/libhackrf/src/hackrf.c | 23 +++++++++++++++++++++++ host/libhackrf/src/hackrf.h | 2 ++ 10 files changed, 76 insertions(+), 5 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 6fa850a6..bc0bb4b3 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -957,6 +957,17 @@ void led_toggle(const led_t led) gpio_toggle(&gpio_led[led]); } +void set_leds(const uint8_t state) +{ + int num_leds = 3; +#ifdef RAD1O + num_leds = 4; +#endif + for (int i = 0; i < num_leds; i++) { + gpio_write(&gpio_led[i], ((state >> i) & 1) == 1); + } +} + void hw_sync_enable(const hw_sync_mode_t hw_sync_mode) { gpio_write(&gpio_hw_sync_enable, hw_sync_mode == 1); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index a32b2c9f..e24007eb 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -300,6 +300,7 @@ typedef enum { void led_on(const led_t led); void led_off(const led_t led); void led_toggle(const led_t led); +void set_leds(const uint8_t state); void hw_sync_enable(const hw_sync_mode_t hw_sync_mode); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index a0604c48..56dd3ebc 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -122,6 +122,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_get_clkin_status, usb_vendor_request_read_board_rev, usb_vendor_request_read_supported_platform, + usb_vendor_request_set_leds, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 1a7484e9..9741fd65 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -197,3 +197,14 @@ usb_request_status_t usb_vendor_request_get_clkin_status( } return USB_REQUEST_STATUS_OK; } + +usb_request_status_t usb_vendor_request_set_leds( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) { + set_leds(endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index 2ab6525e..f29ad050 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -51,5 +51,8 @@ usb_request_status_t usb_vendor_request_set_clkout_enable( usb_request_status_t usb_vendor_request_get_clkin_status( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_set_leds( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage); #endif /* end of include guard: __USB_API_REGISTER_H__ */ diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 7d18e4f6..ecf094d9 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -37,7 +37,7 @@ #define USB_PRODUCT_ID (0xFFFF) #endif -#define USB_API_VERSION (0x0106) +#define USB_API_VERSION (0x0107) #define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index dc25d4e5..9d3c15cc 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -473,6 +473,7 @@ static void usage() 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("\t-l, --leds : configure LED state (0 for all off, 1 for default)\n"); printf("\nExamples:\n"); printf("\thackrf_debug --si5351c -n 0 -r # reads from si5351c register 0\n"); printf("\thackrf_debug --si5351c -c # displays si5351c multisynth configuration\n"); @@ -495,6 +496,7 @@ static struct option long_options[] = { {"tx-underrun-limit", required_argument, 0, 'T'}, {"rx-overrun-limit", required_argument, 0, 'R'}, {"ui", required_argument, 0, 'u'}, + {"leds", required_argument, 0, 'l'}, {0, 0, 0, 0}, }; @@ -513,6 +515,8 @@ int main(int argc, char** argv) const char* serial_number = NULL; bool set_ui = false; uint32_t ui_enable; + bool set_leds = false; + uint32_t led_state; uint32_t tx_limit; uint32_t rx_limit; bool set_tx_limit = false; @@ -529,7 +533,7 @@ int main(int argc, char** argv) while ((opt = getopt_long( argc, argv, - "n:rw:d:cmsfST:R:h?u:", + "n:rw:d:cmsfST:R:h?u:l:", long_options, &option_index)) != EOF) { switch (opt) { @@ -596,6 +600,11 @@ int main(int argc, char** argv) result = parse_int(optarg, &ui_enable); break; + case 'l': + set_leds = true; + result = parse_int(optarg, &led_state); + break; + case 'h': case '?': usage(); @@ -634,14 +643,14 @@ int main(int argc, char** argv) } if (!(write || read || dump_config || dump_state || set_tx_limit || - set_rx_limit || set_ui)) { + set_rx_limit || set_ui || set_leds)) { fprintf(stderr, "Specify read, write, or config option.\n"); usage(); return EXIT_FAILURE; } if (part == PART_NONE && !set_ui && !dump_state && !set_tx_limit && - !set_rx_limit) { + !set_rx_limit && !set_leds) { fprintf(stderr, "Specify a part to read, write, or print config from.\n"); usage(); return EXIT_FAILURE; @@ -707,6 +716,16 @@ int main(int argc, char** argv) result = hackrf_set_ui_enable(device, ui_enable); } + if (set_leds) { + if (led_state > 0xf) { + fprintf(stderr, + "Specify LED state bit field (0 for all off, 1 for default).\n"); + usage(); + return EXIT_FAILURE; + } + result = hackrf_set_leds(device, led_state); + } + result = hackrf_close(device); if (result) { printf("hackrf_close() failed: %s (%d)\n", diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index ea360184..322970e7 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) project(libhackrf C) set(MAJOR_VERSION 0) -set(MINOR_VERSION 7) +set(MINOR_VERSION 8) set(PACKAGE libhackrf) set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}) set(VERSION ${VERSION_STRING}) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 30226162..582d4914 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -102,6 +102,7 @@ typedef enum { HACKRF_VENDOR_REQUEST_GET_CLKIN_STATUS = 44, HACKRF_VENDOR_REQUEST_BOARD_REV_READ = 45, HACKRF_VENDOR_REQUEST_SUPPORTED_PLATFORM_READ = 46, + HACKRF_VENDOR_REQUEST_SET_LEDS = 47, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -2904,6 +2905,28 @@ int ADDCALL hackrf_supported_platform_read(hackrf_device* device, uint32_t* valu } } +int ADDCALL hackrf_set_leds(hackrf_device* device, const uint8_t state) +{ + USB_API_REQUIRED(device, 0x0107) + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SET_LEDS, + state, + 0, + NULL, + 0, + 0); + + if (result != 0) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + #ifdef __cplusplus } // __cplusplus defined. #endif diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 3bfc128f..759ab725 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -514,6 +514,8 @@ extern ADDAPI int ADDCALL hackrf_supported_platform_read( hackrf_device* device, uint32_t* value); +extern ADDAPI int ADDCALL hackrf_set_leds(hackrf_device* device, const uint8_t state); + #ifdef __cplusplus } // __cplusplus defined. #endif