diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index ace67e50..04993725 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -35,6 +35,7 @@ set(SRC_M4 hackrf_usb.c "${PATH_HACKRF_FIRMWARE_COMMON}/tuning.c" "${PATH_HACKRF_FIRMWARE_COMMON}/streaming.c" + m0_state.c "${PATH_HACKRF_FIRMWARE_COMMON}/usb.c" "${PATH_HACKRF_FIRMWARE_COMMON}/usb_request.c" "${PATH_HACKRF_FIRMWARE_COMMON}/usb_standard_request.c" diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 7fa95c74..f34318f5 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -49,6 +49,7 @@ #include "usb_api_transceiver.h" #include "usb_api_ui.h" #include "usb_bulk_buffer.h" +#include "m0_state.h" #include "cpld_xc2c.h" #include "portapack.h" @@ -114,6 +115,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_operacake_set_mode, usb_vendor_request_operacake_get_mode, usb_vendor_request_operacake_set_dwell_times, + usb_vendor_request_get_m0_state, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/m0_state.c b/firmware/hackrf_usb/m0_state.c new file mode 100644 index 00000000..ec113a87 --- /dev/null +++ b/firmware/hackrf_usb/m0_state.c @@ -0,0 +1,44 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "m0_state.h" + +#include +#include +#include + +usb_request_status_t usb_vendor_request_get_m0_state( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) + { + usb_transfer_schedule_block( + endpoint->in, + (void*) &m0_state, + sizeof(m0_state), + NULL, NULL); + usb_transfer_schedule_ack(endpoint->out); + return USB_REQUEST_STATUS_OK; + } else { + return USB_REQUEST_STATUS_OK; + } +} diff --git a/firmware/hackrf_usb/m0_state.h b/firmware/hackrf_usb/m0_state.h index 102a3ada..30950560 100644 --- a/firmware/hackrf_usb/m0_state.h +++ b/firmware/hackrf_usb/m0_state.h @@ -22,6 +22,9 @@ #ifndef __M0_STATE_H__ #define __M0_STATE_H__ +#include +#include + struct m0_state { uint32_t offset; uint32_t tx; @@ -33,4 +36,7 @@ struct m0_state { */ extern volatile struct m0_state m0_state; +usb_request_status_t usb_vendor_request_get_m0_state( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); + #endif/*__M0_STATE_H__*/ diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 1d11c275..aa40db3f 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -36,7 +36,7 @@ #define USB_PRODUCT_ID (0xFFFF) #endif -#define USB_API_VERSION (0x0105) +#define USB_API_VERSION (0x0106) #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 64623b6f..80863a88 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -377,6 +377,12 @@ int write_register(hackrf_device* device, uint8_t part, return HACKRF_ERROR_INVALID_PARAM; } +static void print_state(hackrf_m0_state *state) { + printf("M0 state:\n"); + printf("Offset: %u bytes\n", state->offset); + printf("TX: %u\n", state->tx); +} + static void usage() { printf("\nUsage:\n"); printf("\t-h, --help: this help\n"); @@ -388,12 +394,14 @@ static void usage() { printf("\t-m, --max2837: target MAX2837\n"); printf("\t-s, --si5351c: target SI5351C\n"); printf("\t-f, --rffc5072: target RFFC5072\n"); + printf("\t-S, --state: display M0 state\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"); printf("\thackrf_debug --si5351c -c # displays si5351c multisynth configuration\n"); printf("\thackrf_debug --rffc5072 -r # reads all rffc5072 registers\n"); printf("\thackrf_debug --max2837 -n 10 -w 22 # writes max2837 register 10 with 22 decimal\n"); + printf("\thackrf_debug --state # displays M0 state\n"); } static struct option long_options[] = { @@ -406,6 +414,7 @@ static struct option long_options[] = { { "max2837", no_argument, 0, 'm' }, { "si5351c", no_argument, 0, 's' }, { "rffc5072", no_argument, 0, 'f' }, + { "state", no_argument, 0, 'S' }, { "ui", required_argument, 0, 'u' }, { 0, 0, 0, 0 }, }; @@ -419,6 +428,7 @@ int main(int argc, char** argv) { bool read = false; bool write = false; bool dump_config = false; + bool dump_state = false; uint8_t part = PART_NONE; const char* serial_number = NULL; bool set_ui = false; @@ -430,7 +440,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfh?u:", long_options, &option_index)) != EOF ) { + while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfSh?u:", long_options, &option_index)) != EOF ) { switch( opt ) { case 'n': result = parse_int(optarg, ®ister_number); @@ -449,6 +459,10 @@ int main(int argc, char** argv) { dump_config = true; break; + case 'S': + dump_state = true; + break; + case 'd': serial_number = optarg; break; @@ -517,13 +531,13 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - if(!(write || read || dump_config || set_ui)) { + if(!(write || read || dump_config || dump_state || set_ui)) { fprintf(stderr, "Specify read, write, or config option.\n"); usage(); return EXIT_FAILURE; } - if(part == PART_NONE && !set_ui) { + if(part == PART_NONE && !set_ui && !dump_state) { fprintf(stderr, "Specify a part to read, write, or print config from.\n"); usage(); return EXIT_FAILURE; @@ -551,6 +565,16 @@ int main(int argc, char** argv) { si5351c_read_configuration(device); } + if(dump_state) { + hackrf_m0_state state; + result = hackrf_get_m0_state(device, &state); + if(result != HACKRF_SUCCESS) { + printf("hackrf_get_m0_state() failed: %s (%d)\n", hackrf_error_name(result), result); + return EXIT_FAILURE; + } + print_state(&state); + } + if(set_ui) { result = hackrf_set_ui_enable(device, ui_enable); } diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index a0642143..ea360184 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 6) +set(MINOR_VERSION 7) 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 70017a05..07ac2c70 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -92,6 +92,7 @@ typedef enum { 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_GET_M0_STATE = 41, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -1007,6 +1008,31 @@ int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number } } +int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* state) +{ + USB_API_REQUIRED(device, 0x0106) + int result; + + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_GET_M0_STATE, + 0, + 0, + (unsigned char*)state, + sizeof(hackrf_m0_state), + 0 + ); + + if( result < sizeof(hackrf_m0_state) ) + { + 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 4fb56363..63795f0e 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -155,6 +155,14 @@ typedef struct { uint8_t port; } hackrf_operacake_freq_range; +/** State of the SGPIO loop running on the M0 core. */ +typedef struct { + /** Current offset in the buffer. */ + uint32_t offset; + /** TX flag. */ + uint32_t tx; +} hackrf_m0_state; + struct hackrf_device_list { char **serial_numbers; enum hackrf_usb_board_id *usb_board_ids; @@ -193,6 +201,8 @@ extern ADDAPI int ADDCALL hackrf_stop_rx(hackrf_device* device); extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* tx_ctx); 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); + /* return HACKRF_TRUE if success */ extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device);