Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions firmware/common/radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,19 @@ void radio_init(radio_t* const radio)
radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX;
radio->config[RADIO_BANK_IDLE][RADIO_BIAS_TEE] = false;
radio->regs_dirty = 0;
radio->regs_locked = 0;
}

static inline void mark_dirty(radio_t* const radio, radio_register_t reg)
{
radio->regs_dirty |= (1 << reg);
}

static inline bool check_locked(radio_t* const radio, radio_register_t reg)
{
return radio->regs_locked & (1 << reg);
}

radio_error_t radio_reg_write(
radio_t* const radio,
const radio_register_bank_t bank,
Expand All @@ -77,6 +83,10 @@ radio_error_t radio_reg_write(
return RADIO_ERR_INVALID_REGISTER;
}

if (check_locked(radio, reg)) {
return RADIO_ERR_LOCKED_REGISTER;
}

switch (bank) {
case RADIO_BANK_REQUESTED:
mark_dirty(radio, reg);
Expand Down Expand Up @@ -107,6 +117,20 @@ uint64_t radio_reg_read(
return radio->config[bank][reg];
}

radio_error_t radio_reg_lock(
radio_t* const radio,
const radio_register_t reg,
const bool locked)
{
if (reg > RADIO_NUM_REGS) {
return RADIO_ERR_INVALID_REGISTER;
}

radio->regs_locked = (radio->regs_locked & ~(1 << reg)) | (locked << reg);

return RADIO_OK;
}

static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank)
{
const uint64_t requested = bank[RADIO_OPMODE];
Expand Down
11 changes: 11 additions & 0 deletions firmware/common/radio.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef enum {
RADIO_ERR_INVALID_PARAM = -2,
RADIO_ERR_INVALID_BANK = -3,
RADIO_ERR_INVALID_REGISTER = -4,
RADIO_ERR_LOCKED_REGISTER = -5,
RADIO_ERR_UNSUPPORTED_OPERATION = -10,
RADIO_ERR_UNIMPLEMENTED = -19,
RADIO_ERR_OTHER = -9999,
Expand Down Expand Up @@ -231,6 +232,7 @@ typedef struct {
radio_config_mode_t config_mode;
uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS];
volatile uint32_t regs_dirty;
uint32_t regs_locked;
update_fn update_cb;
} radio_t;

Expand All @@ -254,6 +256,15 @@ uint64_t radio_reg_read(
const radio_register_bank_t bank,
const radio_register_t reg);

/**
* Lock a register. Prevents any future calls to `radio_reg_write`
* from overwriting the current stored value of the register.
*/
radio_error_t radio_reg_lock(
radio_t* const radio,
const radio_register_t reg,
const bool locked);

/**
* Apply changes requested in RADIO_BANK_REQUESTED.
* Return true if any changes were applied.
Expand Down
1 change: 1 addition & 0 deletions firmware/hackrf_usb/hackrf_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
usb_vendor_request_write_radio_reg,
usb_vendor_request_read_radio_reg,
usb_vendor_request_get_buffer_size,
usb_vendor_request_lock_radio_reg,
};

static const uint32_t vendor_request_handler_count =
Expand Down
17 changes: 17 additions & 0 deletions firmware/hackrf_usb/usb_api_register.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,20 @@ usb_request_status_t usb_vendor_request_read_radio_reg(
}
return USB_REQUEST_STATUS_OK;
}

usb_request_status_t usb_vendor_request_lock_radio_reg(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
uint8_t reg = endpoint->setup.index;
bool locked = endpoint->setup.value != 0 ? true : false;
if (reg >= RADIO_NUM_REGS) {
return USB_REQUEST_STATUS_STALL;
}
radio_reg_lock(&radio, reg, locked);
usb_transfer_schedule_ack(endpoint->in);
}

return USB_REQUEST_STATUS_OK;
}
3 changes: 3 additions & 0 deletions firmware/hackrf_usb/usb_api_register.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ usb_request_status_t usb_vendor_request_write_radio_reg(
usb_request_status_t usb_vendor_request_read_radio_reg(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_lock_radio_reg(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
2 changes: 1 addition & 1 deletion firmware/hackrf_usb/usb_descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#define USB_VENDOR_ID (0x1D50)

#define USB_API_VERSION (0x0113)
#define USB_API_VERSION (0x0114)

#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)

Expand Down
65 changes: 60 additions & 5 deletions host/hackrf-tools/src/hackrf_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,30 @@ int radio_write_register(
return result;
}

int radio_lock_register(
hackrf_device* device,
const uint16_t register_number,
const bool register_locked)
{
int result = HACKRF_SUCCESS;
result = hackrf_radio_lock_register(
device,
(uint8_t) register_number,
register_locked);

if (result == HACKRF_SUCCESS) {
printf("register [%2d] -> %s\n",
register_number,
register_locked ? "locked" : "unlocked");
} else {
printf("hackrf_radio_lock_register() failed: %s (%d)\n",
hackrf_error_name(result),
result);
}

return result;
}

int read_register(
hackrf_device* device,
uint8_t part,
Expand Down Expand Up @@ -621,6 +645,20 @@ int write_register(
return HACKRF_ERROR_INVALID_PARAM;
}

int lock_register(
hackrf_device* device,
uint8_t part,
const uint16_t register_number,
const bool register_locked)
{
switch (part) {
case PART_RADIO:
return radio_lock_register(device, register_number, register_locked);
default:
return HACKRF_ERROR_INVALID_PARAM;
}
}

static const char* mode_name(uint32_t mode)
{
const char* mode_names[] = {"IDLE", "WAIT", "RX", "TX_START", "TX_RUN"};
Expand Down Expand Up @@ -675,6 +713,7 @@ static void usage()
printf("\t-n, --register <n>: set register number for read/write operations\n");
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
printf("\t-L, --lock <state>: lock register specified by last -n argument (0 for unlocked, 1 for locked)\n");
printf("\t-c, --config: print SI5351C multisynth configuration information\n");
printf("\t-d, --device <s>: specify a particular device by serial number\n");
printf("\t-m, --max283x: target MAX283x\n");
Expand Down Expand Up @@ -709,6 +748,7 @@ static struct option long_options[] = {
{"register", required_argument, 0, 'n'},
{"write", required_argument, 0, 'w'},
{"read", no_argument, 0, 'r'},
{"lock", required_argument, 0, 'L'},
{"device", required_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"max2837", no_argument, 0, 'm'},
Expand Down Expand Up @@ -740,10 +780,12 @@ int main(int argc, char** argv)
int bank = -1;
uint64_t register_number = REGISTER_INVALID;
uint64_t register_value;
uint64_t register_locked;
hackrf_device* device = NULL;
int option_index = 0;
bool read = false;
bool write = false;
bool lock = false;
bool dump_config = false;
bool dump_state = false;
uint8_t part = PART_NONE;
Expand Down Expand Up @@ -782,7 +824,7 @@ int main(int argc, char** argv)
while ((opt = getopt_long(
argc,
argv,
"b:n:rw:d:cmsfgi1:2:C:N:P:ST:R:h?u:l:ta:o",
"b:n:rw:l:d:cmsfgi1:2:C:N:P:ST:R:h?u:l:ta:o",
long_options,
&option_index)) != EOF) {
switch (opt) {
Expand All @@ -805,6 +847,11 @@ int main(int argc, char** argv)
read = true;
break;

case 'L':
lock = true;
result = parse_int(optarg, &register_locked);
break;

case 'c':
dump_config = true;
break;
Expand Down Expand Up @@ -931,8 +978,8 @@ int main(int argc, char** argv)
}
}

if (write && read) {
fprintf(stderr, "Read and write options are mutually exclusive.\n");
if ((write && read) || (lock && write) || (lock && read)) {
fprintf(stderr, "Read, write and lock options are mutually exclusive.\n");
usage();
return EXIT_FAILURE;
}
Expand All @@ -949,6 +996,10 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}

if (lock && part != PART_RADIO) {
fprintf(stderr, "Lock option is only valid for radio.\n");
}

if ((bank > -1) && (part != PART_RADIO)) {
fprintf(stderr, "Bank valid only for radio.\n");
usage();
Expand All @@ -959,11 +1010,11 @@ int main(int argc, char** argv)
bank = 0;
}

if (!(write || read || dump_config || dump_state || set_tx_limit ||
if (!(write || read || lock || dump_config || dump_state || set_tx_limit ||
set_rx_limit || set_ui || set_leds || set_p1 || set_p2 || set_clkin ||
set_narrowband || set_fpga_bitstream || read_selftest || test_rtc_osc ||
read_adc)) {
fprintf(stderr, "Specify read, write, or config option.\n");
fprintf(stderr, "Specify read, write, lock, or config option.\n");
usage();
return EXIT_FAILURE;
}
Expand Down Expand Up @@ -1016,6 +1067,10 @@ int main(int argc, char** argv)
}
}

if (lock) {
result = lock_register(device, part, register_number, register_locked);
}

if (dump_config) {
si5351c_read_configuration(device);
}
Expand Down
28 changes: 28 additions & 0 deletions host/libhackrf/src/hackrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ typedef enum {
HACKRF_VENDOR_REQUEST_RADIO_WRITE_REG = 59,
HACKRF_VENDOR_REQUEST_RADIO_READ_REG = 60,
HACKRF_VENDOR_REQUEST_GET_BUFFER_SIZE = 61,
HACKRF_VENDOR_REQUEST_RADIO_LOCK_REG = 62,
} hackrf_vendor_request;

#define USB_CONFIG_STANDARD 0x1
Expand Down Expand Up @@ -3575,6 +3576,33 @@ int ADDCALL hackrf_radio_write_register(
}
}

int ADDCALL hackrf_radio_lock_register(
hackrf_device* device,
const uint8_t register_number,
const bool register_locked)
{
USB_API_REQUIRED(device, 0x0114);
int result;

result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_RADIO_LOCK_REG,
register_locked,
register_number,
NULL,
0,
DEFAULT_REQUEST_TIMEOUT);

if (result != 0) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
}

return HACKRF_SUCCESS;
}

#ifdef __cplusplus
} // __cplusplus defined.
#endif
14 changes: 14 additions & 0 deletions host/libhackrf/src/hackrf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,20 @@ extern ADDAPI int ADDCALL hackrf_radio_write_register(
const uint8_t register_number,
const uint64_t value);

/**
* Lock or unlock a radio configuration register.
*
* @param[in] device device to write
* @param[in] register_number register number to mask
* @param[out] locked locked state for the register
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup debug
*/
extern ADDAPI int ADDCALL hackrf_radio_lock_register(
hackrf_device* device,
const uint8_t register_number,
const bool register_locked);

#ifdef __cplusplus
} // __cplusplus defined.
#endif
Loading