From e402adc13e4bf80af7f648f4c736e00127b48de6 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 19 Apr 2023 15:30:31 +0200 Subject: [PATCH] feat(core/ble): improved cooperation between stm and nrf, divided ble_firmware source files [no changelog] --- core/SConscript.ble_firmware | 4 + core/embed/ble_firmware/advertising.c | 196 ++++++++++++ core/embed/ble_firmware/advertising.h | 16 + core/embed/ble_firmware/connection.c | 10 + core/embed/ble_firmware/connection.h | 9 + core/embed/ble_firmware/defs.h | 3 + core/embed/ble_firmware/dis.h | 2 - core/embed/ble_firmware/int_comm.c | 47 ++- core/embed/ble_firmware/int_comm.h | 7 +- core/embed/ble_firmware/main.c | 376 ++--------------------- core/embed/ble_firmware/pm.c | 155 ++++++++++ core/embed/ble_firmware/pm.h | 18 ++ core/embed/ble_firmware/power.c | 21 ++ core/embed/ble_firmware/power.h | 6 + core/embed/bootloader/main.c | 53 ++-- core/embed/firmware/main.c | 6 + core/embed/trezorhal/ble/comm.c | 24 +- core/embed/trezorhal/ble/int_comm_defs.h | 13 +- core/embed/trezorhal/ble/messages.c | 20 ++ core/embed/trezorhal/ble/messages.h | 10 + core/embed/trezorhal/ble/state.c | 28 ++ core/embed/trezorhal/ble/state.h | 6 + core/site_scons/boards/discovery.py | 1 + 23 files changed, 603 insertions(+), 428 deletions(-) create mode 100644 core/embed/ble_firmware/advertising.c create mode 100644 core/embed/ble_firmware/advertising.h create mode 100644 core/embed/ble_firmware/connection.c create mode 100644 core/embed/ble_firmware/connection.h create mode 100644 core/embed/ble_firmware/defs.h create mode 100644 core/embed/ble_firmware/pm.c create mode 100644 core/embed/ble_firmware/pm.h create mode 100644 core/embed/ble_firmware/power.c create mode 100644 core/embed/ble_firmware/power.h create mode 100644 core/embed/trezorhal/ble/messages.c create mode 100644 core/embed/trezorhal/ble/messages.h diff --git a/core/SConscript.ble_firmware b/core/SConscript.ble_firmware index e55fad3c9..d8deceaf8 100644 --- a/core/SConscript.ble_firmware +++ b/core/SConscript.ble_firmware @@ -287,6 +287,10 @@ SOURCE_BLE_FIRMWARE = [ 'embed/ble_firmware/ble_nus.c', 'embed/ble_firmware/int_comm.c', 'embed/ble_firmware/dis.c', + 'embed/ble_firmware/pm.c', + 'embed/ble_firmware/power.c', + 'embed/ble_firmware/advertising.c', + 'embed/ble_firmware/connection.c', 'embed/bootloader/protob/messages.pb.c', 'embed/lib/protob_helpers.c', ] diff --git a/core/embed/ble_firmware/advertising.c b/core/embed/ble_firmware/advertising.c new file mode 100644 index 000000000..e5a01a242 --- /dev/null +++ b/core/embed/ble_firmware/advertising.c @@ -0,0 +1,196 @@ +#include "ble_gap.h" + +#include "advertising.h" +#include "ble_advdata.h" +#include "ble_advertising.h" +#include "ble_nus.h" +#include "bsp.h" +#include "bsp_btn_ble.h" +#include "connection.h" +#include "defs.h" +#include "nrf_log.h" +#include "pm.h" +#include "power.h" + +#define APP_ADV_INTERVAL \ + 64 /**< The advertising interval (in units of 0.625 ms. This value \ + corresponds to 40 ms). */ + +#define APP_ADV_DURATION \ + 18000 /**< The advertising duration (180 seconds) in units of 10 \ + milliseconds. */ + +#define NUS_SERVICE_UUID_TYPE \ + BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service \ + (vendor specific). */ + +static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ + {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; + +BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ + +/**@brief Function for handling advertising events. + * + * @details This function will be called for advertising events which are passed + * to the application. + * + * @param[in] ble_adv_evt Advertising event. + */ +static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { + uint32_t err_code; + + switch (ble_adv_evt) { + case BLE_ADV_EVT_DIRECTED_HIGH_DUTY: + NRF_LOG_INFO("High Duty Directed advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_DIRECTED: + NRF_LOG_INFO("Directed advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_FAST: + NRF_LOG_INFO("Fast advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_SLOW: + NRF_LOG_INFO("Slow advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_SLOW); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_FAST_WHITELIST: + NRF_LOG_INFO("Fast advertising with whitelist."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_SLOW_WHITELIST: + NRF_LOG_INFO("Slow advertising with whitelist."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_IDLE: + // sleep_mode_enter(); + break; + + case BLE_ADV_EVT_WHITELIST_REQUEST: { + ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks, + &irk_cnt); + APP_ERROR_CHECK(err_code); + NRF_LOG_DEBUG( + "pm_whitelist_get returns %d addr in whitelist and %d irk whitelist", + addr_cnt, irk_cnt); + + // Set the correct identities list (no excluding peers with no Central + // Address Resolution). + identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK); + + // Apply the whitelist. + err_code = ble_advertising_whitelist_reply( + &m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt); + APP_ERROR_CHECK(err_code); + } break; // BLE_ADV_EVT_WHITELIST_REQUEST + + case BLE_ADV_EVT_PEER_ADDR_REQUEST: { + pm_peer_data_bonding_t peer_bonding_data; + + // Only Give peer address if we have a handle to the bonded peer. + if (get_peer_id() != PM_PEER_ID_INVALID) { + err_code = pm_peer_data_bonding_load(get_peer_id(), &peer_bonding_data); + if (err_code != NRF_ERROR_NOT_FOUND) { + APP_ERROR_CHECK(err_code); + + // Manipulate identities to exclude peers with no Central Address + // Resolution. + identities_set(PM_PEER_ID_LIST_SKIP_ALL); + + ble_gap_addr_t *p_peer_addr = + &(peer_bonding_data.peer_ble_id.id_addr_info); + err_code = + ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr); + APP_ERROR_CHECK(err_code); + } + } + } break; // BLE_ADV_EVT_PEER_ADDR_REQUEST + + default: + break; + } +} + +void advertising_init(void) { + uint32_t err_code; + uint8_t adv_flags; + ble_advertising_init_t init; + + memset(&init, 0, sizeof(init)); + + adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.include_appearance = true; + init.advdata.flags = adv_flags; + init.advdata.uuids_complete.uuid_cnt = + sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + init.advdata.uuids_complete.p_uuids = m_adv_uuids; + + init.config.ble_adv_whitelist_enabled = true; + init.config.ble_adv_directed_high_duty_enabled = true; + init.config.ble_adv_directed_enabled = false; + init.config.ble_adv_directed_interval = 0; + init.config.ble_adv_directed_timeout = 0; + init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; + init.config.ble_adv_fast_timeout = APP_ADV_DURATION; + + init.evt_handler = on_adv_evt; + + err_code = ble_advertising_init(&m_advertising, &init); + APP_ERROR_CHECK(err_code); + + ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); +} + +void advertising_start(bool whitelist) { + m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = false; + if (m_advertising.adv_mode_current != BLE_ADV_MODE_FAST && + get_connection_handle() == BLE_CONN_HANDLE_INVALID) { + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + + ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + APP_ERROR_CHECK(ret); + } + + if (!whitelist) { + ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising); + APP_ERROR_CHECK(ret); + } +} + +void advertising_stop(void) { + m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = true; + ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE); + APP_ERROR_CHECK(ret); + // ret =sd_ble_gap_disconnect(get_connection_handle(), + // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(ret); +} + +void advertising_restart_without_whitelist(void) { + ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising); + APP_ERROR_CHECK(ret); +} + +bool is_advertising(void) { + return m_advertising.adv_mode_current != BLE_ADV_MODE_IDLE; +} diff --git a/core/embed/ble_firmware/advertising.h b/core/embed/ble_firmware/advertising.h new file mode 100644 index 000000000..b51c85e3b --- /dev/null +++ b/core/embed/ble_firmware/advertising.h @@ -0,0 +1,16 @@ +#ifndef __ADVERTISING__ +#define __ADVERTISING__ + +#include + +void advertising_init(void); + +void advertising_start(bool whitelist); + +void advertising_stop(void); + +void advertising_restart_without_whitelist(void); + +bool is_advertising(void); + +#endif diff --git a/core/embed/ble_firmware/connection.c b/core/embed/ble_firmware/connection.c new file mode 100644 index 000000000..f38e419bf --- /dev/null +++ b/core/embed/ble_firmware/connection.c @@ -0,0 +1,10 @@ + +#include "ble_gap.h" + +#include "connection.h" + +static uint16_t m_conn_handle = + BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ + +void set_connection_handle(uint16_t val) { m_conn_handle = val; } +uint16_t get_connection_handle(void) { return m_conn_handle; } diff --git a/core/embed/ble_firmware/connection.h b/core/embed/ble_firmware/connection.h new file mode 100644 index 000000000..81d39b149 --- /dev/null +++ b/core/embed/ble_firmware/connection.h @@ -0,0 +1,9 @@ +#ifndef BLE_CONNECTION_H__ +#define BLE_CONNECTION_H__ + +#include + +void set_connection_handle(uint16_t val); +uint16_t get_connection_handle(void); + +#endif diff --git a/core/embed/ble_firmware/defs.h b/core/embed/ble_firmware/defs.h new file mode 100644 index 000000000..b2e354d3c --- /dev/null +++ b/core/embed/ble_firmware/defs.h @@ -0,0 +1,3 @@ + +#define APP_BLE_CONN_CFG_TAG \ + 1 /**< A tag identifying the SoftDevice BLE configuration. */ diff --git a/core/embed/ble_firmware/dis.h b/core/embed/ble_firmware/dis.h index 1154c99e5..ad88ffd9a 100644 --- a/core/embed/ble_firmware/dis.h +++ b/core/embed/ble_firmware/dis.h @@ -1,5 +1,3 @@ - - #ifndef __DIS__ #define __DIS__ diff --git a/core/embed/ble_firmware/int_comm.c b/core/embed/ble_firmware/int_comm.c index 90a473e93..f0db42095 100644 --- a/core/embed/ble_firmware/int_comm.c +++ b/core/embed/ble_firmware/int_comm.c @@ -1,11 +1,15 @@ #include "int_comm.h" +#include "advertising.h" #include "app_error.h" #include "app_uart.h" +#include "ble_advertising.h" #include "ble_nus.h" +#include "connection.h" #include "messages.pb.h" #include "nrf_drv_spi.h" #include "nrf_log.h" +#include "pm.h" #include "protob_helpers.h" #include "stdint.h" #include "trezorhal/ble/int_comm_defs.h" @@ -19,7 +23,6 @@ static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN]; static uint8_t m_spi_tx_data[BLE_PACKET_SIZE]; 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. */ @@ -48,8 +51,7 @@ void spi_init(void) { APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL)); } -void nus_init(uint16_t *p_conn_handle) { - m_p_conn_handle = p_conn_handle; +void nus_init() { uint32_t err_code; ble_nus_init_t nus_init; @@ -60,8 +62,6 @@ void nus_init(uint16_t *p_conn_handle) { err_code = ble_nus_init(&m_nus, &nus_init); APP_ERROR_CHECK(err_code); - - *p_conn_handle = BLE_CONN_HANDLE_INVALID; } void send_byte(uint8_t byte) { @@ -177,11 +177,15 @@ 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(); - } + send_status_event(); + break; + case INTERNAL_CMD_ADVERTISING_ON: + advertising_start(true); + send_status_event(); + break; + case INTERNAL_CMD_ADVERTISING_OFF: + advertising_stop(); + send_status_event(); break; default: break; @@ -289,7 +293,7 @@ void uart_event_handle(app_uart_evt_t *p_event) { 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); + get_connection_handle()); if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND)) { @@ -341,16 +345,12 @@ void nus_data_handler(ble_nus_evt_t *p_evt) { } /**@snippet [Handling the data received over BLE] */ -void send_connected_event(void) { +void send_status_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, + INTERNAL_EVENT_STATUS, + (get_connection_handle() != BLE_CONN_HANDLE_INVALID) ? 1 + : 0, // connected + is_advertising() ? 1 : 0, // advertising }; send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data)); } @@ -415,10 +415,3 @@ bool send_repair_request(void) { return result == sectrue; } - -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 index 1fed59e18..180ed9f78 100644 --- a/core/embed/ble_firmware/int_comm.h +++ b/core/embed/ble_firmware/int_comm.h @@ -1,4 +1,3 @@ - #ifndef __INT_COMM__ #define __INT_COMM__ @@ -8,15 +7,13 @@ void spi_init(void); -void nus_init(uint16_t *p_conn_handle); +void nus_init(void); 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); +void send_status_event(void); bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len); diff --git a/core/embed/ble_firmware/main.c b/core/embed/ble_firmware/main.c index 8f2f79df7..6a893f229 100644 --- a/core/embed/ble_firmware/main.c +++ b/core/embed/ble_firmware/main.c @@ -56,23 +56,17 @@ #include "app_timer.h" #include "app_uart.h" #include "app_util_platform.h" -#include "ble_advdata.h" -#include "ble_advertising.h" #include "ble_conn_params.h" #include "ble_hci.h" -#include "ble_nus.h" #include "bsp_btn_ble.h" #include "nordic_common.h" #include "nrf.h" #include "nrf_ble_gatt.h" #include "nrf_ble_qwr.h" -#include "nrf_drv_spi.h" #include "nrf_pwr_mgmt.h" #include "nrf_sdh.h" #include "nrf_sdh_ble.h" #include "nrf_sdh_soc.h" -#include "peer_manager.h" -#include "peer_manager_handler.h" #if defined(UART_PRESENT) #include "nrf_uart.h" @@ -85,31 +79,23 @@ #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" +#include "advertising.h" +#include "ble_nus.h" +#include "connection.h" +#include "defs.h" #include "dis.h" #include "int_comm.h" - -#define APP_BLE_CONN_CFG_TAG \ - 1 /**< A tag identifying the SoftDevice BLE configuration. */ +#include "pm.h" +#include "power.h" #define DEVICE_NAME \ "Trezor" /**< Name of device. Will be included in the advertising data. \ */ -#define NUS_SERVICE_UUID_TYPE \ - BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service \ - (vendor specific). */ #define APP_BLE_OBSERVER_PRIO \ 3 /**< Application's BLE observer priority. You shouldn't need to modify \ this value. */ -#define APP_ADV_INTERVAL \ - 64 /**< The advertising interval (in units of 0.625 ms. This value \ - corresponds to 40 ms). */ - -#define APP_ADV_DURATION \ - 18000 /**< The advertising duration (180 seconds) in units of 10 \ - milliseconds. */ - #define MIN_CONN_INTERVAL \ MSEC_TO_UNITS( \ 7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), \ @@ -143,19 +129,8 @@ #define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ #define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ -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. */ +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ +NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ #define SCHED_MAX_EVENT_DATA_SIZE \ APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */ @@ -168,16 +143,10 @@ BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ 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 = - BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ -static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ - {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; /**@brief Function for assert macro callback. * @@ -258,7 +227,7 @@ static void services_init(void) { APP_ERROR_CHECK(err_code); dis_init(); - nus_init(&m_conn_handle); + nus_init(); } /**@brief Function for handling errors from the Connection Parameters module. @@ -291,141 +260,6 @@ static void conn_params_init(void) { APP_ERROR_CHECK(err_code); } -/**@brief Function for putting the chip into sleep mode. - * - * @note This function will not return. - */ -static void sleep_mode_enter(void) { - uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); - APP_ERROR_CHECK(err_code); - - // Prepare wakeup buttons. - err_code = bsp_btn_ble_sleep_mode_prepare(); - APP_ERROR_CHECK(err_code); - - // Go to system-off mode (this function will not return; wakeup will cause a - // reset). - err_code = sd_power_system_off(); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for setting filtered device identities. - * - * @param[in] skip Filter passed to @ref pm_peer_id_list. - */ -static void identities_set(pm_peer_id_list_skip_t skip) { - pm_peer_id_t peer_ids[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; - uint32_t peer_id_count = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; - - ret_code_t err_code = - pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); - APP_ERROR_CHECK(err_code); - - err_code = pm_device_identities_list_set(peer_ids, peer_id_count); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling advertising events. - * - * @details This function will be called for advertising events which are passed - * to the application. - * - * @param[in] ble_adv_evt Advertising event. - */ -static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { - uint32_t err_code; - - switch (ble_adv_evt) { - case BLE_ADV_EVT_DIRECTED_HIGH_DUTY: - NRF_LOG_INFO("High Duty Directed advertising."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_DIRECTED: - NRF_LOG_INFO("Directed advertising."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_FAST: - NRF_LOG_INFO("Fast advertising."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_SLOW: - NRF_LOG_INFO("Slow advertising."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_SLOW); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_FAST_WHITELIST: - NRF_LOG_INFO("Fast advertising with whitelist."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_SLOW_WHITELIST: - NRF_LOG_INFO("Slow advertising with whitelist."); - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); - APP_ERROR_CHECK(err_code); - break; - - case BLE_ADV_EVT_IDLE: - sleep_mode_enter(); - break; - - case BLE_ADV_EVT_WHITELIST_REQUEST: { - ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; - uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; - - err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks, - &irk_cnt); - APP_ERROR_CHECK(err_code); - NRF_LOG_DEBUG( - "pm_whitelist_get returns %d addr in whitelist and %d irk whitelist", - addr_cnt, irk_cnt); - - // Set the correct identities list (no excluding peers with no Central - // Address Resolution). - identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK); - - // Apply the whitelist. - err_code = ble_advertising_whitelist_reply( - &m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt); - APP_ERROR_CHECK(err_code); - } break; // BLE_ADV_EVT_WHITELIST_REQUEST - - case BLE_ADV_EVT_PEER_ADDR_REQUEST: { - pm_peer_data_bonding_t peer_bonding_data; - - // Only Give peer address if we have a handle to the bonded peer. - if (m_peer_id != PM_PEER_ID_INVALID) { - err_code = pm_peer_data_bonding_load(m_peer_id, &peer_bonding_data); - if (err_code != NRF_ERROR_NOT_FOUND) { - APP_ERROR_CHECK(err_code); - - // Manipulate identities to exclude peers with no Central Address - // Resolution. - identities_set(PM_PEER_ID_LIST_SKIP_ALL); - - ble_gap_addr_t *p_peer_addr = - &(peer_bonding_data.peer_ble_id.id_addr_info); - err_code = - ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr); - APP_ERROR_CHECK(err_code); - } - } - } break; // BLE_ADV_EVT_PEER_ADDR_REQUEST - - default: - break; - } -} - /**@brief Function for handling BLE events. * * @param[in] p_ble_evt Bluetooth stack event. @@ -440,17 +274,18 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { 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); + uint16_t handle = p_ble_evt->evt.gap_evt.conn_handle; + set_connection_handle(handle); + send_status_event(); + err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, handle); APP_ERROR_CHECK(err_code); break; 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; + bsp_indication_set(BSP_INDICATE_IDLE); + send_status_event(); + set_connection_handle(BLE_CONN_HANDLE_INVALID); break; case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { @@ -533,7 +368,7 @@ static void ble_stack_init(void) { /**@brief Function for handling events from the GATT library. */ void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt) { - if ((m_conn_handle == p_evt->conn_handle) && + if ((get_connection_handle() == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; @@ -570,18 +405,15 @@ void bsp_event_handler(bsp_event_t event) { case BSP_EVENT_DISCONNECT: err_code = sd_ble_gap_disconnect( - m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + get_connection_handle(), BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } break; case BSP_EVENT_WHITELIST_OFF: - if (m_conn_handle == BLE_CONN_HANDLE_INVALID) { - err_code = ble_advertising_restart_without_whitelist(&m_advertising); - if (err_code != NRF_ERROR_INVALID_STATE) { - APP_ERROR_CHECK(err_code); - } + if (get_connection_handle() == BLE_CONN_HANDLE_INVALID) { + advertising_restart_without_whitelist(); } break; @@ -615,38 +447,6 @@ static void uart_init(void) { } /**@snippet [UART Initialization] */ -static void advertising_init(void) { - uint32_t err_code; - uint8_t adv_flags; - ble_advertising_init_t init; - - memset(&init, 0, sizeof(init)); - - adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - init.advdata.name_type = BLE_ADVDATA_FULL_NAME; - init.advdata.include_appearance = true; - init.advdata.flags = adv_flags; - init.advdata.uuids_complete.uuid_cnt = - sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.advdata.uuids_complete.p_uuids = m_adv_uuids; - - init.config.ble_adv_whitelist_enabled = true; - init.config.ble_adv_directed_high_duty_enabled = true; - init.config.ble_adv_directed_enabled = false; - init.config.ble_adv_directed_interval = 0; - init.config.ble_adv_directed_timeout = 0; - init.config.ble_adv_fast_enabled = true; - init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; - init.config.ble_adv_fast_timeout = APP_ADV_DURATION; - - init.evt_handler = on_adv_evt; - - err_code = ble_advertising_init(&m_advertising, &init); - APP_ERROR_CHECK(err_code); - - ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); -} - /**@brief Function for initializing buttons and leds. * * @param[out] p_erase_bonds Will be true if the clear bonding button was @@ -694,135 +494,6 @@ static void idle_state_handle(void) { } } -/**@brief Function for setting filtered whitelist. - * - * @param[in] skip Filter passed to @ref pm_peer_id_list. - */ -static void whitelist_set(pm_peer_id_list_skip_t skip) { - pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - uint32_t peer_id_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; - - ret_code_t err_code = - pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); - APP_ERROR_CHECK(err_code); - - NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d", - peer_id_count + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT); - - err_code = pm_whitelist_set(peer_ids, peer_id_count); - APP_ERROR_CHECK(err_code); -} - -///**@brief Clear bond information from persistent storage. */ -static void delete_bonds(void) { - ret_code_t err_code; - - NRF_LOG_INFO("Erase bonds!"); - - err_code = pm_peers_delete(); - APP_ERROR_CHECK(err_code); -} - -static void advertising_start(bool erase_bonds) { - if (erase_bonds == true) { - delete_bonds(); - // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. - } else { - whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); - - ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); - APP_ERROR_CHECK(ret); - } -} - -/**@brief Function for handling Peer Manager events. - * - * @param[in] p_evt Peer Manager event. - */ -static void pm_evt_handler(pm_evt_t const *p_evt) { - pm_handler_on_pm_evt(p_evt); - pm_handler_disconnect_on_sec_failure(p_evt); - pm_handler_flash_clean(p_evt); - - switch (p_evt->evt_id) { - case PM_EVT_CONN_SEC_SUCCEEDED: - m_peer_id = p_evt->peer_id; - break; - - case PM_EVT_PEERS_DELETE_SUCCEEDED: - advertising_start(false); - break; - - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_evt->params.peer_data_update_succeeded.flash_changed && - (p_evt->params.peer_data_update_succeeded.data_id == - PM_PEER_DATA_ID_BONDING)) { - NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible"); - // Note: You should check on what kind of white list policy your - // application should use. - - whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); - } - break; - case PM_EVT_CONN_SEC_CONFIG_REQ: { - bool ok = send_repair_request(); - - 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 { - // 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); - } - - } break; - default: - break; - } -} - -/**@brief Function for the Peer Manager initialization. - */ -static void peer_manager_init(void) { - ble_gap_sec_params_t sec_param; - pm_privacy_params_t privacy_params; - ret_code_t err_code; - - err_code = pm_init(); - APP_ERROR_CHECK(err_code); - - memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); - - // Security parameters to be used for all security procedures. - sec_param.bond = SEC_PARAM_BOND; - sec_param.mitm = SEC_PARAM_MITM; - sec_param.lesc = SEC_PARAM_LESC; - sec_param.keypress = SEC_PARAM_KEYPRESS; - sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; - sec_param.oob = SEC_PARAM_OOB; - sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; - sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; - sec_param.kdist_own.enc = 1; - sec_param.kdist_own.id = 1; - sec_param.kdist_peer.enc = 1; - sec_param.kdist_peer.id = 1; - - err_code = pm_sec_params_set(&sec_param); - APP_ERROR_CHECK(err_code); - - privacy_params.p_device_irk = NULL; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - privacy_params.private_addr_cycle_s = 0; - privacy_params.private_addr_type = - BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - pm_privacy_set(&privacy_params); - - err_code = pm_register(pm_evt_handler); - APP_ERROR_CHECK(err_code); -} - /**@brief Function for the Event Scheduler initialization. */ static void scheduler_init(void) { @@ -850,10 +521,11 @@ int main(void) { conn_params_init(); peer_manager_init(); - // Start execution. - advertising_start(erase_bonds); + send_status_event(); - send_initialized(); + if (erase_bonds) { + delete_bonds(); + } // Enter main loop. for (;;) { diff --git a/core/embed/ble_firmware/pm.c b/core/embed/ble_firmware/pm.c new file mode 100644 index 000000000..afc43a8ae --- /dev/null +++ b/core/embed/ble_firmware/pm.c @@ -0,0 +1,155 @@ + + +#include "nrf_log.h" +#include "peer_manager_handler.h" + +#include "int_comm.h" +#include "pm.h" + +#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. */ + +static pm_peer_id_t + m_peer_id; /**< Device reference handle to the current bonded central. */ + +pm_peer_id_t get_peer_id(void) { return m_peer_id; } + +/**@brief Function for setting filtered whitelist. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. + */ +void whitelist_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); + APP_ERROR_CHECK(err_code); + + NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d", + peer_id_count + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT); + + err_code = pm_whitelist_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling Peer Manager events. + * + * @param[in] p_evt Peer Manager event. + */ +void pm_evt_handler(pm_evt_t const *p_evt) { + pm_handler_on_pm_evt(p_evt); + pm_handler_disconnect_on_sec_failure(p_evt); + pm_handler_flash_clean(p_evt); + + switch (p_evt->evt_id) { + case PM_EVT_CONN_SEC_SUCCEEDED: + m_peer_id = p_evt->peer_id; + break; + + case PM_EVT_PEERS_DELETE_SUCCEEDED: + // advertising_start(false); + break; + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_evt->params.peer_data_update_succeeded.flash_changed && + (p_evt->params.peer_data_update_succeeded.data_id == + PM_PEER_DATA_ID_BONDING)) { + NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible"); + // Note: You should check on what kind of white list policy your + // application should use. + + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + } + break; + case PM_EVT_CONN_SEC_CONFIG_REQ: { + bool ok = send_repair_request(); + + 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 { + // 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); + } + + } break; + default: + break; + } +} + +/**@brief Function for the Peer Manager initialization. + */ +void peer_manager_init(void) { + ble_gap_sec_params_t sec_param; + pm_privacy_params_t privacy_params; + ret_code_t err_code; + + err_code = pm_init(); + APP_ERROR_CHECK(err_code); + + memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); + + // Security parameters to be used for all security procedures. + sec_param.bond = SEC_PARAM_BOND; + sec_param.mitm = SEC_PARAM_MITM; + sec_param.lesc = SEC_PARAM_LESC; + sec_param.keypress = SEC_PARAM_KEYPRESS; + sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; + sec_param.oob = SEC_PARAM_OOB; + sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; + sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; + sec_param.kdist_own.enc = 1; + sec_param.kdist_own.id = 1; + sec_param.kdist_peer.enc = 1; + sec_param.kdist_peer.id = 1; + + err_code = pm_sec_params_set(&sec_param); + APP_ERROR_CHECK(err_code); + + privacy_params.p_device_irk = NULL; + privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; + privacy_params.private_addr_cycle_s = 0; + privacy_params.private_addr_type = + BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; + pm_privacy_set(&privacy_params); + + err_code = pm_register(pm_evt_handler); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for setting filtered device identities. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. + */ +void identities_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); + APP_ERROR_CHECK(err_code); + + err_code = pm_device_identities_list_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + +/////**@brief Clear bond information from persistent storage. */ +void delete_bonds(void) { + ret_code_t err_code; + + NRF_LOG_INFO("Erase bonds!"); + + err_code = pm_peers_delete(); + APP_ERROR_CHECK(err_code); +} diff --git a/core/embed/ble_firmware/pm.h b/core/embed/ble_firmware/pm.h new file mode 100644 index 000000000..cfe9e6193 --- /dev/null +++ b/core/embed/ble_firmware/pm.h @@ -0,0 +1,18 @@ +#ifndef __PEER_MANAGER__ +#define __PEER_MANAGER__ + +#include "peer_manager.h" + +pm_peer_id_t get_peer_id(void); + +void whitelist_set(pm_peer_id_list_skip_t skip); + +void identities_set(pm_peer_id_list_skip_t skip); + +/**@brief Function for the Peer Manager initialization. + */ +void peer_manager_init(void); + +void delete_bonds(void); + +#endif diff --git a/core/embed/ble_firmware/power.c b/core/embed/ble_firmware/power.c new file mode 100644 index 000000000..3fc1199ef --- /dev/null +++ b/core/embed/ble_firmware/power.c @@ -0,0 +1,21 @@ +#include "power.h" +#include "app_error.h" +#include "bsp_btn_ble.h" + +/**@brief Function for putting the chip into sleep mode. + * + * @note This function will not return. + */ +void sleep_mode_enter(void) { + uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); + APP_ERROR_CHECK(err_code); + + // Prepare wakeup buttons. + err_code = bsp_btn_ble_sleep_mode_prepare(); + APP_ERROR_CHECK(err_code); + + // Go to system-off mode (this function will not return; wakeup will cause a + // reset). + err_code = sd_power_system_off(); + APP_ERROR_CHECK(err_code); +} diff --git a/core/embed/ble_firmware/power.h b/core/embed/ble_firmware/power.h new file mode 100644 index 000000000..ac1f8965d --- /dev/null +++ b/core/embed/ble_firmware/power.h @@ -0,0 +1,6 @@ +#ifndef __POWER__ +#define __POWER__ + +void sleep_mode_enter(void); + +#endif diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 779d64952..d2b3346c0 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -51,6 +51,7 @@ #endif #ifdef USE_BLE #include "ble/comm.h" +#include "ble/state.h" #endif #include "usb.h" @@ -123,11 +124,27 @@ static void usb_init_all(secbool usb21_landing) { usb_start(); } -static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, - const image_header *const hdr) { +void start_comm(secbool usb21_landing) { // if both are NULL, we don't have a firmware installed // let's show a webusb landing page in this case - usb_init_all((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); + usb_init_all(usb21_landing); +#ifdef USE_BLE + start_advertising(); +#endif +} + +void stop_comm(void) { + hal_delay(100); + usb_stop(); + usb_deinit(); +#ifdef USE_BLE + stop_advertising(); +#endif +} + +static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, + const image_header *const hdr) { + start_comm((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); uint8_t buf_usb[USB_PACKET_SIZE]; #ifdef USE_BLE @@ -164,6 +181,8 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, buf = ble_buf; break; } + + ble_event_poll(); #endif } @@ -197,9 +216,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, case MessageType_MessageType_PairingRequest: // pairing request response = process_msg_Pairing(active_iface, msg_size, ble_buf); if (response != INPUT_CONFIRM) { - hal_delay(100); - usb_stop(); - usb_deinit(); + stop_comm(); return RETURN; } screen_connect(); @@ -209,9 +226,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, case MessageType_MessageType_RepairRequest: // repairing request response = process_msg_Repair(active_iface, msg_size, ble_buf); if (response != INPUT_CONFIRM) { - hal_delay(100); - usb_stop(); - usb_deinit(); + stop_comm(); return RETURN; } // screen_connect(); @@ -277,9 +292,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, response = ui_screen_wipe_confirm(); if (INPUT_CANCEL == response) { send_user_abort(active_iface, "Wipe cancelled"); - hal_delay(100); - usb_stop(); - usb_deinit(); + stop_comm(); return RETURN; } ui_screen_wipe(); @@ -287,13 +300,11 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, process_msg_WipeDevice(active_iface, msg_size, buf); if (upload_response < 0) { // error screen_wipe_fail(); - usb_stop(); - usb_deinit(); + stop_comm(); return SHUTDOWN; } else { // success screen_wipe_success(); - usb_stop(); - usb_deinit(); + stop_comm(); return SHUTDOWN; } break; @@ -307,13 +318,10 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, upload_response != UPLOAD_ERR_USER_ABORT) { // error, but not user abort ui_screen_fail(); - usb_stop(); - usb_deinit(); + stop_comm(); return SHUTDOWN; } else if (upload_response == UPLOAD_ERR_USER_ABORT) { - hal_delay(100); - usb_stop(); - usb_deinit(); + stop_comm(); return RETURN; } else if (upload_response == 0) { // last chunk received ui_screen_install_progress_upload(1000); @@ -324,8 +332,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, hal_delay(1000); ui_screen_done(1, secfalse); hal_delay(1000); - usb_stop(); - usb_deinit(); + stop_comm(); ui_screen_boot_empty(true); return CONTINUE; } diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 6fc96fd26..f128cab85 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -65,6 +65,7 @@ #endif #ifdef USE_BLE #include "ble/comm.h" +#include "ble/state.h" #endif #ifdef SYSTEM_VIEW @@ -149,6 +150,7 @@ int main(void) { #ifdef USE_BLE ble_comm_init(); + start_advertising(); #endif #if !defined TREZOR_MODEL_1 @@ -250,6 +252,10 @@ void SVC_C_Handler(uint32_t *stack) { ; break; case SVC_REBOOT_TO_BOOTLOADER: +#ifdef USE_BLE + stop_advertising(); + // TODO: make sure that no answer is pending from NRF +#endif ensure_compatible_settings(); mpu_config_bootloader(); __asm__ volatile("msr control, %0" ::"r"(0x0)); diff --git a/core/embed/trezorhal/ble/comm.c b/core/embed/trezorhal/ble/comm.c index f8621fcaf..56c8fd536 100644 --- a/core/embed/trezorhal/ble/comm.c +++ b/core/embed/trezorhal/ble/comm.c @@ -25,6 +25,7 @@ #include "buffers.h" #include "dma.h" #include "int_comm_defs.h" +#include "messages.h" #include "state.h" #define SPI_QUEUE_SIZE 10 @@ -152,18 +153,14 @@ 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); + // case INTERNAL_EVENT_INITIALIZED: { + // set_connected(false); + // set_initialized(true); + // break; + // } + case INTERNAL_EVENT_STATUS: { + set_connected(data[1]); + set_advertising(data[2]); set_initialized(true); break; } @@ -249,8 +246,7 @@ void ble_event_poll() { } if (!ble_initialized()) { - uint8_t cmd = INTERNAL_CMD_SEND_STATE; - ble_int_comm_send(&cmd, sizeof(cmd), INTERNAL_EVENT); + send_state_request(); } } diff --git a/core/embed/trezorhal/ble/int_comm_defs.h b/core/embed/trezorhal/ble/int_comm_defs.h index ea3ac3294..18e9f09f1 100644 --- a/core/embed/trezorhal/ble/int_comm_defs.h +++ b/core/embed/trezorhal/ble/int_comm_defs.h @@ -15,10 +15,13 @@ #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) +typedef enum { + INTERNAL_EVENT_STATUS = 0x01, +} InternalEvent_t; +typedef enum { + INTERNAL_CMD_SEND_STATE = 0x00, + INTERNAL_CMD_ADVERTISING_ON = 0x01, + INTERNAL_CMD_ADVERTISING_OFF = 0x02, +} InternalCmd_t; #endif diff --git a/core/embed/trezorhal/ble/messages.c b/core/embed/trezorhal/ble/messages.c new file mode 100644 index 000000000..90cf0f1e0 --- /dev/null +++ b/core/embed/trezorhal/ble/messages.c @@ -0,0 +1,20 @@ + +#include + +#include "comm.h" +#include "messages.h" + +void send_state_request(void) { + uint8_t cmd = INTERNAL_CMD_SEND_STATE; + ble_int_comm_send(&cmd, sizeof(cmd), INTERNAL_EVENT); +} + +void send_advertising_on(void) { + uint8_t cmd = INTERNAL_CMD_ADVERTISING_ON; + ble_int_comm_send(&cmd, sizeof(cmd), INTERNAL_EVENT); +} + +void send_advertising_off(void) { + uint8_t cmd = INTERNAL_CMD_ADVERTISING_OFF; + ble_int_comm_send(&cmd, sizeof(cmd), INTERNAL_EVENT); +} diff --git a/core/embed/trezorhal/ble/messages.h b/core/embed/trezorhal/ble/messages.h new file mode 100644 index 000000000..d5f65c496 --- /dev/null +++ b/core/embed/trezorhal/ble/messages.h @@ -0,0 +1,10 @@ +#ifndef __BLE_MESSAGES__ +#define __BLE_MESSAGES__ + +void send_state_request(void); + +void send_advertising_on(void); + +void send_advertising_off(void); + +#endif diff --git a/core/embed/trezorhal/ble/state.c b/core/embed/trezorhal/ble/state.c index 33965a48d..13850f588 100644 --- a/core/embed/trezorhal/ble/state.c +++ b/core/embed/trezorhal/ble/state.c @@ -1,14 +1,42 @@ #include "ble/state.h" +#include "messages.h" static bool ble_state_connected = false; static bool ble_state_initialized = false; +static bool ble_advertising_wanted = false; +static bool ble_advertising = false; bool ble_connected(void) { return ble_state_connected; } void set_connected(bool connected) { ble_state_connected = connected; } +void set_advertising(bool advertising) { + if (ble_advertising_wanted != advertising) { + if (ble_advertising_wanted) { + send_advertising_on(); + } else { + send_advertising_off(); + } + } + ble_advertising = advertising; +} + void set_initialized(bool initialized) { ble_state_initialized = initialized; } bool ble_initialized(void) { return ble_state_initialized; } + +void start_advertising(void) { + ble_advertising_wanted = true; + if (!ble_advertising) { + send_advertising_on(); + } +} + +void stop_advertising(void) { + ble_advertising_wanted = false; + if (ble_advertising) { + send_advertising_off(); + } +} diff --git a/core/embed/trezorhal/ble/state.h b/core/embed/trezorhal/ble/state.h index 98f38d30a..e30d69d0d 100644 --- a/core/embed/trezorhal/ble/state.h +++ b/core/embed/trezorhal/ble/state.h @@ -11,6 +11,12 @@ void set_initialized(bool initialized); bool ble_connected(void); +void set_advertising(bool advertising); + void set_connected(bool connected); +void start_advertising(void); + +void stop_advertising(void); + #endif diff --git a/core/site_scons/boards/discovery.py b/core/site_scons/boards/discovery.py index 7c30b2209..1aad85c58 100644 --- a/core/site_scons/boards/discovery.py +++ b/core/site_scons/boards/discovery.py @@ -26,6 +26,7 @@ def configure(env, features_wanted, defines, sources): sources += ['embed/trezorhal/ble/dfu.c', ] sources += ['embed/trezorhal/ble/fwu.c', ] sources += ['embed/trezorhal/ble/state.c', ] + sources += ['embed/trezorhal/ble/messages.c', ] features_available.append("ble") if "dma2d" in features_wanted: