mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-04 22:02:34 +00:00
feat(core): ble pairing
This commit is contained in:
parent
945958096e
commit
cfd5cdadb8
@ -39,3 +39,21 @@ message UploadBLEFirmwareNextChunk {
|
||||
message UploadBLEFirmwareChunk {
|
||||
required bytes data = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request: initiates new pairing request
|
||||
* @start
|
||||
* @next AuthKey
|
||||
* @next Failure
|
||||
*/
|
||||
message PairingRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: confirms pairing request with auth key entered on the device
|
||||
* @end
|
||||
*/
|
||||
message AuthKey {
|
||||
required bytes key = 1;
|
||||
}
|
||||
|
@ -140,6 +140,8 @@ enum MessageType {
|
||||
MessageType_UploadBLEFirmwareInit = 8000 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_UploadBLEFirmwareNextChunk = 8001 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_UploadBLEFirmwareChunk = 8002 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_PairingRequest = 8003 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_AuthKey = 8004 [(bitcoin_only) = true, (wire_out) = true];
|
||||
|
||||
// Bitcoin
|
||||
MessageType_GetPublicKey = 11 [(bitcoin_only) = true, (wire_in) = true];
|
||||
|
@ -251,14 +251,29 @@ SOURCE_NRFHAL = [
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_gatt/nrf_ble_gatt.c',
|
||||
'embed/sdk/nrf52/components/ble/nrf_ble_qwr/nrf_ble_qwr.c',
|
||||
'embed/sdk/nrf52/external/utf_converter/utf.c',
|
||||
'embed/sdk/nrf52/components/ble/ble_services/ble_nus/ble_nus.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_ble.c',
|
||||
'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_soc.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/gatt_cache_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/gatts_cache_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/id_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_data_storage.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_database.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_id.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/peer_manager_handler.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/pm_buffer.c',
|
||||
'embed/sdk/nrf52/components/libraries/fds/fds.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/security_manager.c',
|
||||
'embed/sdk/nrf52/components/ble/peer_manager/security_dispatcher.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c',
|
||||
'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_sd.c',
|
||||
|
||||
]
|
||||
|
||||
SOURCE_BLE_FIRMWARE = [
|
||||
'embed/ble_firmware/main.c',
|
||||
'embed/ble_firmware/ble_nus.c',
|
||||
]
|
||||
|
||||
if MMD:
|
||||
|
356
core/embed/ble_firmware/ble_nus.c
Normal file
356
core/embed/ble_firmware/ble_nus.c
Normal file
@ -0,0 +1,356 @@
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
* Copyright (c) 2012 - 2021, Nordic Semiconductor ASA
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic
|
||||
* Semiconductor ASA integrated circuit in a product or a software update for
|
||||
* such product, must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_NUS)
|
||||
#include "ble.h"
|
||||
#include "ble_nus.h"
|
||||
#include "ble_srv_common.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME ble_nus
|
||||
#if BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL
|
||||
#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR
|
||||
#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR
|
||||
#else // BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#define NRF_LOG_LEVEL 0
|
||||
#endif // BLE_NUS_CONFIG_LOG_ENABLED
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */
|
||||
#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */
|
||||
|
||||
#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */
|
||||
#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */
|
||||
|
||||
#define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_gatts_value_t gatts_val;
|
||||
uint8_t cccd_value[2];
|
||||
ble_nus_client_context_t * p_client = NULL;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gap_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gap_evt.conn_handle);
|
||||
}
|
||||
|
||||
/* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */
|
||||
memset(&gatts_val, 0, sizeof(ble_gatts_value_t));
|
||||
gatts_val.p_value = cccd_value;
|
||||
gatts_val.len = sizeof(cccd_value);
|
||||
gatts_val.offset = 0;
|
||||
|
||||
err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle,
|
||||
p_nus->tx_handles.cccd_handle,
|
||||
&gatts_val);
|
||||
|
||||
if ((err_code == NRF_SUCCESS) &&
|
||||
(p_nus->data_handler != NULL) &&
|
||||
ble_srv_is_notification_enabled(gatts_val.p_value))
|
||||
{
|
||||
if (p_client != NULL)
|
||||
{
|
||||
p_client->is_notification_enabled = true;
|
||||
}
|
||||
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.type = BLE_NUS_EVT_COMM_STARTED;
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_nus_client_context_t * p_client;
|
||||
ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gatts_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gatts_evt.conn_handle);
|
||||
}
|
||||
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) &&
|
||||
(p_evt_write->len == 2))
|
||||
{
|
||||
if (p_client != NULL)
|
||||
{
|
||||
if (ble_srv_is_notification_enabled(p_evt_write->data))
|
||||
{
|
||||
p_client->is_notification_enabled = true;
|
||||
evt.type = BLE_NUS_EVT_COMM_STARTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_client->is_notification_enabled = false;
|
||||
evt.type = BLE_NUS_EVT_COMM_STOPPED;
|
||||
}
|
||||
|
||||
if (p_nus->data_handler != NULL)
|
||||
{
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) &&
|
||||
(p_nus->data_handler != NULL))
|
||||
{
|
||||
evt.type = BLE_NUS_EVT_RX_DATA;
|
||||
evt.params.rx_data.p_data = p_evt_write->data;
|
||||
evt.params.rx_data.length = p_evt_write->len;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do Nothing. This event is not relevant for this service.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice.
|
||||
*
|
||||
* @param[in] p_nus Nordic UART Service structure.
|
||||
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
|
||||
*/
|
||||
static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_nus_evt_t evt;
|
||||
ble_nus_client_context_t * p_client;
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage,
|
||||
p_ble_evt->evt.gatts_evt.conn_handle,
|
||||
(void *) &p_client);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.",
|
||||
p_ble_evt->evt.gatts_evt.conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL))
|
||||
{
|
||||
memset(&evt, 0, sizeof(ble_nus_evt_t));
|
||||
evt.type = BLE_NUS_EVT_TX_RDY;
|
||||
evt.p_nus = p_nus;
|
||||
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
|
||||
evt.p_link_ctx = p_client;
|
||||
|
||||
p_nus->data_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
|
||||
{
|
||||
if ((p_context == NULL) || (p_ble_evt == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ble_nus_t * p_nus = (ble_nus_t *)p_context;
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connect(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_WRITE:
|
||||
on_write(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
|
||||
on_hvx_tx_complete(p_nus, p_ble_evt);
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_uuid_t ble_uuid;
|
||||
ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
|
||||
ble_add_char_params_t add_char_params;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_nus);
|
||||
VERIFY_PARAM_NOT_NULL(p_nus_init);
|
||||
|
||||
// Initialize the service structure.
|
||||
p_nus->data_handler = p_nus_init->data_handler;
|
||||
|
||||
/**@snippet [Adding proprietary Service to the SoftDevice] */
|
||||
// Add a custom base UUID.
|
||||
err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
ble_uuid.type = p_nus->uuid_type;
|
||||
ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
|
||||
|
||||
// Add the service.
|
||||
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
|
||||
&ble_uuid,
|
||||
&p_nus->service_handle);
|
||||
/**@snippet [Adding proprietary Service to the SoftDevice] */
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
// Add the RX Characteristic.
|
||||
memset(&add_char_params, 0, sizeof(add_char_params));
|
||||
add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;
|
||||
add_char_params.uuid_type = p_nus->uuid_type;
|
||||
add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN;
|
||||
add_char_params.init_len = sizeof(uint8_t);
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.char_props.write = 1;
|
||||
add_char_params.char_props.write_wo_resp = 1;
|
||||
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
|
||||
err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Add the TX Characteristic.
|
||||
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
|
||||
memset(&add_char_params, 0, sizeof(add_char_params));
|
||||
add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC;
|
||||
add_char_params.uuid_type = p_nus->uuid_type;
|
||||
add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN;
|
||||
add_char_params.init_len = sizeof(uint8_t);
|
||||
add_char_params.is_var_len = true;
|
||||
add_char_params.char_props.notify = 1;
|
||||
|
||||
add_char_params.read_access = SEC_MITM;
|
||||
add_char_params.write_access = SEC_MITM;
|
||||
add_char_params.cccd_write_access = SEC_MITM;
|
||||
|
||||
return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
|
||||
/**@snippet [Adding proprietary characteristic to the SoftDevice] */
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_nus_data_send(ble_nus_t * p_nus,
|
||||
uint8_t * p_data,
|
||||
uint16_t * p_length,
|
||||
uint16_t conn_handle)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_gatts_hvx_params_t hvx_params;
|
||||
ble_nus_client_context_t * p_client;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_nus);
|
||||
|
||||
err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client);
|
||||
VERIFY_SUCCESS(err_code);
|
||||
|
||||
if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
|
||||
{
|
||||
return NRF_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!p_client->is_notification_enabled)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (*p_length > BLE_NUS_MAX_DATA_LEN)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(&hvx_params, 0, sizeof(hvx_params));
|
||||
|
||||
hvx_params.handle = p_nus->tx_handles.value_handle;
|
||||
hvx_params.p_data = p_data;
|
||||
hvx_params.p_len = p_length;
|
||||
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
|
||||
|
||||
return sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
||||
}
|
||||
|
||||
|
||||
#endif // NRF_MODULE_ENABLED(BLE_NUS)
|
@ -52,6 +52,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "app_scheduler.h"
|
||||
#include "app_timer.h"
|
||||
#include "app_uart.h"
|
||||
#include "app_util_platform.h"
|
||||
@ -69,6 +70,8 @@
|
||||
#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"
|
||||
@ -142,6 +145,8 @@ 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. */
|
||||
|
||||
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 =
|
||||
@ -151,6 +156,9 @@ 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.
|
||||
@ -190,6 +198,9 @@ static void gap_params_init(void) {
|
||||
strlen(DEVICE_NAME));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
|
||||
|
||||
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
|
||||
@ -229,6 +240,14 @@ static void nus_data_handler(ble_nus_evt_t *p_evt) {
|
||||
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]);
|
||||
@ -238,11 +257,8 @@ static void nus_data_handler(ble_nus_evt_t *p_evt) {
|
||||
}
|
||||
} while (err_code == NRF_ERROR_BUSY);
|
||||
}
|
||||
// if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] ==
|
||||
// '\r') {
|
||||
// while (app_uart_put('\n') == NRF_ERROR_BUSY)
|
||||
// ;
|
||||
// }
|
||||
|
||||
app_uart_put(0x55); // EOM
|
||||
}
|
||||
}
|
||||
/**@snippet [Handling the data received over BLE] */
|
||||
@ -270,27 +286,6 @@ static void services_init(void) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for handling an event from the Connection Parameters Module.
|
||||
*
|
||||
* @details This function will be called for all events in the Connection
|
||||
* Parameters Module which are passed to the application.
|
||||
*
|
||||
* @note All this function does is to disconnect. This could have been done by
|
||||
* simply setting the disconnect_on_fail config parameter, but instead we use
|
||||
* the event handler mechanism to demonstrate its use.
|
||||
*
|
||||
* @param[in] p_evt Event received from the Connection Parameters Module.
|
||||
*/
|
||||
static void on_conn_params_evt(ble_conn_params_evt_t *p_evt) {
|
||||
uint32_t err_code;
|
||||
|
||||
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
|
||||
err_code = sd_ble_gap_disconnect(m_conn_handle,
|
||||
BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for handling errors from the Connection Parameters module.
|
||||
*
|
||||
* @param[in] nrf_error Error code containing information about what went
|
||||
@ -314,7 +309,7 @@ static void conn_params_init(void) {
|
||||
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
|
||||
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
|
||||
cp_init.disconnect_on_fail = false;
|
||||
cp_init.evt_handler = on_conn_params_evt;
|
||||
cp_init.evt_handler = NULL;
|
||||
cp_init.error_handler = conn_params_error_handler;
|
||||
|
||||
err_code = ble_conn_params_init(&cp_init);
|
||||
@ -339,6 +334,22 @@ static void sleep_mode_enter(void) {
|
||||
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
|
||||
@ -350,13 +361,91 @@ 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;
|
||||
}
|
||||
@ -397,19 +486,45 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) {
|
||||
APP_ERROR_CHECK(err_code);
|
||||
} break;
|
||||
|
||||
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
|
||||
// Pairing not supported
|
||||
err_code = sd_ble_gap_sec_params_reply(
|
||||
m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
case BLE_GAP_EVT_AUTH_KEY_REQUEST: {
|
||||
NRF_LOG_INFO("Key requested.");
|
||||
|
||||
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
// No system attributes have been stored.
|
||||
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
break;
|
||||
uint8_t tx_data[] = {
|
||||
0xA0, // internal message
|
||||
0x00, // length - HI
|
||||
0x0D, // length - LO
|
||||
0x3F, 0x23, 0x23, 0x1F, 0x43, 0x00, 0x00, 0x00, 0x00,
|
||||
0x55, // EOM
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(tx_data); i++) {
|
||||
do {
|
||||
err_code = app_uart_put(tx_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);
|
||||
}
|
||||
|
||||
uint8_t p_key[6] = {0};
|
||||
|
||||
while (!m_uart_rx_data_ready_internal)
|
||||
;
|
||||
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;
|
||||
}
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
// Disconnect on GATT Client timeout event.
|
||||
err_code =
|
||||
@ -526,43 +641,89 @@ void bsp_event_handler(bsp_event_t event) {
|
||||
*/
|
||||
/**@snippet [Handling the data received over UART] */
|
||||
void uart_event_handle(app_uart_evt_t *p_event) {
|
||||
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
|
||||
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:
|
||||
UNUSED_VARIABLE(app_uart_get(&data_array[index]));
|
||||
index++;
|
||||
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;
|
||||
|
||||
if ((index >= 64)) {
|
||||
if (index > 1) {
|
||||
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
|
||||
NRF_LOG_HEXDUMP_DEBUG(data_array, index);
|
||||
|
||||
do {
|
||||
uint16_t length = (uint16_t)index;
|
||||
err_code =
|
||||
ble_nus_data_send(&m_nus, data_array, &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 {
|
||||
// unknown message
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
index = 0;
|
||||
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;
|
||||
// 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;
|
||||
@ -597,23 +758,55 @@ static void uart_init(void) {
|
||||
|
||||
/**@brief Function for initializing the Advertising functionality.
|
||||
*/
|
||||
// static void advertising_init(void) {
|
||||
// uint32_t err_code;
|
||||
// ble_advertising_init_t init;
|
||||
//
|
||||
// memset(&init, 0, sizeof(init));
|
||||
//
|
||||
// init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
|
||||
// init.advdata.include_appearance = false;
|
||||
// init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
|
||||
//
|
||||
// init.srdata.uuids_complete.uuid_cnt =
|
||||
// sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
|
||||
// init.srdata.uuids_complete.p_uuids = m_adv_uuids;
|
||||
//
|
||||
// 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);
|
||||
//}
|
||||
|
||||
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 = false;
|
||||
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
|
||||
|
||||
init.srdata.uuids_complete.uuid_cnt =
|
||||
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.srdata.uuids_complete.p_uuids = m_adv_uuids;
|
||||
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);
|
||||
@ -663,16 +856,145 @@ static void power_management_init(void) {
|
||||
* event occurs.
|
||||
*/
|
||||
static void idle_state_handle(void) {
|
||||
app_sched_execute();
|
||||
if (NRF_LOG_PROCESS() == false) {
|
||||
nrf_pwr_mgmt_run();
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for starting advertising.
|
||||
/**@brief Function for setting filtered whitelist.
|
||||
*
|
||||
* @param[in] skip Filter passed to @ref pm_peer_id_list.
|
||||
*/
|
||||
static void advertising_start(void) {
|
||||
uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#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.
|
||||
*/
|
||||
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;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**@brief Function for the Peer Manager initialization.
|
||||
*/
|
||||
static void peer_manager_init(void) {
|
||||
ble_gap_sec_params_t sec_param;
|
||||
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);
|
||||
|
||||
err_code = pm_register(pm_evt_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
/**@brief Function for the Event Scheduler initialization.
|
||||
*/
|
||||
static void scheduler_init(void) {
|
||||
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
/**@brief Application main function.
|
||||
@ -687,16 +1009,16 @@ int main(void) {
|
||||
buttons_leds_init(&erase_bonds);
|
||||
power_management_init();
|
||||
ble_stack_init();
|
||||
scheduler_init();
|
||||
gap_params_init();
|
||||
gatt_init();
|
||||
services_init();
|
||||
advertising_init();
|
||||
conn_params_init();
|
||||
peer_manager_init();
|
||||
|
||||
// Start execution.
|
||||
printf("\r\nUART started.\r\n");
|
||||
NRF_LOG_INFO("Debug logging for UART over RTT started.");
|
||||
advertising_start();
|
||||
advertising_start(true);
|
||||
|
||||
// Enter main loop.
|
||||
for (;;) {
|
||||
|
@ -206,7 +206,7 @@
|
||||
// <e> PEER_MANAGER_ENABLED - peer_manager - Peer Manager
|
||||
//==========================================================
|
||||
#ifndef PEER_MANAGER_ENABLED
|
||||
#define PEER_MANAGER_ENABLED 0
|
||||
#define PEER_MANAGER_ENABLED 1
|
||||
#endif
|
||||
// <o> PM_MAX_REGISTRANTS - Number of event handlers that can be registered.
|
||||
#ifndef PM_MAX_REGISTRANTS
|
||||
@ -226,7 +226,7 @@
|
||||
// <i> Enable/disable central-specific Peer Manager functionality.
|
||||
|
||||
#ifndef PM_CENTRAL_ENABLED
|
||||
#define PM_CENTRAL_ENABLED 1
|
||||
#define PM_CENTRAL_ENABLED 0
|
||||
#endif
|
||||
|
||||
// <q> PM_SERVICE_CHANGED_ENABLED - Enable/disable the service changed management for GATT server in Peer Manager.
|
||||
@ -6728,7 +6728,7 @@
|
||||
// <e> FDS_ENABLED - fds - Flash data storage module
|
||||
//==========================================================
|
||||
#ifndef FDS_ENABLED
|
||||
#define FDS_ENABLED 0
|
||||
#define FDS_ENABLED 1
|
||||
#endif
|
||||
// <h> Pages - Virtual page settings
|
||||
|
||||
@ -7252,7 +7252,7 @@
|
||||
// <e> NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library
|
||||
//==========================================================
|
||||
#ifndef NRF_FSTORAGE_ENABLED
|
||||
#define NRF_FSTORAGE_ENABLED 0
|
||||
#define NRF_FSTORAGE_ENABLED 1
|
||||
#endif
|
||||
// <h> nrf_fstorage - Common settings
|
||||
|
||||
@ -7496,7 +7496,7 @@
|
||||
|
||||
|
||||
#ifndef RETARGET_ENABLED
|
||||
#define RETARGET_ENABLED 1
|
||||
#define RETARGET_ENABLED 0
|
||||
#endif
|
||||
|
||||
// <q> SLIP_ENABLED - slip - SLIP encoding and decoding
|
||||
@ -11914,7 +11914,7 @@
|
||||
// <2=> NRF_SDH_DISPATCH_MODEL_POLLING
|
||||
|
||||
#ifndef NRF_SDH_DISPATCH_MODEL
|
||||
#define NRF_SDH_DISPATCH_MODEL 0
|
||||
#define NRF_SDH_DISPATCH_MODEL 1
|
||||
#endif
|
||||
|
||||
// </h>
|
||||
|
@ -72,7 +72,7 @@ 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_comm_send(buf.buf, buf.len);
|
||||
ble_int_comm_send(buf.buf, buf.len, ble_last_internal);
|
||||
return MP_OBJ_NEW_SMALL_INT(buf.len);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_BLE_write_obj,
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
// Whether USB data pins were connected on last check (USB configured)
|
||||
bool usb_connected_previously = true;
|
||||
bool ble_last_internal = false;
|
||||
|
||||
#define CHECK_PARAM_RANGE(value, minimum, maximum) \
|
||||
if (value < minimum || value > maximum) { \
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include STM32_HAL_H
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
static UART_HandleTypeDef urt;
|
||||
|
||||
void ble_comm_init(void) {
|
||||
@ -47,7 +49,7 @@ void ble_comm_init(void) {
|
||||
}
|
||||
|
||||
void ble_comm_send(uint8_t *data, uint32_t len) {
|
||||
HAL_UART_Transmit(&urt, data, len, 10);
|
||||
HAL_UART_Transmit(&urt, data, len, 30);
|
||||
}
|
||||
|
||||
uint32_t ble_comm_receive(uint8_t *data, uint32_t len) {
|
||||
@ -65,3 +67,67 @@ 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;
|
||||
uint8_t len_hi = msg_len >> 8;
|
||||
uint8_t len_lo = msg_len & 0xFF;
|
||||
uint8_t eom = 0x55;
|
||||
|
||||
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, &len_hi, 1, 1);
|
||||
HAL_UART_Transmit(&urt, &len_lo, 1, 1);
|
||||
|
||||
HAL_UART_Transmit(&urt, data, len, 10);
|
||||
HAL_UART_Transmit(&urt, &eom, 1, 1);
|
||||
}
|
||||
|
||||
uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal) {
|
||||
data[0] = 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) {
|
||||
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;
|
||||
|
||||
HAL_StatusTypeDef result = HAL_UART_Receive(&urt, data, act_len - 4, 5);
|
||||
|
||||
if (result != HAL_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t eom = 0;
|
||||
HAL_UART_Receive(&urt, &eom, 1, 1);
|
||||
|
||||
if (eom == 0x55) {
|
||||
if (init_byte == 0xA0) {
|
||||
*internal = true;
|
||||
} else {
|
||||
*internal = false;
|
||||
}
|
||||
return act_len - 4;
|
||||
}
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
// disregard byte.
|
||||
// todo: flush everything on the line, also for other errors
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
|
||||
#include <stdbool.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);
|
||||
uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal);
|
||||
|
@ -121,7 +121,6 @@ dfu_result_t dfu_update_do(uint8_t *datfile, uint32_t datfile_len,
|
||||
|
||||
void txFunction(struct SFwu *fwu, uint8_t *buf, uint8_t len) {
|
||||
ble_comm_send(buf, len);
|
||||
;
|
||||
}
|
||||
|
||||
static uint8_t readData(uint8_t *data, int maxLen) {
|
||||
|
@ -303,6 +303,8 @@ apps.management.backup_device
|
||||
import apps.management.backup_device
|
||||
apps.management.backup_types
|
||||
import apps.management.backup_types
|
||||
apps.management.ble.pairing_request
|
||||
import apps.management.ble.pairing_request
|
||||
apps.management.ble.upload_ble_firmware_init
|
||||
import apps.management.ble.upload_ble_firmware_init
|
||||
apps.management.change_pin
|
||||
|
19
core/src/apps/management/ble/pairing_request.py
Normal file
19
core/src/apps/management/ble/pairing_request.py
Normal file
@ -0,0 +1,19 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from trezor.wire import GenericContext
|
||||
from trezor.messages import (
|
||||
AuthKey,
|
||||
PairingRequest,
|
||||
)
|
||||
|
||||
|
||||
async def pairing_request(ctx: GenericContext, _msg: PairingRequest) -> AuthKey:
|
||||
from trezor.messages import (
|
||||
AuthKey,
|
||||
)
|
||||
from trezor.ui.layouts import request_pin_on_device
|
||||
|
||||
pin = await request_pin_on_device(ctx, "PAIRING", None, True, False, True)
|
||||
|
||||
return AuthKey(key=pin.encode())
|
@ -58,6 +58,8 @@ def _find_message_handler_module(msg_type: int) -> str:
|
||||
# BLE
|
||||
if msg_type == MessageType.UploadBLEFirmwareInit:
|
||||
return "apps.management.ble.upload_ble_firmware_init"
|
||||
if msg_type == MessageType.PairingRequest:
|
||||
return "apps.management.ble.pairing_request"
|
||||
|
||||
# bitcoin
|
||||
if msg_type == MessageType.AuthorizeCoinJoin:
|
||||
|
@ -53,6 +53,8 @@ SelfTest = 32
|
||||
UploadBLEFirmwareInit = 8000
|
||||
UploadBLEFirmwareNextChunk = 8001
|
||||
UploadBLEFirmwareChunk = 8002
|
||||
PairingRequest = 8003
|
||||
AuthKey = 8004
|
||||
GetPublicKey = 11
|
||||
PublicKey = 12
|
||||
SignTx = 15
|
||||
|
@ -75,6 +75,8 @@ if TYPE_CHECKING:
|
||||
UploadBLEFirmwareInit = 8000
|
||||
UploadBLEFirmwareNextChunk = 8001
|
||||
UploadBLEFirmwareChunk = 8002
|
||||
PairingRequest = 8003
|
||||
AuthKey = 8004
|
||||
GetPublicKey = 11
|
||||
PublicKey = 12
|
||||
SignTx = 15
|
||||
|
@ -1221,6 +1221,26 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["UploadBLEFirmwareChunk"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class PairingRequest(protobuf.MessageType):
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["PairingRequest"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class AuthKey(protobuf.MessageType):
|
||||
key: "bytes"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
key: "bytes",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: Any) -> TypeGuard["AuthKey"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class CardanoBlockchainPointerType(protobuf.MessageType):
|
||||
block_index: "int"
|
||||
tx_index: "int"
|
||||
|
@ -1101,10 +1101,12 @@ async def request_pin_on_device(
|
||||
attempts_remaining: int | None,
|
||||
allow_cancel: bool,
|
||||
wrong_pin: bool = False,
|
||||
skip_button_request: bool = False,
|
||||
) -> str:
|
||||
from trezor.wire import PinCancelled
|
||||
|
||||
await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry)
|
||||
if not skip_button_request:
|
||||
await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry)
|
||||
|
||||
if attempts_remaining is None:
|
||||
subprompt = ""
|
||||
|
@ -83,6 +83,8 @@ class MessageType(IntEnum):
|
||||
UploadBLEFirmwareInit = 8000
|
||||
UploadBLEFirmwareNextChunk = 8001
|
||||
UploadBLEFirmwareChunk = 8002
|
||||
PairingRequest = 8003
|
||||
AuthKey = 8004
|
||||
GetPublicKey = 11
|
||||
PublicKey = 12
|
||||
SignTx = 15
|
||||
@ -2089,6 +2091,24 @@ class UploadBLEFirmwareChunk(protobuf.MessageType):
|
||||
self.data = data
|
||||
|
||||
|
||||
class PairingRequest(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 8003
|
||||
|
||||
|
||||
class AuthKey(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 8004
|
||||
FIELDS = {
|
||||
1: protobuf.Field("key", "bytes", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
key: "bytes",
|
||||
) -> None:
|
||||
self.key = key
|
||||
|
||||
|
||||
class FirmwareErase(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 6
|
||||
FIELDS = {
|
||||
|
Loading…
Reference in New Issue
Block a user