Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for setting BLE name from Trezor firmware #4504

Merged
merged 1 commit into from
Jan 23, 2025
Merged
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
16 changes: 15 additions & 1 deletion core/embed/io/ble/inc/io/ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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
//
Expand Down
34 changes: 19 additions & 15 deletions core/embed/io/ble/stm32/ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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:
Expand Down
13 changes: 10 additions & 3 deletions core/embed/io/ble/stm32/ble_comm_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
31 changes: 27 additions & 4 deletions core/embed/rust/src/trezorhal/ble.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _);
}
}
4 changes: 2 additions & 2 deletions core/embed/sys/syscall/stm32/syscall_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion core/embed/sys/syscall/stm32/syscall_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
12 changes: 12 additions & 0 deletions core/embed/sys/syscall/stm32/syscall_verifiers.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,18 @@ secbool firmware_get_vendor__verified(char *buff, size_t buff_size) {
// ---------------------------------------------------------------------

#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;
Expand Down
2 changes: 2 additions & 0 deletions core/embed/sys/syscall/stm32/syscall_verifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
71 changes: 54 additions & 17 deletions core/embed/upymod/modtrezorio/modtrezorio-ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// """
Expand All @@ -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),
Expand All @@ -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);
Expand Down
Loading
Loading