From 2c505978a54b7aba79c3b4c79328045d7b63dfa8 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Tue, 7 Mar 2023 15:08:02 +0100 Subject: [PATCH] feat(core): internal events between nrf and stm --- core/SConscript.ble_firmware | 2 + core/SConscript.firmware | 1 + core/embed/ble_firmware/int_comm.c | 245 ++++++++++++++++ core/embed/ble_firmware/int_comm.h | 25 ++ core/embed/ble_firmware/main.c | 276 +++--------------- .../extmod/modtrezorio/modtrezorio-ble.h | 3 +- .../extmod/modtrezorio/modtrezorio-poll.h | 11 + core/embed/extmod/modtrezorio/modtrezorio.c | 2 + core/embed/rust/Cargo.toml | 1 + core/embed/rust/build.rs | 2 + core/embed/rust/src/trezorhal/ble.rs | 5 + core/embed/rust/src/trezorhal/mod.rs | 2 + core/embed/rust/trezorhal.h | 1 + core/embed/trezorhal/ble/comm.c | 155 ++++++++-- core/embed/trezorhal/ble/comm.h | 11 +- core/embed/trezorhal/ble/int_comm_defs.h | 20 ++ core/embed/trezorhal/ble/state.c | 14 + core/embed/trezorhal/ble/state.h | 16 + core/embed/unix/ble/state.c | 14 + core/embed/unix/ble/state.h | 16 + 20 files changed, 566 insertions(+), 256 deletions(-) create mode 100644 core/embed/ble_firmware/int_comm.c create mode 100644 core/embed/ble_firmware/int_comm.h create mode 100644 core/embed/rust/src/trezorhal/ble.rs create mode 100644 core/embed/trezorhal/ble/int_comm_defs.h create mode 100644 core/embed/trezorhal/ble/state.c create mode 100644 core/embed/trezorhal/ble/state.h create mode 100644 core/embed/unix/ble/state.c create mode 100644 core/embed/unix/ble/state.h diff --git a/core/SConscript.ble_firmware b/core/SConscript.ble_firmware index 0daec60bd2..843e22b14a 100644 --- a/core/SConscript.ble_firmware +++ b/core/SConscript.ble_firmware @@ -191,6 +191,7 @@ CPPPATH_MOD += [ 'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/ac_rec_parser', 'embed/sdk/nrf52/components/libraries/stack_guard', 'embed/sdk/nrf52/components/libraries/log/src', + 'embed' ] SOURCE_MOD += [ ] @@ -274,6 +275,7 @@ SOURCE_NRFHAL = [ SOURCE_BLE_FIRMWARE = [ 'embed/ble_firmware/main.c', 'embed/ble_firmware/ble_nus.c', + 'embed/ble_firmware/int_comm.c', ] if MMD: diff --git a/core/SConscript.firmware b/core/SConscript.firmware index b236386a69..9aa7595d8d 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -382,6 +382,7 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/ble/comm.c', 'embed/trezorhal/ble/dfu.c', 'embed/trezorhal/ble/fwu.c', + 'embed/trezorhal/ble/state.c', ] diff --git a/core/embed/ble_firmware/int_comm.c b/core/embed/ble_firmware/int_comm.c new file mode 100644 index 0000000000..c774a85057 --- /dev/null +++ b/core/embed/ble_firmware/int_comm.c @@ -0,0 +1,245 @@ + +#include "int_comm.h" +#include "app_error.h" +#include "app_uart.h" +#include "ble_nus.h" +#include "nrf_log.h" +#include "stdint.h" +#include "trezorhal/ble/int_comm_defs.h" + +static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN]; +static bool m_uart_rx_data_ready_internal = false; +static uint16_t *m_p_conn_handle = NULL; + +BLE_NUS_DEF(m_nus, + NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ + +void nus_init(uint16_t *p_conn_handle) { + m_p_conn_handle = p_conn_handle; + uint32_t err_code; + + ble_nus_init_t nus_init; + + memset(&nus_init, 0, sizeof(nus_init)); + + nus_init.data_handler = nus_data_handler; + + err_code = ble_nus_init(&m_nus, &nus_init); + APP_ERROR_CHECK(err_code); + + *p_conn_handle = BLE_CONN_HANDLE_INVALID; +} + +void process_command(uint8_t *data, uint16_t len) { + uint8_t cmd = data[0]; + switch (cmd) { + case INTERNAL_CMD_SEND_STATE: + if (*m_p_conn_handle != BLE_CONN_HANDLE_INVALID) { + send_connected_event(); + } else { + send_disconnected_event(); + } + break; + default: + break; + } +} + +/**@brief Function for handling app_uart events. + * + * @details This function will receive a single character from the app_uart + * module and append it to a string. The string will be be sent over BLE when + * the last character received was a 'new line' '\n' (hex 0x0A) or if the string + * has reached the maximum data length. + */ +/**@snippet [Handling the data received over UART] */ +void uart_event_handle(app_uart_evt_t *p_event) { + static uint8_t index = 0; + static uint8_t message_type = 0; + static uint16_t len = 0; + uint32_t err_code; + uint8_t rx_byte = 0; + + switch (p_event->evt_type) { + case APP_UART_DATA_READY: + while (app_uart_get(&rx_byte) == NRF_SUCCESS) { + if (index == 0) { + if (rx_byte == INTERNAL_MESSAGE || rx_byte == INTERNAL_EVENT || + rx_byte == EXTERNAL_MESSAGE) { + message_type = rx_byte; + index += 1; + continue; + } else { + // unknown message + continue; + } + } + + if (index == 1) { + // len HI + len = rx_byte << 8; + index += 1; + continue; + } + + if (index == 2) { + // len LO + len |= rx_byte; + index += 1; + if (len > sizeof(m_uart_rx_data) + OVERHEAD_SIZE) { + // message too long + index = 0; + continue; + } + continue; + } + + if (index < (len - 1)) { + // command + m_uart_rx_data[index - COMM_HEADER_SIZE] = rx_byte; + index += 1; + continue; + } + + if (index >= (len - 1)) { + if (rx_byte == EOM) { + if (message_type == EXTERNAL_MESSAGE) { + NRF_LOG_DEBUG("Ready to send data over BLE NUS"); + NRF_LOG_HEXDUMP_DEBUG(m_uart_rx_data, index); + + do { + uint16_t length = (uint16_t)len - OVERHEAD_SIZE; + err_code = ble_nus_data_send(&m_nus, m_uart_rx_data, &length, + *m_p_conn_handle); + if ((err_code != NRF_ERROR_INVALID_STATE) && + (err_code != NRF_ERROR_RESOURCES) && + (err_code != NRF_ERROR_NOT_FOUND)) { + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_RESOURCES); + } else if (message_type == INTERNAL_MESSAGE) { + m_uart_rx_data_ready_internal = true; + } else if (message_type == INTERNAL_EVENT) { + process_command(m_uart_rx_data, len - OVERHEAD_SIZE); + } + } + index = 0; + } + } + break; + default: + break; + } +} +/**@snippet [Handling the data received over UART] */ + +void send_byte(uint8_t byte) { + uint32_t err_code; + + do { + err_code = app_uart_put(byte); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { + NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); + } + } while (err_code == NRF_ERROR_BUSY); +} + +void send_packet(uint8_t message_type, const uint8_t *tx_data, uint16_t len) { + uint16_t total_len = len + OVERHEAD_SIZE; + send_byte(message_type); + send_byte((total_len >> 8) & 0xFF); + send_byte(total_len & 0xFF); + for (uint32_t i = 0; i < len; i++) { + send_byte(tx_data[i]); + } + send_byte(EOM); +} + +/**@brief Function for handling the data from the Nordic UART Service. + * + * @details This function will process the data received from the Nordic UART + * BLE Service and send it to the UART module. + * + * @param[in] p_evt Nordic UART Service event. + */ +/**@snippet [Handling the data received over BLE] */ +void nus_data_handler(ble_nus_evt_t *p_evt) { + if (p_evt->type == BLE_NUS_EVT_RX_DATA) { + NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART."); + NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, + p_evt->params.rx_data.length); + + if (p_evt->params.rx_data.length != 64) { + return; + } + + send_packet(EXTERNAL_MESSAGE, p_evt->params.rx_data.p_data, + p_evt->params.rx_data.length); + } +} +/**@snippet [Handling the data received over BLE] */ + +void send_connected_event(void) { + uint8_t tx_data[] = { + INTERNAL_EVENT_CONNECTED, + }; + send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data)); +} + +void send_disconnected_event(void) { + uint8_t tx_data[] = { + INTERNAL_EVENT_DISCONNECTED, + }; + send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data)); +} + +uint16_t get_message_type(const uint8_t *rx_data) { + return (rx_data[3] << 8) | rx_data[4]; +} + +bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len) { + uint8_t tx_data[] = { + 0x3F, 0x23, 0x23, 0x1F, 0x43, 0x00, 0x00, 0x00, 0x00, + }; + send_packet(INTERNAL_MESSAGE, tx_data, sizeof(tx_data)); + + while (!m_uart_rx_data_ready_internal) + ; + + if (get_message_type(m_uart_rx_data) != 8004) { + m_uart_rx_data_ready_internal = false; + return false; + } + + for (int i = 0; i < 6; i++) { + p_key[i] = m_uart_rx_data[i + 11]; + } + m_uart_rx_data_ready_internal = false; + + return true; +} + +bool send_repair_request(void) { + uint8_t tx_data[] = { + 0x3F, 0x23, 0x23, 0x1F, 0x45, 0x00, 0x00, 0x00, 0x00, + }; + send_packet(INTERNAL_MESSAGE, tx_data, sizeof(tx_data)); + + while (!m_uart_rx_data_ready_internal) + ; + + m_uart_rx_data_ready_internal = false; + + if (get_message_type(m_uart_rx_data) != 2) { + return false; + } + + return true; +} + +void send_initialized(void) { + uint8_t tx_data[] = { + INTERNAL_EVENT_INITIALIZED, + }; + send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data)); +} diff --git a/core/embed/ble_firmware/int_comm.h b/core/embed/ble_firmware/int_comm.h new file mode 100644 index 0000000000..252a4a5627 --- /dev/null +++ b/core/embed/ble_firmware/int_comm.h @@ -0,0 +1,25 @@ + +#ifndef __INT_COMM__ +#define __INT_COMM__ + +#include "app_uart.h" +#include "ble_nus.h" +#include "stdint.h" + +void nus_init(uint16_t *p_conn_handle); + +void nus_data_handler(ble_nus_evt_t *p_evt); + +void uart_event_handle(app_uart_evt_t *p_event); + +void send_connected_event(void); + +void send_disconnected_event(void); + +bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len); + +bool send_repair_request(void); + +void send_initialized(void); + +#endif diff --git a/core/embed/ble_firmware/main.c b/core/embed/ble_firmware/main.c index bc02c53f09..d0747a94e3 100644 --- a/core/embed/ble_firmware/main.c +++ b/core/embed/ble_firmware/main.c @@ -84,6 +84,8 @@ #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" +#include "int_comm.h" + #define APP_BLE_CONN_CFG_TAG \ 1 /**< A tag identifying the SoftDevice BLE configuration. */ @@ -139,12 +141,31 @@ #define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ #define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ -BLE_NUS_DEF(m_nus, - NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ -NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ +#define SEC_PARAM_BOND 1 /**< Perform bonding. */ +#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ +#define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ +#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ +#define SEC_PARAM_IO_CAPABILITIES \ + BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY /**< No I/O capabilities. */ +#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ +#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ +#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ + +#define SCHED_MAX_EVENT_DATA_SIZE \ + APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */ +#ifdef SVCALL_AS_NORMAL_FUNCTION +#define SCHED_QUEUE_SIZE \ + 20 /**< Maximum number of events in the scheduler queue. More is needed in \ + case of Serialization. */ +#else +#define SCHED_QUEUE_SIZE \ + 10 /**< Maximum number of events in the scheduler queue. */ +#endif + static pm_peer_id_t m_peer_id; /**< Device reference handle to the current bonded central. */ static uint16_t m_conn_handle = @@ -156,9 +177,6 @@ static uint16_t m_ble_nus_max_data_len = static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; -static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN]; -static bool m_uart_rx_data_ready_internal = false; - /**@brief Function for assert macro callback. * * @details This function will be called in case of an assert in the SoftDevice. @@ -224,51 +242,11 @@ static void nrf_qwr_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } -/**@brief Function for handling the data from the Nordic UART Service. - * - * @details This function will process the data received from the Nordic UART - * BLE Service and send it to the UART module. - * - * @param[in] p_evt Nordic UART Service event. - */ -/**@snippet [Handling the data received over BLE] */ -static void nus_data_handler(ble_nus_evt_t *p_evt) { - if (p_evt->type == BLE_NUS_EVT_RX_DATA) { - uint32_t err_code; - - NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART."); - NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, - p_evt->params.rx_data.length); - - if (p_evt->params.rx_data.length != 64) { - return; - } - - app_uart_put(0xA1); // external message - app_uart_put(0x00); // len - HI - app_uart_put(0x44); // len - LO - - for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++) { - do { - err_code = app_uart_put(p_evt->params.rx_data.p_data[i]); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { - NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_BUSY); - } - - app_uart_put(0x55); // EOM - } -} -/**@snippet [Handling the data received over BLE] */ - /**@brief Function for initializing services that will be used by the * application. */ static void services_init(void) { uint32_t err_code; - ble_nus_init_t nus_init; nrf_ble_qwr_init_t qwr_init = {0}; // Initialize Queued Write Module. @@ -277,13 +255,7 @@ static void services_init(void) { err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); APP_ERROR_CHECK(err_code); - // Initialize NUS. - memset(&nus_init, 0, sizeof(nus_init)); - - nus_init.data_handler = nus_data_handler; - - err_code = ble_nus_init(&m_nus, &nus_init); - APP_ERROR_CHECK(err_code); + nus_init(&m_conn_handle); } /**@brief Function for handling errors from the Connection Parameters module. @@ -451,20 +423,6 @@ static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { } } -static void int_comm_send(uint8_t *tx_data, uint16_t len) { - uint32_t err_code; - - for (uint32_t i = 0; i < len; i++) { - do { - err_code = app_uart_put(tx_data[i]); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { - NRF_LOG_ERROR("Failed sending data to STM. Error 0x%x. ", err_code); - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_BUSY); - } -} - /**@brief Function for handling BLE events. * * @param[in] p_ble_evt Bluetooth stack event. @@ -478,6 +436,8 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { NRF_LOG_INFO("Connected"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); + + send_connected_event(); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); APP_ERROR_CHECK(err_code); @@ -486,6 +446,7 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("Disconnected"); // LED indication will be changed when advertising starts. + send_disconnected_event(); m_conn_handle = BLE_CONN_HANDLE_INVALID; break; @@ -503,37 +464,19 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { case BLE_GAP_EVT_AUTH_KEY_REQUEST: { NRF_LOG_INFO("Key requested."); - uint8_t tx_data[] = { - 0xA0, // internal message - 0x00, // length - HI - 0x0D, // length - LO - 0x3F, 0x23, 0x23, 0x1F, 0x43, 0x00, 0x00, 0x00, 0x00, - 0x55, // EOM - }; - - int_comm_send(tx_data, sizeof(tx_data)); - uint8_t p_key[6] = {0}; - while (!m_uart_rx_data_ready_internal) - ; + bool ok = send_auth_key_request(p_key, sizeof(p_key)); - uint16_t message_type = (m_uart_rx_data[3] << 8) | m_uart_rx_data[4]; - - if (message_type != 8004) { - break; + if (ok) { + NRF_LOG_INFO("Received data: %c", p_key); + err_code = + sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, p_key); + } else { + NRF_LOG_INFO("Auth key request failed."); } - for (int i = 0; i < 6; i++) { - p_key[i] = m_uart_rx_data[i + 11]; - } - m_uart_rx_data_ready_internal = false; - - NRF_LOG_INFO("Received data: %c", p_key); - - err_code = - sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, - BLE_GAP_AUTH_KEY_TYPE_PASSKEY, p_key); // APP_ERROR_CHECK(err_code); break; } @@ -644,105 +587,6 @@ void bsp_event_handler(bsp_event_t event) { } } -/**@brief Function for handling app_uart events. - * - * @details This function will receive a single character from the app_uart - * module and append it to a string. The string will be be sent over BLE when - * the last character received was a 'new line' '\n' (hex 0x0A) or if the string - * has reached the maximum data length. - */ -/**@snippet [Handling the data received over UART] */ -void uart_event_handle(app_uart_evt_t *p_event) { - static uint8_t index = 0; - static uint8_t external = 0; - static uint16_t len = 0; - uint32_t err_code; - uint8_t rx_byte = 0; - - switch (p_event->evt_type) { - case APP_UART_DATA_READY: - while (app_uart_get(&rx_byte) == NRF_SUCCESS) { - if (index == 0) { - // decide destination - if (rx_byte == 0xA0) { - // internal message - external = 0; - index += 1; - continue; - } else if (rx_byte == 0xA1) { - // external message - external = 1; - index += 1; - continue; - - } else { - // unknown message - continue; - } - } - - if (index == 1) { - // len HI - len = rx_byte << 8; - index += 1; - continue; - } - - if (index == 2) { - // len LO - len |= rx_byte; - index += 1; - continue; - } - - if (index < (len - 1)) { - // command - m_uart_rx_data[index - 3] = rx_byte; - index += 1; - continue; - } - - if (index >= (len - 1)) { - { - if (rx_byte == 0x55) { - if (external) { - NRF_LOG_DEBUG("Ready to send data over BLE NUS"); - NRF_LOG_HEXDUMP_DEBUG(m_uart_rx_data, index); - - do { - uint16_t length = (uint16_t)len - 4; - err_code = ble_nus_data_send(&m_nus, m_uart_rx_data, &length, - m_conn_handle); - if ((err_code != NRF_ERROR_INVALID_STATE) && - (err_code != NRF_ERROR_RESOURCES) && - (err_code != NRF_ERROR_NOT_FOUND)) { - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_RESOURCES); - } else { - m_uart_rx_data_ready_internal = true; - } - } - index = 0; - } - } - } - break; - - // case APP_UART_COMMUNICATION_ERROR: - // APP_ERROR_HANDLER(p_event->data.error_communication); - // break; - // - // case APP_UART_FIFO_ERROR: - // APP_ERROR_HANDLER(p_event->data.error_code); - // break; - - default: - break; - } -} -/**@snippet [Handling the data received over UART] */ - /**@brief Function for initializing the UART module. */ /**@snippet [UART Initialization] */ @@ -888,27 +732,6 @@ static void advertising_start(bool erase_bonds) { } } -#define SEC_PARAM_BOND 1 /**< Perform bonding. */ -#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ -#define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ -#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ -#define SEC_PARAM_IO_CAPABILITIES \ - BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY /**< No I/O capabilities. */ -#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ -#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ -#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ - -#define SCHED_MAX_EVENT_DATA_SIZE \ - APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */ -#ifdef SVCALL_AS_NORMAL_FUNCTION -#define SCHED_QUEUE_SIZE \ - 20 /**< Maximum number of events in the scheduler queue. More is needed in \ - case of Serialization. */ -#else -#define SCHED_QUEUE_SIZE \ - 10 /**< Maximum number of events in the scheduler queue. */ -#endif - /**@brief Function for handling Peer Manager events. * * @param[in] p_evt Peer Manager event. @@ -939,29 +762,14 @@ static void pm_evt_handler(pm_evt_t const *p_evt) { } break; case PM_EVT_CONN_SEC_CONFIG_REQ: { - uint8_t tx_data[] = { - 0xA0, // internal message - 0x00, // length - HI - 0x0D, // length - LO - 0x3F, 0x23, 0x23, 0x1F, 0x45, 0x00, 0x00, 0x00, 0x00, - 0x55, // EOM - }; + bool ok = send_repair_request(); - int_comm_send(tx_data, sizeof(tx_data)); - - while (!m_uart_rx_data_ready_internal) - ; - - uint16_t message_type = (m_uart_rx_data[3] << 8) | m_uart_rx_data[4]; - - m_uart_rx_data_ready_internal = false; - - if (message_type == 2) { - // Allow or reject pairing request from an already bonded peer. + if (ok) { + // Allow pairing request from an already bonded peer. pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); } else { - // Allow or reject pairing request from an already bonded peer. + // Reject pairing request from an already bonded peer. pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false}; pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); } @@ -1031,7 +839,9 @@ int main(void) { peer_manager_init(); // Start execution. - advertising_start(true); + advertising_start(erase_bonds); + + send_initialized(); // Enter main loop. for (;;) { diff --git a/core/embed/extmod/modtrezorio/modtrezorio-ble.h b/core/embed/extmod/modtrezorio/modtrezorio-ble.h index a7d3e0da56..67765336a6 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-ble.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-ble.h @@ -72,7 +72,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_BLE_update_chunk_obj, STATIC mp_obj_t mod_trezorio_BLE_write(mp_obj_t self, mp_obj_t msg) { mp_buffer_info_t buf = {0}; mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); - ble_int_comm_send(buf.buf, buf.len, ble_last_internal); + ble_int_comm_send(buf.buf, buf.len, + ble_last_internal ? INTERNAL_MESSAGE : EXTERNAL_MESSAGE); return MP_OBJ_NEW_SMALL_INT(buf.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_BLE_write_obj, diff --git a/core/embed/extmod/modtrezorio/modtrezorio-poll.h b/core/embed/extmod/modtrezorio/modtrezorio-poll.h index 56ff16d461..e4ac9f016c 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-poll.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-poll.h @@ -20,11 +20,13 @@ #include #include "ble/comm.h" +#include "ble/state.h" #include "button.h" #include "common.h" #include "display.h" #include "embed/extmod/trezorobj.h" +#define BLE_EVENTS_IFACE (252) #define USB_DATA_IFACE (253) #define BUTTON_IFACE (254) #define TOUCH_IFACE (255) @@ -128,6 +130,15 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, ret->items[1] = usb_connected ? mp_const_true : mp_const_false; return mp_const_true; } + } else if (iface == BLE_EVENTS_IFACE) { + ble_int_comm_poll(); + uint8_t connected = ble_connected(); + if (connected != ble_connected_previously) { + ble_connected_previously = connected; + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = connected ? mp_const_true : mp_const_false; + return mp_const_true; + } } #endif #if USE_BUTTON diff --git a/core/embed/extmod/modtrezorio/modtrezorio.c b/core/embed/extmod/modtrezorio/modtrezorio.c index 7175cc1a37..cffe98e777 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio.c +++ b/core/embed/extmod/modtrezorio/modtrezorio.c @@ -34,6 +34,7 @@ // Whether USB data pins were connected on last check (USB configured) bool usb_connected_previously = true; +uint8_t ble_connected_previously = false; bool ble_last_internal = false; #define CHECK_PARAM_RANGE(value, minimum, maximum) \ @@ -120,6 +121,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_POLL_WRITE), MP_ROM_INT(POLL_WRITE)}, {MP_ROM_QSTR(MP_QSTR_USB_CHECK), MP_ROM_INT(USB_DATA_IFACE)}, + {MP_ROM_QSTR(MP_QSTR_BLE_CHECK), MP_ROM_INT(BLE_EVENTS_IFACE)}, }; STATIC MP_DEFINE_CONST_DICT(mp_module_trezorio_globals, diff --git a/core/embed/rust/Cargo.toml b/core/embed/rust/Cargo.toml index b473f3caaf..64e37e9e8e 100644 --- a/core/embed/rust/Cargo.toml +++ b/core/embed/rust/Cargo.toml @@ -23,6 +23,7 @@ clippy = [] jpeg = [] disp_i8080_8bit_dw = [] # write pixels directly to peripheral disp_i8080_16bit_dw = [] # write pixels directly to peripheral +ble = [] debug = ["ui_debug"] sbu = [] sd_card = [] diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 30a2885707..c348acc280 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -347,6 +347,8 @@ fn generate_trezorhal_bindings() { .no_copy("buffer_blurring_t") .allowlist_var("text_buffer_height") .allowlist_var("buffer_width") + // ble + .allowlist_function("ble_connected") //usb .allowlist_function("usb_configured") // touch diff --git a/core/embed/rust/src/trezorhal/ble.rs b/core/embed/rust/src/trezorhal/ble.rs new file mode 100644 index 0000000000..754070c8bd --- /dev/null +++ b/core/embed/rust/src/trezorhal/ble.rs @@ -0,0 +1,5 @@ +use super::ffi; + +pub fn ble_connected() -> bool { + unsafe { ffi::ble_connected() } +} diff --git a/core/embed/rust/src/trezorhal/mod.rs b/core/embed/rust/src/trezorhal/mod.rs index a3730ed730..c735de7d52 100644 --- a/core/embed/rust/src/trezorhal/mod.rs +++ b/core/embed/rust/src/trezorhal/mod.rs @@ -1,4 +1,6 @@ pub mod bip39; +#[cfg(feature = "ble")] +pub mod ble; #[macro_use] #[allow(unused_macros)] pub mod fatal_error; diff --git a/core/embed/rust/trezorhal.h b/core/embed/rust/trezorhal.h index 23ec6b5e61..615a2c3ecd 100644 --- a/core/embed/rust/trezorhal.h +++ b/core/embed/rust/trezorhal.h @@ -1,4 +1,5 @@ #include TREZOR_BOARD +#include "ble/state.h" #include "buffers.h" #include "button.h" #include "common.h" diff --git a/core/embed/trezorhal/ble/comm.c b/core/embed/trezorhal/ble/comm.c index 156bf391ac..d1bb4b37d2 100644 --- a/core/embed/trezorhal/ble/comm.c +++ b/core/embed/trezorhal/ble/comm.c @@ -21,8 +21,11 @@ #include TREZOR_BOARD #include "comm.h" +#include "int_comm_defs.h" +#include "state.h" static UART_HandleTypeDef urt; +static uint8_t last_init_byte = 0; void ble_comm_init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -46,6 +49,8 @@ void ble_comm_init(void) { urt.Instance = USART1; HAL_UART_Init(&urt); + + set_initialized(false); } void ble_comm_send(uint8_t *data, uint32_t len) { @@ -68,20 +73,13 @@ uint32_t ble_comm_receive(uint8_t *data, uint32_t len) { return 0; } -void ble_int_comm_send(uint8_t *data, uint32_t len, bool internal) { - uint16_t msg_len = len + 4; +void ble_int_comm_send(uint8_t *data, uint32_t len, uint8_t message_type) { + uint16_t msg_len = len + OVERHEAD_SIZE; uint8_t len_hi = msg_len >> 8; uint8_t len_lo = msg_len & 0xFF; - uint8_t eom = 0x55; + uint8_t eom = EOM; - uint8_t init_byte = 0; - if (internal) { - init_byte = 0xA0; - } else { - init_byte = 0xA1; - } - - HAL_UART_Transmit(&urt, &init_byte, 1, 1); + HAL_UART_Transmit(&urt, &message_type, 1, 1); HAL_UART_Transmit(&urt, &len_hi, 1, 1); HAL_UART_Transmit(&urt, &len_lo, 1, 1); @@ -89,13 +87,52 @@ void ble_int_comm_send(uint8_t *data, uint32_t len, bool internal) { HAL_UART_Transmit(&urt, &eom, 1, 1); } -uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal) { - data[0] = 0; +void process_poll(uint8_t *data, uint32_t len) { + uint8_t cmd = data[0]; + + switch (cmd) { + case INTERNAL_EVENT_INITIALIZED: { + set_connected(false); + set_initialized(true); + break; + } + case INTERNAL_EVENT_CONNECTED: { + set_connected(true); + set_initialized(true); + break; + } + case INTERNAL_EVENT_DISCONNECTED: { + set_connected(false); + set_initialized(true); + break; + } + default: + break; + } +} + +void flush_line(void) { + while (urt.Instance->SR & USART_SR_RXNE) { + (void)urt.Instance->DR; + } +} + +uint32_t ble_int_comm_poll(void) { + uint8_t data[64] = {0}; if (urt.Instance->SR & USART_SR_RXNE) { uint8_t init_byte = 0; - HAL_UART_Receive(&urt, &init_byte, 1, 1); - if (init_byte == 0xA0 || init_byte == 0xA1) { + if (last_init_byte != 0) { + if (last_init_byte == INTERNAL_EVENT) { + init_byte = last_init_byte; + } else { + return 0; + } + } else { + HAL_UART_Receive(&urt, &init_byte, 1, 1); + } + + if (init_byte == INTERNAL_EVENT) { uint8_t len_hi = 0; uint8_t len_lo = 0; HAL_UART_Receive(&urt, &len_hi, 1, 1); @@ -103,28 +140,104 @@ uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal) { uint16_t act_len = (len_hi << 8) | len_lo; - HAL_StatusTypeDef result = HAL_UART_Receive(&urt, data, act_len - 4, 5); + if (act_len > sizeof(data) + OVERHEAD_SIZE) { + last_init_byte = 0; + flush_line(); + return 0; + } + + HAL_StatusTypeDef result = + HAL_UART_Receive(&urt, data, act_len - OVERHEAD_SIZE, 5); if (result != HAL_OK) { + last_init_byte = 0; + flush_line(); return 0; } uint8_t eom = 0; HAL_UART_Receive(&urt, &eom, 1, 1); - if (eom == 0x55) { - if (init_byte == 0xA0) { + if (eom == EOM) { + process_poll(data, act_len - OVERHEAD_SIZE); + last_init_byte = 0; + return act_len - OVERHEAD_SIZE; + } + return 0; + + } else if (init_byte == INTERNAL_MESSAGE || init_byte == EXTERNAL_MESSAGE) { + last_init_byte = init_byte; + } else { + flush_line(); + } + return 0; + } + + if (!ble_initialized()) { + uint8_t cmd = INTERNAL_CMD_SEND_STATE; + ble_int_comm_send(&cmd, sizeof(cmd), INTERNAL_EVENT); + } + + return 0; +} + +uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal) { + if (urt.Instance->SR & USART_SR_RXNE) { + uint8_t init_byte = 0; + + if (last_init_byte != 0) { + if (last_init_byte == INTERNAL_MESSAGE || + last_init_byte == EXTERNAL_MESSAGE) { + init_byte = last_init_byte; + } else { + return 0; + } + + } else { + HAL_UART_Receive(&urt, &init_byte, 1, 1); + } + + if (init_byte == INTERNAL_MESSAGE || init_byte == EXTERNAL_MESSAGE) { + uint8_t len_hi = 0; + uint8_t len_lo = 0; + HAL_UART_Receive(&urt, &len_hi, 1, 1); + HAL_UART_Receive(&urt, &len_lo, 1, 1); + + uint16_t act_len = (len_hi << 8) | len_lo; + + if (act_len > len + OVERHEAD_SIZE) { + last_init_byte = 0; + flush_line(); + return 0; + } + + HAL_StatusTypeDef result = + HAL_UART_Receive(&urt, data, act_len - OVERHEAD_SIZE, 5); + + if (result != HAL_OK) { + last_init_byte = 0; + flush_line(); + return 0; + } + + uint8_t eom = 0; + HAL_UART_Receive(&urt, &eom, 1, 1); + + if (eom == EOM) { + if (init_byte == INTERNAL_MESSAGE) { *internal = true; } else { *internal = false; } - return act_len - 4; + last_init_byte = 0; + return act_len - OVERHEAD_SIZE; } return 0; + } else if (init_byte == INTERNAL_EVENT) { + last_init_byte = init_byte; } else { - // disregard byte. - // todo: flush everything on the line, also for other errors + flush_line(); return 0; } } diff --git a/core/embed/trezorhal/ble/comm.h b/core/embed/trezorhal/ble/comm.h index b5019f95e1..98716d09b0 100644 --- a/core/embed/trezorhal/ble/comm.h +++ b/core/embed/trezorhal/ble/comm.h @@ -1,9 +1,18 @@ + +#ifndef __BLE_COMM_H__ +#define __BLE_COMM_H__ + #include +#include "int_comm_defs.h" void ble_comm_init(void); void ble_comm_send(uint8_t *data, uint32_t len); uint32_t ble_comm_receive(uint8_t *data, uint32_t len); -void ble_int_comm_send(uint8_t *data, uint32_t len, bool internal); +void ble_int_comm_send(uint8_t *data, uint32_t len, uint8_t message_type); uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal); + +uint32_t ble_int_comm_poll(void); + +#endif diff --git a/core/embed/trezorhal/ble/int_comm_defs.h b/core/embed/trezorhal/ble/int_comm_defs.h new file mode 100644 index 0000000000..0758cf8920 --- /dev/null +++ b/core/embed/trezorhal/ble/int_comm_defs.h @@ -0,0 +1,20 @@ + +#ifndef __INT_COMM_DEFS__ +#define __INT_COMM_DEFS__ + +#define COMM_HEADER_SIZE (3) +#define COMM_FOOTER_SIZE (1) +#define OVERHEAD_SIZE (COMM_HEADER_SIZE + COMM_FOOTER_SIZE) + +#define EOM (0x55) +#define INTERNAL_EVENT (0xA2) +#define EXTERNAL_MESSAGE (0xA1) +#define INTERNAL_MESSAGE (0xA0) + +#define INTERNAL_EVENT_INITIALIZED (0x00) +#define INTERNAL_EVENT_CONNECTED (0x01) +#define INTERNAL_EVENT_DISCONNECTED (0x02) + +#define INTERNAL_CMD_SEND_STATE (0x00) + +#endif diff --git a/core/embed/trezorhal/ble/state.c b/core/embed/trezorhal/ble/state.c new file mode 100644 index 0000000000..33965a48dd --- /dev/null +++ b/core/embed/trezorhal/ble/state.c @@ -0,0 +1,14 @@ + + +#include "ble/state.h" + +static bool ble_state_connected = false; +static bool ble_state_initialized = false; + +bool ble_connected(void) { return ble_state_connected; } + +void set_connected(bool connected) { ble_state_connected = connected; } + +void set_initialized(bool initialized) { ble_state_initialized = initialized; } + +bool ble_initialized(void) { return ble_state_initialized; } diff --git a/core/embed/trezorhal/ble/state.h b/core/embed/trezorhal/ble/state.h new file mode 100644 index 0000000000..98f38d30ac --- /dev/null +++ b/core/embed/trezorhal/ble/state.h @@ -0,0 +1,16 @@ + +#ifndef __BLE_STATE__ +#define __BLE_STATE__ + +#include +#include + +bool ble_initialized(void); + +void set_initialized(bool initialized); + +bool ble_connected(void); + +void set_connected(bool connected); + +#endif diff --git a/core/embed/unix/ble/state.c b/core/embed/unix/ble/state.c new file mode 100644 index 0000000000..33965a48dd --- /dev/null +++ b/core/embed/unix/ble/state.c @@ -0,0 +1,14 @@ + + +#include "ble/state.h" + +static bool ble_state_connected = false; +static bool ble_state_initialized = false; + +bool ble_connected(void) { return ble_state_connected; } + +void set_connected(bool connected) { ble_state_connected = connected; } + +void set_initialized(bool initialized) { ble_state_initialized = initialized; } + +bool ble_initialized(void) { return ble_state_initialized; } diff --git a/core/embed/unix/ble/state.h b/core/embed/unix/ble/state.h new file mode 100644 index 0000000000..98f38d30ac --- /dev/null +++ b/core/embed/unix/ble/state.h @@ -0,0 +1,16 @@ + +#ifndef __BLE_STATE__ +#define __BLE_STATE__ + +#include +#include + +bool ble_initialized(void); + +void set_initialized(bool initialized); + +bool ble_connected(void); + +void set_connected(bool connected); + +#endif