Compare commits

...
Sign in to create a new pull request.

9 commits

Author SHA1 Message Date
Antoine van Gelder
911194afbc
break
Some checks failed
Build / firmware (UNIVERSAL, latest, ubuntu) (push) Failing after 5s
Check code style / clang-format (push) Failing after 5s
Check code style / clang-format-1 (push) Failing after 4s
Check code style / clang-format-2 (push) Failing after 4s
Check code style / clang-format-3 (push) Failing after 5s
Check includes / includes-check (HACKRF_ONE, 3.12.0) (push) Failing after 5s
Check includes / includes-check (HACKRF_ONE, latest) (push) Failing after 5s
Check includes / includes-check (JAWBREAKER, 3.12.0) (push) Failing after 5s
Check includes / includes-check (JAWBREAKER, latest) (push) Failing after 5s
Check includes / includes-check (PRALINE, 3.12.0) (push) Failing after 4s
Check includes / includes-check (PRALINE, latest) (push) Failing after 3s
Check includes / includes-check (RAD1O, 3.12.0) (push) Failing after 3s
Check includes / includes-check (RAD1O, latest) (push) Failing after 5s
Check includes / includes-check (UNIVERSAL, 3.12.0) (push) Failing after 5s
Check includes / includes-check (UNIVERSAL, latest) (push) Failing after 6s
Build / host (3.10.0, gcc, Unix Makefiles, --target install, --build, macos, bash, sudo) (push) Has been cancelled
Build / host (latest, --install-prefix=/usr/local, gcc, MSYS Makefiles, --install, latest, windows, msys2) (push) Has been cancelled
Build / host (latest, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, late… (push) Has been cancelled
Build / host (latest, gcc, Unix Makefiles, --install, latest, macos, bash, sudo) (push) Has been cancelled
Build / firmware (HACKRF_ONE, latest, windows) (push) Has been cancelled
Build / host (3.21.7, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 17 2022, --install, 17.1… (push) Has been cancelled
Build / host (4.2.6, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, lates… (push) Has been cancelled
Build / firmware (JAWBREAKER, latest, windows) (push) Has been cancelled
Build / firmware (PRALINE, 3.12.0, macos) (push) Has been cancelled
Build / firmware (PRALINE, latest, macos) (push) Has been cancelled
Build / firmware (PRALINE, latest, windows) (push) Has been cancelled
Build / firmware (RAD1O, latest, windows) (push) Has been cancelled
Build / firmware (UNIVERSAL, 3.12.0, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, windows) (push) Has been cancelled
2026-07-24 13:47:45 +02:00
Antoine van Gelder
23813d6bdc
disable set_radio_sample_rate 2026-07-24 13:32:45 +02:00
Antoine van Gelder
83a49c3ada
compiler fix 2026-07-24 12:54:21 +02:00
Antoine van Gelder
640b17997b
libhackrf: add 'hackrf_radio_set_frequency()', 'hackrf_radio_set_frequency_explicit()' and 'hackrf_radio_set_sample_rate()' 2026-07-24 10:30:36 +02:00
Antoine van Gelder
1b1cfcfa0f
Remove 'RADIO_CONFIG_LEGACY'
Some checks failed
Build / firmware (UNIVERSAL, latest, ubuntu) (push) Failing after 2s
Check code style / clang-format (push) Failing after 3s
Check code style / clang-format-1 (push) Failing after 2s
Check code style / clang-format-2 (push) Failing after 2s
Check code style / clang-format-3 (push) Failing after 4s
Check includes / includes-check (HACKRF_ONE, 3.12.0) (push) Failing after 4s
Check includes / includes-check (HACKRF_ONE, latest) (push) Failing after 4s
Check includes / includes-check (JAWBREAKER, 3.12.0) (push) Failing after 4s
Check includes / includes-check (JAWBREAKER, latest) (push) Failing after 3s
Check includes / includes-check (PRALINE, 3.12.0) (push) Failing after 4s
Check includes / includes-check (PRALINE, latest) (push) Failing after 3s
Check includes / includes-check (RAD1O, 3.12.0) (push) Failing after 4s
Check includes / includes-check (RAD1O, latest) (push) Failing after 5s
Check includes / includes-check (UNIVERSAL, 3.12.0) (push) Failing after 6s
Check includes / includes-check (UNIVERSAL, latest) (push) Failing after 8s
Build / host (3.10.0, gcc, Unix Makefiles, --target install, --build, macos, bash, sudo) (push) Has been cancelled
Build / host (3.21.7, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 17 2022, --install, 17.1… (push) Has been cancelled
Build / host (4.2.6, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, lates… (push) Has been cancelled
Build / host (latest, --install-prefix=/usr/local, gcc, MSYS Makefiles, --install, latest, windows, msys2) (push) Has been cancelled
Build / host (latest, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, late… (push) Has been cancelled
Build / firmware (PRALINE, latest, macos) (push) Has been cancelled
Build / firmware (PRALINE, latest, windows) (push) Has been cancelled
Build / firmware (RAD1O, latest, windows) (push) Has been cancelled
Build / firmware (UNIVERSAL, 3.12.0, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, windows) (push) Has been cancelled
Build / host (latest, gcc, Unix Makefiles, --install, latest, macos, bash, sudo) (push) Has been cancelled
Build / firmware (HACKRF_ONE, latest, windows) (push) Has been cancelled
Build / firmware (JAWBREAKER, latest, windows) (push) Has been cancelled
Build / firmware (PRALINE, 3.12.0, macos) (push) Has been cancelled
2026-07-24 09:32:26 +02:00
Antoine van Gelder
5aa73e7d7f
Add 'hackrf_radio_set_mode()' 2026-07-24 09:32:26 +02:00
Antoine van Gelder
027c3df17c
Add 'hackrf_open_mode()', 'hackrf_open_mode_by_serial()' and 'hackrf_device_list_open_mode()' 2026-07-24 09:32:26 +02:00
Antoine van Gelder
efe61835d5
radio: add radio_set_config_mode() 2026-07-24 09:29:58 +02:00
Antoine van Gelder
a79688985c
radio: Add support for locking radio registers
Some checks failed
Build / firmware (UNIVERSAL, latest, ubuntu) (push) Failing after 6s
Check code style / clang-format (push) Failing after 7s
Check code style / clang-format-1 (push) Failing after 5s
Check code style / clang-format-2 (push) Failing after 5s
Check code style / clang-format-3 (push) Failing after 5s
Check includes / includes-check (HACKRF_ONE, 3.12.0) (push) Failing after 5s
Check includes / includes-check (HACKRF_ONE, latest) (push) Failing after 4s
Check includes / includes-check (JAWBREAKER, 3.12.0) (push) Failing after 4s
Check includes / includes-check (JAWBREAKER, latest) (push) Failing after 3s
Check includes / includes-check (PRALINE, 3.12.0) (push) Failing after 3s
Check includes / includes-check (PRALINE, latest) (push) Failing after 3s
Check includes / includes-check (RAD1O, 3.12.0) (push) Failing after 3s
Check includes / includes-check (RAD1O, latest) (push) Failing after 4s
Check includes / includes-check (UNIVERSAL, 3.12.0) (push) Failing after 4s
Check includes / includes-check (UNIVERSAL, latest) (push) Failing after 4s
Build / host (3.10.0, gcc, Unix Makefiles, --target install, --build, macos, bash, sudo) (push) Has been cancelled
Build / host (3.21.7, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 17 2022, --install, 17.1… (push) Has been cancelled
Build / host (4.2.6, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, lates… (push) Has been cancelled
Build / host (latest, --install-prefix=/usr/local, gcc, MSYS Makefiles, --install, latest, windows, msys2) (push) Has been cancelled
Build / host (latest, -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install, msvc, Visual Studio 18 2026, --install, late… (push) Has been cancelled
Build / host (latest, gcc, Unix Makefiles, --install, latest, macos, bash, sudo) (push) Has been cancelled
Build / firmware (HACKRF_ONE, latest, windows) (push) Has been cancelled
Build / firmware (JAWBREAKER, latest, windows) (push) Has been cancelled
Build / firmware (PRALINE, 3.12.0, macos) (push) Has been cancelled
Build / firmware (PRALINE, latest, macos) (push) Has been cancelled
Build / firmware (PRALINE, latest, windows) (push) Has been cancelled
Build / firmware (RAD1O, latest, windows) (push) Has been cancelled
Build / firmware (UNIVERSAL, 3.12.0, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, macos) (push) Has been cancelled
Build / firmware (UNIVERSAL, latest, windows) (push) Has been cancelled
2026-07-24 09:27:23 +02:00
15 changed files with 942 additions and 24 deletions

View file

@ -26,6 +26,14 @@
#include "ice40_spi.h"
/* Supported Bitstreams. */
typedef enum {
FPGA_BITSTREAM_STANDARD = 0,
FPGA_BITSTREAM_HALFPREC = 1,
FPGA_BITSTREAM_EXTPREC_RX = 2,
FPGA_BITSTREAM_EXTPREC_TX = 3,
} fpga_bitstream_index_t;
/* Up to 7 registers, each containing up to 8 bits of data */
#define FPGA_NUM_REGS 7
#define FPGA_DATA_REGS_MAX_VALUE 255

View file

@ -53,6 +53,7 @@ void radio_init(radio_t* const radio)
radio->config[bank][reg] = RADIO_UNSET;
}
}
radio->config_mode = RADIO_CONFIG_STANDARD;
radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
@ -60,6 +61,7 @@ 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)
@ -67,6 +69,11 @@ 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,
@ -77,6 +84,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);
@ -107,6 +118,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];
@ -1010,3 +1035,69 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode)
nvic_enable_irq(NVIC_USB0_IRQ);
radio_update(radio);
}
bool radio_set_config_mode(radio_t* const radio, const radio_config_mode_t mode)
{
// Check if the requested mode is supported.
switch (mode) {
case RADIO_CONFIG_STANDARD:
// supported on all boards
break;
#ifdef IS_PRALINE
case RADIO_CONFIG_HALF_PRECISION:
case RADIO_CONFIG_EXT_PRECISION_RX:
case RADIO_CONFIG_EXT_PRECISION_TX:
// only supported on praline
if (!IS_PRALINE) {
return false;
}
break;
#endif
default:
return false;
}
// Don't do anything if we're already in the requested mode.
if (mode == radio->config_mode) {
return true;
}
#if defined(IS_PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE))
if (IS_PRALINE) {
fpga_bitstream_index_t bitstream_index;
switch (mode) {
case RADIO_CONFIG_STANDARD:
bitstream_index = FPGA_BITSTREAM_STANDARD;
break;
case RADIO_CONFIG_HALF_PRECISION:
bitstream_index = FPGA_BITSTREAM_HALFPREC;
break;
case RADIO_CONFIG_EXT_PRECISION_RX:
bitstream_index = FPGA_BITSTREAM_EXTPREC_RX;
break;
case RADIO_CONFIG_EXT_PRECISION_TX:
bitstream_index = FPGA_BITSTREAM_EXTPREC_TX;
break;
default:
return false;
}
// Reset radio state.
for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) {
radio_reg_write(radio, RADIO_BANK_APPLIED, reg, RADIO_UNSET);
radio_reg_write(radio, RADIO_BANK_REQUESTED, reg, RADIO_UNSET);
}
// Load bitstream.
extern struct fpga_loader_t fpga_loader;
if (!fpga_image_load(&fpga_loader, bitstream_index)) {
return false;
}
}
#endif
// Update radio config mode.
radio->config_mode = mode;
return true;
}

View file

@ -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,
@ -41,11 +42,12 @@ typedef enum {
/* radio configuration modes */
typedef enum {
RADIO_CONFIG_LEGACY = 0,
RADIO_CONFIG_STANDARD = 1,
RADIO_CONFIG_EXT_PRECISION_RX = 2,
RADIO_CONFIG_EXT_PRECISION_TX = 3,
RADIO_CONFIG_HALF_PRECISION = 4,
RADIO_CONFIG_STANDARD = 0,
#ifdef IS_PRALINE
RADIO_CONFIG_EXT_PRECISION_RX = 1,
RADIO_CONFIG_EXT_PRECISION_TX = 2,
RADIO_CONFIG_HALF_PRECISION = 3,
#endif
} radio_config_mode_t;
typedef struct {
@ -231,6 +233,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;
@ -254,6 +257,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.
@ -266,6 +278,12 @@ bool radio_update(radio_t* const radio);
*/
void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode);
/**
* Switch to a new configuration mode.
* Return true if the mode was successfully switched.
*/
bool radio_set_config_mode(radio_t* const radio, const radio_config_mode_t mode);
/**
* Driver instance.
*/

View file

@ -60,6 +60,7 @@ set(SRC_M4
usb_api_spiflash.c
usb_api_transceiver.c
usb_api_operacake.c
usb_api_radio.c
usb_api_sweep.c
usb_api_selftest.c
usb_api_ui.c

View file

@ -75,6 +75,7 @@
#include "usb_api_board_info.h"
#include "usb_api_m0_state.h"
#include "usb_api_operacake.h"
#include "usb_api_radio.h"
#include "usb_api_register.h"
#include "usb_api_selftest.h"
#include "usb_api_spiflash.h"
@ -182,6 +183,13 @@ 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,
usb_vendor_request_open,
usb_vendor_request_close,
usb_vendor_request_set_radio_mode,
usb_vendor_request_set_radio_frequency,
usb_vendor_request_set_radio_frequency_explicit,
usb_vendor_request_set_radio_sample_rate,
};
static const uint32_t vendor_request_handler_count =

View file

@ -0,0 +1,151 @@
/*
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
*
* 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 <stddef.h>
#include <stdint.h>
#include <fixed_point.h>
#include <radio.h>
#include <usb_request.h>
#include <usb_type.h>
#include "usb_queue.h"
usb_request_status_t usb_vendor_request_set_radio_mode(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
radio_config_mode_t mode = endpoint->setup.value;
if (!radio_set_config_mode(&radio, mode)) {
return USB_REQUEST_STATUS_STALL;
}
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
fp_40_24_t set_radio_frequency_param;
usb_request_status_t usb_vendor_request_set_radio_frequency(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->out,
&set_radio_frequency_param,
sizeof(fp_40_24_t),
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_FREQUENCY_RF,
set_radio_frequency_param);
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_FREQUENCY_IF,
RADIO_UNSET);
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_FREQUENCY_LO,
RADIO_UNSET);
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_IMAGE_REJECT,
RADIO_UNSET);
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
typedef struct {
fp_40_24_t if_freq_hz;
fp_40_24_t lo_freq_hz;
uint8_t path;
} set_radio_frequency_explicit_params_t;
set_radio_frequency_explicit_params_t set_radio_frequency_explicit_params;
usb_request_status_t usb_vendor_request_set_radio_frequency_explicit(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->out,
&set_radio_frequency_explicit_params,
sizeof(set_radio_frequency_explicit_params_t),
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_FREQUENCY_IF,
set_radio_frequency_explicit_params.if_freq_hz);
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_FREQUENCY_LO,
set_radio_frequency_explicit_params.lo_freq_hz);
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_IMAGE_REJECT,
set_radio_frequency_explicit_params.path);
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
fp_28_36_t set_radio_sample_rate_param;
usb_request_status_t usb_vendor_request_set_radio_sample_rate(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->out,
&set_radio_sample_rate_param,
sizeof(fp_28_36_t),
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
radio_reg_write(
&radio,
RADIO_BANK_REQUESTED,
RADIO_SAMPLE_RATE,
set_radio_sample_rate_param);
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
*
* 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.
*/
#pragma once
#include <usb_request.h>
#include <usb_type.h>
usb_request_status_t usb_vendor_request_set_radio_mode(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_radio_frequency(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_radio_frequency_explicit(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_radio_sample_rate(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);

View file

@ -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;
}

View file

@ -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);

View file

@ -486,6 +486,42 @@ usb_request_status_t usb_vendor_request_get_buffer_size(
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_open(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
uint16_t usb_api_version;
radio_config_mode_t radio_config_mode;
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_api_version = endpoint->setup.value;
radio_config_mode = (radio_config_mode_t) endpoint->setup.index;
// TODO let device know we have a new libhackrf connection and its supported usb_api_version
(void) usb_api_version;
// switch bitstreams and update radio mode
if (!radio_set_config_mode(&radio, radio_config_mode)) {
return USB_REQUEST_STATUS_STALL;
}
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_close(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
// TODO do nothing for now
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
/* clang-format off */
// Which GPDMA channel to use.

View file

@ -80,6 +80,12 @@ usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
usb_request_status_t usb_vendor_request_get_buffer_size(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_open(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_close(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
void request_transceiver_mode(transceiver_mode_t mode);
void transceiver_startup(transceiver_mode_t mode);

View file

@ -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)

View file

@ -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,
@ -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"};
@ -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");
@ -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'},
@ -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;
@ -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) {
@ -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;
@ -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;
}
@ -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();
@ -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;
}
@ -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);
}

View file

@ -121,6 +121,13 @@ 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_OPEN = 63,
HACKRF_VENDOR_REQUEST_CLOSE = 64,
HACKRF_VENDOR_REQUEST_RADIO_SET_MODE = 65,
HACKRF_VENDOR_REQUEST_RADIO_SET_FREQUENCY = 66,
HACKRF_VENDOR_REQUEST_RADIO_SET_FREQUENCY_EXPLICIT = 67,
HACKRF_VENDOR_REQUEST_RADIO_SET_SAMPLE_RATE = 68,
} hackrf_vendor_request;
#define USB_CONFIG_STANDARD 0x1
@ -714,7 +721,10 @@ libusb_device_handle* hackrf_open_usb(const char* const desired_serial_number)
return usb_device;
}
static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** device)
static int hackrf_open_setup(
enum radio_config_mode mode,
libusb_device_handle* usb_device,
hackrf_device** device)
{
int result;
hackrf_device* lib_device;
@ -796,6 +806,24 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d
lib_device->buffer_size = 32768;
}
if (lib_device->usb_api_version >= 0x0114) {
// Send supported usb api version and requested configuration mode to device.
result = libusb_control_transfer(
lib_device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_OPEN,
lib_device->usb_api_version,
(uint16_t) mode,
NULL,
0,
DEFAULT_REQUEST_TIMEOUT);
if (result != 0) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
}
}
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
if (result != 0) {
free(lib_device);
@ -834,7 +862,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_open(hackrf_device** device)
int ADDCALL hackrf_open_mode(const enum radio_config_mode mode, hackrf_device** device)
{
libusb_device_handle* usb_device;
@ -865,17 +893,18 @@ int ADDCALL hackrf_open(hackrf_device** device)
return HACKRF_ERROR_NOT_FOUND;
}
return hackrf_open_setup(usb_device, device);
return hackrf_open_setup(mode, usb_device, device);
}
int ADDCALL hackrf_open_by_serial(
int ADDCALL hackrf_open_mode_by_serial(
const enum radio_config_mode mode,
const char* const desired_serial_number,
hackrf_device** device)
{
libusb_device_handle* usb_device;
if (desired_serial_number == NULL) {
return hackrf_open(device);
return hackrf_open_mode(mode, device);
}
if (device == NULL) {
@ -888,10 +917,11 @@ int ADDCALL hackrf_open_by_serial(
return HACKRF_ERROR_NOT_FOUND;
}
return hackrf_open_setup(usb_device, device);
return hackrf_open_setup(mode, usb_device, device);
}
int ADDCALL hackrf_device_list_open(
int ADDCALL hackrf_device_list_open_mode(
const enum radio_config_mode mode,
hackrf_device_list_t* list,
int idx,
hackrf_device** device)
@ -912,7 +942,30 @@ int ADDCALL hackrf_device_list_open(
return HACKRF_ERROR_LIBUSB;
}
return hackrf_open_setup(usb_device, device);
return hackrf_open_setup(mode, usb_device, device);
}
int ADDCALL hackrf_open(hackrf_device** device)
{
return hackrf_open_mode(RADIO_CONFIG_STANDARD, device);
}
int ADDCALL hackrf_open_by_serial(
const char* const desired_serial_number,
hackrf_device** device)
{
return hackrf_open_mode_by_serial(
RADIO_CONFIG_STANDARD,
desired_serial_number,
device);
}
int ADDCALL hackrf_device_list_open(
hackrf_device_list_t* list,
int idx,
hackrf_device** device)
{
return hackrf_device_list_open_mode(RADIO_CONFIG_STANDARD, list, idx, device);
}
int ADDCALL hackrf_device_list_bus_sharing(hackrf_device_list_t* list, int idx)
@ -2443,10 +2496,11 @@ int ADDCALL hackrf_stop_tx(hackrf_device* device)
int ADDCALL hackrf_close(hackrf_device* device)
{
int result1, result2;
int result1, result2, result3;
result1 = HACKRF_SUCCESS;
result2 = HACKRF_SUCCESS;
result3 = HACKRF_SUCCESS;
if (device != NULL) {
result1 = hackrf_stop_cmd(device);
@ -2456,6 +2510,27 @@ int ADDCALL hackrf_close(hackrf_device* device)
* also cancel any pending transmit/receive transfers.
*/
result2 = kill_transfer_thread(device);
if (device->usb_api_version >= 0x0114) {
/*
* Let the device know it's been closed.
*/
result3 = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_CLOSE,
0,
0,
NULL,
0,
DEFAULT_REQUEST_TIMEOUT);
if (result3 != 0) {
last_libusb_error = result3;
result3 = HACKRF_ERROR_LIBUSB;
}
}
if (device->usb_device != NULL) {
libusb_release_interface(device->usb_device, 0);
libusb_close(device->usb_device);
@ -2474,7 +2549,12 @@ int ADDCALL hackrf_close(hackrf_device* device)
if (result2 != HACKRF_SUCCESS) {
return result2;
}
return result1;
if (result1 != HACKRF_SUCCESS) {
return result1;
}
return result3;
}
const char* ADDCALL hackrf_error_name(enum hackrf_error errcode)
@ -3575,6 +3655,219 @@ 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;
}
int ADDCALL hackrf_radio_set_mode(hackrf_device* device, const enum radio_config_mode mode)
{
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_SET_MODE,
mode,
0,
NULL,
0,
DEFAULT_REQUEST_TIMEOUT);
if (result != 0) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
}
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_str_to_fp64(const uint8_t Qn, const char* str, uint64_t* const value)
{
uint64_t m = 0;
uint64_t n = 0;
uint64_t div = 1;
uint64_t div_max = ceil((double) Qn * log10(2.0)) * 10;
// validate input
char* endptr;
strtod(str, &endptr);
if (endptr == str || *endptr != '\0') {
return HACKRF_ERROR_INVALID_PARAM;
}
// parse sign
bool negative = false;
if (*str == '-' || *str == '+') {
negative = (*str == '-');
str++;
}
// parse integer component
for (; (*str >= '0') && (*str <= '9'); str++) {
m = (m * 10) + (*str - '0');
}
*value = (m << Qn) * (negative ? -1 : 1);
if (*str != '.') {
return HACKRF_SUCCESS;
}
str++;
// parse fractional component
for (; (*str >= '0') && (*str <= '9') && (div < div_max); str++) {
n = (n * 10) + (*str - '0');
div *= 10;
}
if (div == 1) {
return HACKRF_SUCCESS;
}
*value += ((n << Qn) + (div / 2)) / div;
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_radio_set_frequency(hackrf_device* device, const fp_40_24_t freq_hz)
{
USB_API_REQUIRED(device, 0x0114);
uint64_t set_freq_fp_param;
uint8_t length;
int result;
// serialize parameters
set_freq_fp_param = TO_LE64(freq_hz);
length = sizeof(uint64_t);
result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_RADIO_SET_FREQUENCY,
0,
0,
(unsigned char*) &set_freq_fp_param,
length,
DEFAULT_REQUEST_TIMEOUT);
if (result < length) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
}
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_radio_set_frequency_explicit(
hackrf_device* device,
const fp_40_24_t if_freq_hz,
const fp_40_24_t lo_freq_hz,
const enum rf_path_filter path)
{
USB_API_REQUIRED(device, 0x0114);
struct {
fp_40_24_t if_freq_hz;
fp_40_24_t lo_freq_hz;
uint8_t path;
} params;
uint8_t length;
int result;
// TODO are these values still correct for HackRF Pro ?
if (FP_FREQ(if_freq_hz) < 2000000000 || FP_FREQ(if_freq_hz) > 3000000000) {
return HACKRF_ERROR_INVALID_PARAM;
}
// TODO are these values still correct for HackRF Pro ?
if ((path != RF_PATH_FILTER_BYPASS) &&
(FP_FREQ(lo_freq_hz) < 84375000 || FP_FREQ(lo_freq_hz) > 5400000000)) {
return HACKRF_ERROR_INVALID_PARAM;
}
if (path > 2) {
return HACKRF_ERROR_INVALID_PARAM;
}
params.if_freq_hz = TO_LE(if_freq_hz);
params.lo_freq_hz = TO_LE(lo_freq_hz);
params.path = (uint8_t) path;
length = sizeof(params);
result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_RADIO_SET_FREQUENCY_EXPLICIT,
0,
0,
(unsigned char*) &params,
length,
DEFAULT_REQUEST_TIMEOUT);
if (result < length) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
} else {
return HACKRF_SUCCESS;
}
}
int ADDCALL hackrf_radio_set_sample_rate(hackrf_device* device, const fp_28_36_t freq_hz)
{
USB_API_REQUIRED(device, 0x0114);
uint64_t set_sr_fp_param;
uint8_t length;
int result;
set_sr_fp_param = TO_LE64(freq_hz);
length = sizeof(uint64_t);
result = libusb_control_transfer(
device->usb_device,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_RECIPIENT_DEVICE,
HACKRF_VENDOR_REQUEST_RADIO_SET_SAMPLE_RATE,
0,
0,
(unsigned char*) &set_sr_fp_param,
length,
DEFAULT_REQUEST_TIMEOUT);
if (result < length) {
last_libusb_error = result;
return HACKRF_ERROR_LIBUSB;
}
return HACKRF_SUCCESS;
}
#ifdef __cplusplus
} // __cplusplus defined.
#endif

