mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-27 15:51:02 +00:00
feat(core): add support for setting BLE name from Trezor firmware
[no changelog]
This commit is contained in:
parent
205a3bee79
commit
a5809c872e
@ -29,6 +29,8 @@
|
||||
#define BLE_RX_PACKET_SIZE 244
|
||||
#define BLE_TX_PACKET_SIZE 64
|
||||
|
||||
#define BLE_ADV_NAME_LEN 20
|
||||
|
||||
typedef enum {
|
||||
BLE_SWITCH_OFF = 0, // Turn off BLE advertising, disconnect
|
||||
BLE_SWITCH_ON = 1, // Turn on BLE advertising
|
||||
@ -37,6 +39,18 @@ typedef enum {
|
||||
BLE_ERASE_BONDS = 4, // Erase all bonding information
|
||||
BLE_ALLOW_PAIRING = 5, // Accept pairing request
|
||||
BLE_REJECT_PAIRING = 6, // Reject pairing request
|
||||
} ble_command_type_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[32];
|
||||
uint8_t name[BLE_ADV_NAME_LEN];
|
||||
|
||||
} ble_command_data_t;
|
||||
|
||||
typedef struct {
|
||||
ble_command_type_t cmd_type;
|
||||
uint8_t data_len;
|
||||
ble_command_data_t data;
|
||||
} ble_command_t;
|
||||
|
||||
typedef enum {
|
||||
@ -91,7 +105,7 @@ void ble_stop(void);
|
||||
// Sends a specific command to the BLE module for execution.
|
||||
//
|
||||
// Returns `true` if the command was successfully issued.
|
||||
bool ble_issue_command(ble_command_t command);
|
||||
bool ble_issue_command(ble_command_t *command);
|
||||
|
||||
// Reads an event from the BLE module
|
||||
//
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <sys/irq.h>
|
||||
#include <sys/systimer.h>
|
||||
#include <util/tsqueue.h>
|
||||
#include <util/unit_properties.h>
|
||||
|
||||
#include "ble_comm_defs.h"
|
||||
|
||||
@ -65,6 +66,7 @@ typedef struct {
|
||||
tsqueue_entry_t ts_queue_entries[TX_QUEUE_LEN];
|
||||
tsqueue_t tx_queue;
|
||||
|
||||
char adv_name[BLE_ADV_NAME_LEN];
|
||||
systimer_t *timer;
|
||||
uint16_t ping_cntr;
|
||||
} ble_driver_t;
|
||||
@ -80,11 +82,19 @@ static bool ble_send_state_request(ble_driver_t *drv) {
|
||||
|
||||
static bool ble_send_advertising_on(ble_driver_t *drv, bool whitelist) {
|
||||
(void)drv;
|
||||
uint8_t data[2];
|
||||
data[0] = INTERNAL_CMD_ADVERTISING_ON;
|
||||
data[1] = whitelist ? 1 : 0;
|
||||
return nrf_send_msg(NRF_SERVICE_BLE_MANAGER, data, sizeof(data), NULL,
|
||||
NULL) >= 0;
|
||||
|
||||
unit_properties_t props;
|
||||
unit_properties_get(&props);
|
||||
|
||||
cmd_advertising_on_t data = {
|
||||
.cmd_id = INTERNAL_CMD_ADVERTISING_ON,
|
||||
.whitelist = whitelist ? 1 : 0,
|
||||
.color = props.color,
|
||||
};
|
||||
memcpy(data.name, drv->adv_name, BLE_ADV_NAME_LEN);
|
||||
|
||||
return nrf_send_msg(NRF_SERVICE_BLE_MANAGER, (uint8_t *)&data, sizeof(data),
|
||||
NULL, NULL) >= 0;
|
||||
}
|
||||
|
||||
static bool ble_send_advertising_off(ble_driver_t *drv) {
|
||||
@ -146,14 +156,6 @@ static void ble_process_rx_msg_status(const uint8_t *data, uint32_t len) {
|
||||
event_status_msg_t msg;
|
||||
memcpy(&msg, data, sizeof(event_status_msg_t));
|
||||
|
||||
if (!drv->status_valid) {
|
||||
if (msg.peer_count > 0) {
|
||||
drv->mode_requested = BLE_MODE_CONNECTABLE;
|
||||
} else {
|
||||
drv->mode_requested = BLE_MODE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (drv->connected != msg.connected) {
|
||||
if (msg.connected) {
|
||||
// new connection
|
||||
@ -507,7 +509,7 @@ uint32_t ble_read(uint8_t *data, uint16_t max_len) {
|
||||
return read_len;
|
||||
}
|
||||
|
||||
bool ble_issue_command(ble_command_t command) {
|
||||
bool ble_issue_command(ble_command_t *command) {
|
||||
ble_driver_t *drv = &g_ble_driver;
|
||||
|
||||
if (!drv->initialized) {
|
||||
@ -518,14 +520,16 @@ bool ble_issue_command(ble_command_t command) {
|
||||
|
||||
bool result = false;
|
||||
|
||||
switch (command) {
|
||||
switch (command->cmd_type) {
|
||||
case BLE_SWITCH_OFF:
|
||||
drv->mode_requested = BLE_MODE_OFF;
|
||||
break;
|
||||
case BLE_SWITCH_ON:
|
||||
memcpy(drv->adv_name, command->data.name, sizeof(drv->adv_name));
|
||||
drv->mode_requested = BLE_MODE_CONNECTABLE;
|
||||
break;
|
||||
case BLE_PAIRING_MODE:
|
||||
memcpy(drv->adv_name, command->data.name, sizeof(drv->adv_name));
|
||||
drv->mode_requested = BLE_MODE_PAIRING;
|
||||
break;
|
||||
case BLE_DISCONNECT:
|
||||
|
@ -17,11 +17,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_BLE_COMM_DEFS_H_
|
||||
#define TREZORHAL_BLE_COMM_DEFS_H_
|
||||
#pragma once
|
||||
|
||||
#include <trezor_types.h>
|
||||
|
||||
#include <io/ble.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t msg_id;
|
||||
uint8_t connected;
|
||||
@ -56,4 +57,10 @@ typedef enum {
|
||||
INTERNAL_CMD_ALLOW_PAIRING = 0x06,
|
||||
INTERNAL_CMD_REJECT_PAIRING = 0x07,
|
||||
} internal_cmd_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t cmd_id;
|
||||
uint8_t whitelist;
|
||||
uint8_t color;
|
||||
uint8_t name[BLE_ADV_NAME_LEN];
|
||||
} cmd_advertising_on_t;
|
||||
|
@ -15,20 +15,43 @@ pub fn connected() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pairing_mode() {
|
||||
pub fn pairing_mode(name: &str) {
|
||||
unsafe {
|
||||
ffi::ble_issue_command(ffi::ble_command_t_BLE_PAIRING_MODE);
|
||||
let mut cmd = ffi::ble_command_t {
|
||||
cmd_type: ffi::ble_command_type_t_BLE_PAIRING_MODE,
|
||||
data_len: 0,
|
||||
data: ffi::ble_command_data_t { raw: [0; 32] },
|
||||
};
|
||||
|
||||
let bytes = name.as_bytes();
|
||||
|
||||
// Determine how many bytes we can copy (min of buffer size and string length).
|
||||
let len = bytes.len().min(cmd.data.name.len());
|
||||
|
||||
cmd.data.name[..len].copy_from_slice(&bytes[..len]);
|
||||
|
||||
ffi::ble_issue_command(&mut cmd as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allow_pairing() {
|
||||
unsafe {
|
||||
ffi::ble_issue_command(ffi::ble_command_t_BLE_ALLOW_PAIRING);
|
||||
let mut cmd = ffi::ble_command_t {
|
||||
cmd_type: ffi::ble_command_type_t_BLE_ALLOW_PAIRING,
|
||||
data_len: 0,
|
||||
data: ffi::ble_command_data_t { raw: [0; 32] },
|
||||
};
|
||||
ffi::ble_issue_command(&mut cmd as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reject_pairing() {
|
||||
unsafe {
|
||||
ffi::ble_issue_command(ffi::ble_command_t_BLE_REJECT_PAIRING);
|
||||
let mut cmd = ffi::ble_command_t {
|
||||
cmd_type: ffi::ble_command_type_t_BLE_REJECT_PAIRING,
|
||||
data_len: 0,
|
||||
data: ffi::ble_command_data_t { raw: [0; 32] },
|
||||
};
|
||||
ffi::ble_issue_command(&mut cmd as _);
|
||||
}
|
||||
}
|
||||
|
@ -687,8 +687,8 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
|
||||
} break;
|
||||
|
||||
case SYSCALL_BLE_ISSUE_COMMAND: {
|
||||
ble_command_t command = args[0];
|
||||
ble_issue_command(command);
|
||||
ble_command_t *command = (ble_command_t *)args[0];
|
||||
args[0] = ble_issue_command__verified(command);
|
||||
} break;
|
||||
|
||||
case SYSCALL_BLE_GET_STATE: {
|
||||
|
@ -655,7 +655,7 @@ secbool firmware_calc_hash(const uint8_t *challenge, size_t challenge_len,
|
||||
|
||||
void ble_start(void) { syscall_invoke0(SYSCALL_BLE_START); }
|
||||
|
||||
bool ble_issue_command(ble_command_t command) {
|
||||
bool ble_issue_command(ble_command_t *command) {
|
||||
return (bool)syscall_invoke1((uint32_t)command, SYSCALL_BLE_ISSUE_COMMAND);
|
||||
}
|
||||
|
||||
|
@ -718,6 +718,18 @@ access_violation:
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#ifdef USE_BLE
|
||||
bool ble_issue_command__verified(ble_command_t *command) {
|
||||
if (!probe_read_access(command, sizeof(*command))) {
|
||||
goto access_violation;
|
||||
}
|
||||
|
||||
return ble_issue_command(command);
|
||||
|
||||
access_violation:
|
||||
apptask_access_violation();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_get_state__verified(ble_state_t *state) {
|
||||
if (!probe_write_access(state, sizeof(*state))) {
|
||||
goto access_violation;
|
||||
|
@ -191,6 +191,8 @@ secbool firmware_get_vendor__verified(char *buff, size_t buff_size);
|
||||
|
||||
#include <io/ble.h>
|
||||
|
||||
bool ble_issue_command__verified(ble_command_t *state);
|
||||
|
||||
void ble_get_state__verified(ble_state_t *state);
|
||||
|
||||
bool ble_get_event__verified(ble_event_t *event);
|
||||
|
@ -124,18 +124,18 @@ STATIC mp_obj_t mod_trezorio_BLE_read(size_t n_args, const mp_obj_t *args) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_BLE_read_obj, 1, 2,
|
||||
mod_trezorio_BLE_read);
|
||||
|
||||
/// def erase_bonds() -> None:
|
||||
/// def erase_bonds() -> bool:
|
||||
/// """
|
||||
/// Erases all BLE bonds
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorio_BLE_erase_bonds(void) {
|
||||
ble_issue_command(BLE_ERASE_BONDS);
|
||||
return mp_const_none;
|
||||
ble_command_t cmd = {.cmd_type = BLE_ERASE_BONDS, .data_len = 0};
|
||||
return mp_obj_new_bool(ble_issue_command(&cmd));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_erase_bonds_obj,
|
||||
mod_trezorio_BLE_erase_bonds);
|
||||
|
||||
/// def start_comm() -> None:
|
||||
/// def start_comm() -> bool:
|
||||
/// """
|
||||
/// Start communication with BLE chip
|
||||
/// """
|
||||
@ -146,41 +146,76 @@ STATIC mp_obj_t mod_trezorio_BLE_start_comm(void) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_start_comm_obj,
|
||||
mod_trezorio_BLE_start_comm);
|
||||
|
||||
/// def start_advertising(whitelist: bool) -> None:
|
||||
/// def start_advertising(whitelist: bool, name: str | None) -> bool:
|
||||
/// """
|
||||
/// Start advertising
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorio_BLE_start_advertising(mp_obj_t whitelist) {
|
||||
bool whitelist_bool = mp_obj_is_true(whitelist);
|
||||
STATIC mp_obj_t mod_trezorio_BLE_start_advertising(size_t n_args,
|
||||
const mp_obj_t *args) {
|
||||
bool whitelist_bool = mp_obj_is_true(args[0]);
|
||||
|
||||
ble_issue_command(whitelist_bool ? BLE_SWITCH_ON : BLE_PAIRING_MODE);
|
||||
return mp_const_none;
|
||||
mp_buffer_info_t name = {0};
|
||||
|
||||
char *name_buf = NULL;
|
||||
int name_len = 0;
|
||||
|
||||
if (n_args == 1 || !mp_get_buffer(args[1], &name, MP_BUFFER_READ)) {
|
||||
name_buf = MODEL_FULL_NAME;
|
||||
name_len = strlen(MODEL_FULL_NAME);
|
||||
} else {
|
||||
name_buf = name.buf;
|
||||
name_len = name.len;
|
||||
}
|
||||
|
||||
ble_command_t cmd = {
|
||||
.cmd_type = whitelist_bool ? BLE_SWITCH_ON : BLE_PAIRING_MODE,
|
||||
.data_len = name.len};
|
||||
|
||||
// get a minimum of the two lengths
|
||||
int len = name_len < BLE_ADV_NAME_LEN ? name_len : BLE_ADV_NAME_LEN;
|
||||
|
||||
memcpy(cmd.data.name, name_buf, len);
|
||||
|
||||
return mp_obj_new_bool(ble_issue_command(&cmd));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_BLE_start_advertising_obj,
|
||||
mod_trezorio_BLE_start_advertising);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
|
||||
mod_trezorio_BLE_start_advertising_obj, 1, 2,
|
||||
mod_trezorio_BLE_start_advertising);
|
||||
|
||||
/// def stop_advertising(whitelist: bool) -> None:
|
||||
/// def stop_advertising(whitelist: bool) -> bool:
|
||||
/// """
|
||||
/// Stop advertising
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorio_BLE_stop_advertising(void) {
|
||||
ble_issue_command(BLE_SWITCH_OFF);
|
||||
return mp_const_none;
|
||||
ble_command_t cmd = {.cmd_type = BLE_SWITCH_OFF, .data_len = 0};
|
||||
return mp_obj_new_bool(ble_issue_command(&cmd));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_stop_advertising_obj,
|
||||
mod_trezorio_BLE_stop_advertising);
|
||||
|
||||
/// def disconnect() -> None:
|
||||
/// def disconnect() -> bool:
|
||||
/// """
|
||||
/// Disconnect BLE
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorio_BLE_disconnect(void) {
|
||||
ble_issue_command(BLE_DISCONNECT);
|
||||
return mp_const_none;
|
||||
ble_command_t cmd = {.cmd_type = BLE_DISCONNECT, .data_len = 0};
|
||||
return mp_obj_new_bool(ble_issue_command(&cmd));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_disconnect_obj,
|
||||
mod_trezorio_BLE_disconnect);
|
||||
|
||||
/// def peer_count() -> int:
|
||||
/// """
|
||||
/// Get peer count (number of bonded devices)
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorio_BLE_peer_count(void) {
|
||||
ble_state_t state;
|
||||
ble_get_state(&state);
|
||||
return MP_OBJ_NEW_SMALL_INT(state.peer_count);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorio_BLE_peer_count_obj,
|
||||
mod_trezorio_BLE_peer_count);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mod_trezorio_BLE_globals_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ble)},
|
||||
// {MP_ROM_QSTR(MP_QSTR_update_init),
|
||||
@ -199,6 +234,8 @@ STATIC const mp_rom_map_elem_t mod_trezorio_BLE_globals_table[] = {
|
||||
MP_ROM_PTR(&mod_trezorio_BLE_stop_advertising_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_disconnect),
|
||||
MP_ROM_PTR(&mod_trezorio_BLE_disconnect_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_peer_count),
|
||||
MP_ROM_PTR(&mod_trezorio_BLE_peer_count_obj)},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mod_trezorio_BLE_globals,
|
||||
mod_trezorio_BLE_globals_table);
|
||||
|
@ -16,35 +16,42 @@ def read(buf: bytes, offset: int = 0) -> int
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def erase_bonds() -> None:
|
||||
def erase_bonds() -> bool:
|
||||
"""
|
||||
Erases all BLE bonds
|
||||
"""
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def start_comm() -> None:
|
||||
def start_comm() -> bool:
|
||||
"""
|
||||
Start communication with BLE chip
|
||||
"""
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def start_advertising(whitelist: bool) -> None:
|
||||
def start_advertising(whitelist: bool, name: str | None) -> bool:
|
||||
"""
|
||||
Start advertising
|
||||
"""
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def stop_advertising(whitelist: bool) -> None:
|
||||
def stop_advertising(whitelist: bool) -> bool:
|
||||
"""
|
||||
Stop advertising
|
||||
"""
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def disconnect() -> None:
|
||||
def disconnect() -> bool:
|
||||
"""
|
||||
Disconnect BLE
|
||||
"""
|
||||
|
||||
|
||||
# upymod/modtrezorio/modtrezorio-ble.h
|
||||
def peer_count() -> int:
|
||||
"""
|
||||
Get peer count (number of bonded devices)
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user