Skip to content

Commit e88882b

Browse files
committed
radio: Add support for locking radio registers
1 parent 74d0437 commit e88882b

9 files changed

Lines changed: 159 additions & 6 deletions

File tree

firmware/common/radio.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,19 @@ void radio_init(radio_t* const radio)
5959
radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX;
6060
radio->config[RADIO_BANK_IDLE][RADIO_BIAS_TEE] = false;
6161
radio->regs_dirty = 0;
62+
radio->regs_locked = 0;
6263
}
6364

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

70+
static inline bool check_locked(radio_t* const radio, radio_register_t reg)
71+
{
72+
return radio->regs_locked & (1 << reg);
73+
}
74+
6975
radio_error_t radio_reg_write(
7076
radio_t* const radio,
7177
const radio_register_bank_t bank,
@@ -76,6 +82,10 @@ radio_error_t radio_reg_write(
7682
return RADIO_ERR_INVALID_REGISTER;
7783
}
7884

85+
if (check_locked(radio, reg)) {
86+
return RADIO_ERR_LOCKED_REGISTER;
87+
}
88+
7989
switch (bank) {
8090
case RADIO_BANK_ACTIVE:
8191
mark_dirty(radio, reg);
@@ -106,6 +116,20 @@ uint64_t radio_reg_read(
106116
return radio->config[bank][reg];
107117
}
108118

119+
radio_error_t radio_reg_lock(
120+
radio_t* const radio,
121+
const radio_register_t reg,
122+
const bool locked)
123+
{
124+
if (reg > RADIO_NUM_REGS) {
125+
return RADIO_ERR_INVALID_REGISTER;
126+
}
127+
128+
radio->regs_locked = (radio->regs_locked & ~(1 << reg)) | (locked << reg);
129+
130+
return RADIO_OK;
131+
}
132+
109133
static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank)
110134
{
111135
const uint64_t requested = bank[RADIO_OPMODE];

firmware/common/radio.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef enum {
3434
RADIO_ERR_INVALID_PARAM = -2,
3535
RADIO_ERR_INVALID_BANK = -3,
3636
RADIO_ERR_INVALID_REGISTER = -4,
37+
RADIO_ERR_LOCKED_REGISTER = -5,
3738
RADIO_ERR_UNSUPPORTED_OPERATION = -10,
3839
RADIO_ERR_UNIMPLEMENTED = -19,
3940
RADIO_ERR_OTHER = -9999,
@@ -225,6 +226,7 @@ typedef struct {
225226
radio_config_mode_t config_mode;
226227
uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS];
227228
volatile uint32_t regs_dirty;
229+
uint32_t regs_locked;
228230
update_fn update_cb;
229231
} radio_t;
230232

@@ -248,6 +250,15 @@ uint64_t radio_reg_read(
248250
const radio_register_bank_t bank,
249251
const radio_register_t reg);
250252

253+
/**
254+
* Lock a register. Prevents any future calls to `radio_reg_write`
255+
* from overwriting the current stored value of the register.
256+
*/
257+
radio_error_t radio_reg_lock(
258+
radio_t* const radio,
259+
const radio_register_t reg,
260+
const bool locked);
261+
251262
/**
252263
* Apply changes requested in RADIO_BANK_ACTIVE.
253264
* Return true if any changes were applied.

firmware/hackrf_usb/hackrf_usb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
182182
usb_vendor_request_write_radio_reg,
183183
usb_vendor_request_read_radio_reg,
184184
usb_vendor_request_get_buffer_size,
185+
usb_vendor_request_lock_radio_reg,
185186
};
186187

187188
static const uint32_t vendor_request_handler_count =

firmware/hackrf_usb/usb_api_register.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,20 @@ usb_request_status_t usb_vendor_request_read_radio_reg(
416416
}
417417
return USB_REQUEST_STATUS_OK;
418418
}
419+
420+
usb_request_status_t usb_vendor_request_lock_radio_reg(
421+
usb_endpoint_t* const endpoint,
422+
const usb_transfer_stage_t stage)
423+
{
424+
if (stage == USB_TRANSFER_STAGE_SETUP) {
425+
uint8_t reg = endpoint->setup.index;
426+
bool locked = endpoint->setup.value != 0 ? true : false;
427+
if (reg >= RADIO_NUM_REGS) {
428+
return USB_REQUEST_STATUS_STALL;
429+
}
430+
radio_reg_lock(&radio, reg, locked);
431+
usb_transfer_schedule_ack(endpoint->in);
432+
}
433+
434+
return USB_REQUEST_STATUS_OK;
435+
}

firmware/hackrf_usb/usb_api_register.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ usb_request_status_t usb_vendor_request_write_radio_reg(
7070
usb_request_status_t usb_vendor_request_read_radio_reg(
7171
usb_endpoint_t* const endpoint,
7272
const usb_transfer_stage_t stage);
73+
usb_request_status_t usb_vendor_request_lock_radio_reg(
74+
usb_endpoint_t* const endpoint,
75+
const usb_transfer_stage_t stage);

firmware/hackrf_usb/usb_descriptor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#define USB_VENDOR_ID (0x1D50)
3030

31-
#define USB_API_VERSION (0x0112)
31+
#define USB_API_VERSION (0x0113)
3232

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

host/hackrf-tools/src/hackrf_debug.c

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,30 @@ int radio_write_register(
545545
return result;
546546
}
547547

548+
int radio_lock_register(
549+
hackrf_device* device,
550+
const uint16_t register_number,
551+
const bool register_locked)
552+
{
553+
int result = HACKRF_SUCCESS;
554+
result = hackrf_radio_lock_register(
555+
device,
556+
(uint8_t) register_number,
557+
register_locked);
558+
559+
if (result == HACKRF_SUCCESS) {
560+
printf("register [%2d] -> %s\n",
561+
register_number,
562+
register_locked ? "locked" : "unlocked");
563+
} else {
564+
printf("hackrf_radio_lock_register() failed: %s (%d)\n",
565+
hackrf_error_name(result),
566+
result);
567+
}
568+
569+
return result;
570+
}
571+
548572
int read_register(
549573
hackrf_device* device,
550574
uint8_t part,
@@ -621,6 +645,20 @@ int write_register(
621645
return HACKRF_ERROR_INVALID_PARAM;
622646
}
623647

648+
int lock_register(
649+
hackrf_device* device,
650+
uint8_t part,
651+
const uint16_t register_number,
652+
const bool register_locked)
653+
{
654+
switch (part) {
655+
case PART_RADIO:
656+
return radio_lock_register(device, register_number, register_locked);
657+
default:
658+
return HACKRF_ERROR_INVALID_PARAM;
659+
}
660+
}
661+
624662
static const char* mode_name(uint32_t mode)
625663
{
626664
const char* mode_names[] = {"IDLE", "WAIT", "RX", "TX_START", "TX_RUN"};
@@ -675,6 +713,7 @@ static void usage()
675713
printf("\t-n, --register <n>: set register number for read/write operations\n");
676714
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
677715
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
716+
printf("\t-L, --lock <state>: lock register specified by last -n argument (0 for unlocked, 1 for locked)\n");
678717
printf("\t-c, --config: print SI5351C multisynth configuration information\n");
679718
printf("\t-d, --device <s>: specify a particular device by serial number\n");
680719
printf("\t-m, --max283x: target MAX283x\n");
@@ -709,6 +748,7 @@ static struct option long_options[] = {
709748
{"register", required_argument, 0, 'n'},
710749
{"write", required_argument, 0, 'w'},
711750
{"read", no_argument, 0, 'r'},
751+
{"lock", required_argument, 0, 'L'},
712752
{"device", required_argument, 0, 'd'},
713753
{"help", no_argument, 0, 'h'},
714754
{"max2837", no_argument, 0, 'm'},
@@ -740,10 +780,12 @@ int main(int argc, char** argv)
740780
int bank = -1;
741781
uint64_t register_number = REGISTER_INVALID;
742782
uint64_t register_value;
783+
uint64_t register_locked;
743784
hackrf_device* device = NULL;
744785
int option_index = 0;
745786
bool read = false;
746787
bool write = false;
788+
bool lock = false;
747789
bool dump_config = false;
748790
bool dump_state = false;
749791
uint8_t part = PART_NONE;
@@ -782,7 +824,7 @@ int main(int argc, char** argv)
782824
while ((opt = getopt_long(
783825
argc,
784826
argv,
785-
"b:n:rw:d:cmsfgi1:2:C:N:P:ST:R:h?u:l:ta:o",
827+
"b:n:rw:l:d:cmsfgi1:2:C:N:P:ST:R:h?u:l:ta:o",
786828
long_options,
787829
&option_index)) != EOF) {
788830
switch (opt) {
@@ -805,6 +847,11 @@ int main(int argc, char** argv)
805847
read = true;
806848
break;
807849

850+
case 'L':
851+
lock = true;
852+
result = parse_int(optarg, &register_locked);
853+
break;
854+
808855
case 'c':
809856
dump_config = true;
810857
break;
@@ -931,8 +978,8 @@ int main(int argc, char** argv)
931978
}
932979
}
933980

934-
if (write && read) {
935-
fprintf(stderr, "Read and write options are mutually exclusive.\n");
981+
if ((write && read) || (lock && write) || (lock && read)) {
982+
fprintf(stderr, "Read, write and lock options are mutually exclusive.\n");
936983
usage();
937984
return EXIT_FAILURE;
938985
}
@@ -949,6 +996,10 @@ int main(int argc, char** argv)
949996
return EXIT_FAILURE;
950997
}
951998

999+
if (lock && part != PART_RADIO) {
1000+
fprintf(stderr, "Lock option is only valid for radio.\n");
1001+
}
1002+
9521003
if ((bank > -1) && (part != PART_RADIO)) {
9531004
fprintf(stderr, "Bank valid only for radio.\n");
9541005
usage();
@@ -959,11 +1010,11 @@ int main(int argc, char** argv)
9591010
bank = 0;
9601011
}
9611012

962-
if (!(write || read || dump_config || dump_state || set_tx_limit ||
1013+
if (!(write || read || lock || dump_config || dump_state || set_tx_limit ||
9631014
set_rx_limit || set_ui || set_leds || set_p1 || set_p2 || set_clkin ||
9641015
set_narrowband || set_fpga_bitstream || read_selftest || test_rtc_osc ||
9651016
read_adc)) {
966-
fprintf(stderr, "Specify read, write, or config option.\n");
1017+
fprintf(stderr, "Specify read, write, lock, or config option.\n");
9671018
usage();
9681019
return EXIT_FAILURE;
9691020
}
@@ -1016,6 +1067,10 @@ int main(int argc, char** argv)
10161067
}
10171068
}
10181069

1070+
if (lock) {
1071+
result = lock_register(device, part, register_number, register_locked);
1072+
}
1073+
10191074
if (dump_config) {
10201075
si5351c_read_configuration(device);
10211076
}

host/libhackrf/src/hackrf.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ typedef enum {
120120
HACKRF_VENDOR_REQUEST_RADIO_WRITE_REG = 59,
121121
HACKRF_VENDOR_REQUEST_RADIO_READ_REG = 60,
122122
HACKRF_VENDOR_REQUEST_GET_BUFFER_SIZE = 61,
123+
HACKRF_VENDOR_REQUEST_RADIO_LOCK_REG = 62,
123124
} hackrf_vendor_request;
124125

125126
#define USB_CONFIG_STANDARD 0x1
@@ -3574,6 +3575,33 @@ int ADDCALL hackrf_radio_write_register(
35743575
}
35753576
}
35763577

3578+
int ADDCALL hackrf_radio_lock_register(
3579+
hackrf_device* device,
3580+
const uint8_t register_number,
3581+
const bool register_locked)
3582+
{
3583+
USB_API_REQUIRED(device, 0x0113);
3584+
int result;
3585+
3586+
result = libusb_control_transfer(
3587+
device->usb_device,
3588+
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
3589+
LIBUSB_RECIPIENT_DEVICE,
3590+
HACKRF_VENDOR_REQUEST_RADIO_LOCK_REG,
3591+
register_locked,
3592+
register_number,
3593+
NULL,
3594+
0,
3595+
DEFAULT_REQUEST_TIMEOUT);
3596+
3597+
if (result != 0) {
3598+
last_libusb_error = result;
3599+
return HACKRF_ERROR_LIBUSB;
3600+
}
3601+
3602+
return HACKRF_SUCCESS;
3603+
}
3604+
35773605
#ifdef __cplusplus
35783606
} // __cplusplus defined.
35793607
#endif

host/libhackrf/src/hackrf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,20 @@ extern ADDAPI int ADDCALL hackrf_radio_write_register(
23852385
const uint8_t register_number,
23862386
const uint64_t value);
23872387

2388+
/**
2389+
* Lock or unlock a radio configuration register.
2390+
*
2391+
* @param[in] device device to write
2392+
* @param[in] register_number register number to mask
2393+
* @param[out] locked locked state for the register
2394+
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
2395+
* @ingroup debug
2396+
*/
2397+
extern ADDAPI int ADDCALL hackrf_radio_lock_register(
2398+
hackrf_device* device,
2399+
const uint8_t register_number,
2400+
const bool register_locked);
2401+
23882402
#ifdef __cplusplus
23892403
} // __cplusplus defined.
23902404
#endif

0 commit comments

Comments
 (0)