View file

@ -23,6 +23,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
#pragma once
#include <math.h>
#include <stdint.h>
#include <sys/types.h>
#include <stdbool.h> // for bool
@ -946,6 +947,18 @@ enum clkin_ctrl_signal {
CLKIN_SIGNAL_P22 = 1,
};
/**
* HackRF Pro Radio Configuration Mode.
*
* Used by @ref hackrf_open, @ref hackrf_open_mode_by_serial and @ref hackrf_device_list_open_mode to set the active configuration mode.
*/
enum radio_config_mode {
RADIO_CONFIG_STANDARD = 0,
RADIO_CONFIG_EXT_PRECISION_RX = 1,
RADIO_CONFIG_EXT_PRECISION_TX = 2,
RADIO_CONFIG_HALF_PRECISION = 3,
};
/**
* Opaque struct for hackrf device info. Object can be created via @ref hackrf_open, @ref hackrf_device_list_open or @ref hackrf_open_by_serial and be destroyed via @ref hackrf_close
* @ingroup device
@ -1199,6 +1212,7 @@ extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
/**
* Open a @ref hackrf_device from a device list
* @deprecated this function has been replaced by @ref hackrf_device_list_open_mode
* @param[in] list device list to open device from
* @param[in] idx index of the device to open
* @param[out] device device handle to open
@ -1210,6 +1224,24 @@ extern ADDAPI int ADDCALL hackrf_device_list_open(
int idx,
hackrf_device** device);
/**
* Open a @ref hackrf_device from a device list and initialize it to the given radio configuration mode.
*
* Modes other than RADIO_CONFIG_STANDARD are only supported on HackRF Pro hardware.
*
* @param[in] mode configuration mode. Defaults to RADIO_CONFIG_STANDARD. Available modes are defined in @ref radio_config_mode.
* @param[in] list device list to open device from
* @param[in] idx index of the device to open
* @param[out] device device handle to open
* @return @ref HACKRF_SUCCESS on success, @ref HACKRF_ERROR_INVALID_PARAM on invalid parameters or other @ref hackrf_error variant
* @ingroup device
*/
extern ADDAPI int ADDCALL hackrf_device_list_open_mode(
const enum radio_config_mode mode,
hackrf_device_list_t* list,
int idx,
hackrf_device** device);
/**
* Check if a listed HackRF device is sharing its USB bus with other devices.
*
@ -1231,14 +1263,30 @@ extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t* list);
/**
* Open first available HackRF device
* @deprecated this function has been replaced by @ref hackrf_open_mode
* @param[out] device device handle
* @return @ref HACKRF_SUCCESS on success, @ref HACKRF_ERROR_INVALID_PARAM if @p device is NULL, @ref HACKRF_ERROR_NOT_FOUND if no HackRF devices are found or other @ref hackrf_error variant
* @ingroup device
*/
extern ADDAPI int ADDCALL hackrf_open(hackrf_device** device);
/**
* Open first available HackRF device and initialize it to the given radio configuration mode.
*
* Modes other than RADIO_CONFIG_STANDARD are only supported on HackRF Pro hardware.
*
* @param[in] mode configuration mode. Defaults to RADIO_CONFIG_STANDARD. Available modes are defined in @ref radio_config_mode.
* @param[out] device device handle
* @return @ref HACKRF_SUCCESS on success, @ref HACKRF_ERROR_INVALID_PARAM if @p device is NULL, @ref HACKRF_ERROR_NOT_FOUND if no HackRF devices are found or other @ref hackrf_error variant
* @ingroup device
*/
extern ADDAPI int ADDCALL hackrf_open_mode(
const enum radio_config_mode mode,
hackrf_device** device);
/**
* Open HackRF device by serial number
* @deprecated this function has been replaced by @ref hackrf_open_mode_by_serial
* @param[in] desired_serial_number serial number of device to open. If NULL then default to first device found.
* @param[out] device device handle
* @return @ref HACKRF_SUCCESS on success, @ref HACKRF_ERROR_INVALID_PARAM if @p device is NULL, @ref HACKRF_ERROR_NOT_FOUND if no HackRF devices are found or other @ref hackrf_error variant
@ -1248,6 +1296,22 @@ extern ADDAPI int ADDCALL hackrf_open_by_serial(
const char* const desired_serial_number,
hackrf_device** device);
/**
* Open HackRF device by serial number and initialize it to the given radio configuration mode.
*
* Modes other than RADIO_CONFIG_STANDARD are only supported on HackRF Pro hardware.
*
* @param[in] mode configuration mode. Defaults to RADIO_CONFIG_STANDARD. Available modes are defined in @ref radio_config_mode.
* @param[in] desired_serial_number serial number of device to open. If NULL then default to first device found.
* @param[out] device device handle
* @return @ref HACKRF_SUCCESS on success, @ref HACKRF_ERROR_INVALID_PARAM if @p device is NULL, @ref HACKRF_ERROR_NOT_FOUND if no HackRF devices are found or other @ref hackrf_error variant
* @ingroup device
*/
extern ADDAPI int ADDCALL hackrf_open_mode_by_serial(
const enum radio_config_mode mode,
const char* const desired_serial_number,
hackrf_device** device);
/**
* Close a previously opened device
* @param[in] device device to close
@ -1752,7 +1816,8 @@ extern ADDAPI int ADDCALL hackrf_usb_api_version_read(
* Simple (auto) tuning via specifying a center frequency in Hz
*
* This setting is not exact and depends on the PLL settings. Exact resolution is not determined, but the actual tuned frequency will be queryable in the future.
*
*
* @deprecated this function has been replaced by @ref hackrf_radio_set_frequency
* @param device device to tune
* @param freq_hz center frequency in Hz. Defaults to 900MHz. Should be in range 1-6000MHz, but 0-7250MHz is possible. The resolution is ~50Hz, I could not find the exact number.
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
@ -1764,7 +1829,8 @@ extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t
* Set the center frequency via explicit tuning
*
* Center frequency is set to \f$f_{center} = f_{IF} + k\cdot f_{LO}\f$ where \f$k\in\left\{-1; 0; 1\right\}\f$, depending on the value of @p path. See the documentation of @ref rf_path_filter for details
*
*
* @deprecated this function has been replaced by @ref hackrf_radio_set_frequency_explicit
* @param device device to tune
* @param if_freq_hz tuning frequency of the MAX2837 transceiver IC in Hz. Must be in the range of 2150-2750MHz
* @param lo_freq_hz tuning frequency of the RFFC5072 mixer/synthesizer IC in Hz. Must be in the range 84.375-5400MHz, defaults to 1000MHz. No effect if @p path is set to @ref RF_PATH_FILTER_BYPASS
@ -1785,7 +1851,8 @@ extern ADDAPI int ADDCALL hackrf_set_freq_explicit(
*
* This function sets the sample rate by specifying a clock frequency in Hz and a divider, so the resulting sample rate will be @p freq_hz / @p divider.
* This function also sets the baseband filter bandwidth to a value \f$ \le 0.75 \cdot F_s \f$, so any calls to @ref hackrf_set_baseband_filter_bandwidth should only be made after this.
*
*
* @deprecated this function has been replaced by @ref hackrf_radio_set_sample_rate
* @param device device to configure
* @param freq_hz sample rate base frequency in Hz
* @param divider frequency divider. Must be in the range 1-31
@ -1803,6 +1870,7 @@ extern ADDAPI int ADDCALL hackrf_set_sample_rate_manual(
* Sample rate should be in the range 2-20MHz, with the default being 10MHz. Lower & higher values are technically possible, but the performance is not guaranteed.
* This function also sets the baseband filter bandwidth to a value \f$ \le 0.75 \cdot F_s \f$, so any calls to @ref hackrf_set_baseband_filter_bandwidth should only be made after this.
*
* @deprecated this function has been replaced by @ref hackrf_radio_set_sample_rate
* @param device device to configure
* @param freq_hz sample rate frequency in Hz. Should be in the range 2-20MHz
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
@ -2385,6 +2453,128 @@ 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);
/**
* Switches the radio configuration mode.
*
* @param[in] device device to configure
* @param[in] mode configuration mode. Defaults to RADIO_CONFIG_STANDARD. Available modes are defined in @ref radio_config_mode.
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_radio_set_mode(
hackrf_device* device,
const enum radio_config_mode mode);
/**
* 40.24 Fixed-point type.
*
* Used by @ref hackrf_radio_set_frequency and @ref hackrf_radio_set_frequency_explicit
* to represent a fractional tuning frequency.
*/
typedef uint64_t fp_40_24_t;
/**
* 28.36 Fixed-point type.
*
* Used by @ref hackrf_radio_set_sample_rate to represent a fractional sample rate.
*/
typedef uint64_t fp_28_36_t;
/**
* Convert an integer frequency value to its corresponding fixed-point value.
*/
#define FREQ_FP(u64) ((uint64_t) u64 << 24)
/**
* Convert an integer sample rate value to its corresponding fixed-point value.
*/
#define SR_FP(u64) ((uint64_t) u64 << 36)
/**
* Convert a fixed-point frequency value to its corresponding integer value, rounding up to the nearest integer.
*
*/
#define FP_FREQ(u64) (((uint64_t) u64 + ((1ULL << 24) - 1)) >> 24)
/**
* Convert a fixed-point sample rate value to its corresponding integer value, rounding up to the nearest integer.
*/
#define FP_SR(u64) (((uint64_t) u64 + ((1ULL << 36) - 1)) >> 36)
/**
* Convert ASCII string to a 64 bit fixed-point number with a given number of bits of accuracy.
*
* @param[in] str string to parse
* @param[in] Qn number of bits to use for fractional part
* @param[out] value converted value
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_str_to_fp64(
const uint8_t Qn,
const char* str,
uint64_t* const value);
/**
* Set the radio center frequency to a fractional, fixed-point value.
*
* @param[in] device device to tune
* @param[in] hz center frequency in Hz
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_radio_set_frequency(
hackrf_device* device,
const fp_40_24_t freq_hz);
/**
* Set the radio center frequency to via explicit tuning.
*
* Center frequency is set to \f$f_{center} = f_{IF} + k\cdot f_{LO}\f$ where \f$k\in\left\{-1; 0; 1\right\}\f$, depending on the value of @p path. See the documentation of @ref rf_path_filter for details
*
* @param device device to tune
* TODO are these values still applicable for HackRF Pro ?
* @param if_freq_hz tuning frequency of the MAX2837 transceiver IC in Hz. Must be in the range of 2150-2750MHz
* TODO are these values still applicable for HackRF Pro ?
* @param lo_freq_hz tuning frequency of the RFFC5072 mixer/synthesizer IC in Hz. Must be in the range 84.375-5400MHz, defaults to 1000MHz. No effect if @p path is set to @ref RF_PATH_FILTER_BYPASS
* @param path filter path for mixer. See the documentation for @ref rf_path_filter for details
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_radio_set_frequency_explicit(
hackrf_device* device,
const fp_40_24_t if_freq_hz,
const fp_40_24_t lo_freq_hz,
const enum rf_path_filter path);
/**
* Set the radio sample rate to a fractional, fixed-point value.
*
* This function does not automatically configure the baseband filter bandwidth, so any calls to this function should be followed by @ref hackrf_set_baseband_filter_bandwidth should it require adjustment.
*
* @param[in] device device to configure
* @param[in] sps samples per second
* @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant
* @ingroup configuration
*/
extern ADDAPI int ADDCALL hackrf_radio_set_sample_rate(
hackrf_device* device,
const fp_28_36_t freq_hz);
#ifdef __cplusplus
} // __cplusplus defined.
#endif