mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #14198 from ARMmbed/feature-bluetooth-traces
Feature bluetooth tracespull/14455/head
commit
1fdb1c18e8
|
@ -47,4 +47,8 @@
|
|||
|
||||
#### How is this defect reproduced ?
|
||||
|
||||
<!--
|
||||
For connectivity issues it is recommended to enable mbed trace and attach the traces
|
||||
generated by the logger to the issue.
|
||||
-->
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
#include "mbed_wsf_trace.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -289,6 +293,7 @@ bool_t WsfTokenService(void);
|
|||
/*! \brief 3 argument HCI error trace. */
|
||||
#define HCI_TRACE_ERR3(msg, var1, var2, var3) WSF_TRACE3("HCI", "ERR", msg, var1, var2, var3)
|
||||
|
||||
#if !MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
/*! \brief HCI PDUMP on command. */
|
||||
#define HCI_PDUMP_CMD(len, pBuf)
|
||||
/*! \brief HCI PDUMP on event. */
|
||||
|
@ -301,6 +306,7 @@ bool_t WsfTokenService(void);
|
|||
#define HCI_PDUMP_TX_ISO(len, pBuf)
|
||||
/*! \brief HCI PDUMP on Received ISO message. */
|
||||
#define HCI_PDUMP_RX_ISO(len, pBuf)
|
||||
#endif // !MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
|
||||
/*! \brief 0 argument DM info trace. */
|
||||
#define DM_TRACE_INFO0(msg) WSF_TRACE0("DM", "INFO", msg)
|
||||
|
|
|
@ -108,10 +108,15 @@
|
|||
"value": 16,
|
||||
"macro_name": "BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE"
|
||||
},
|
||||
|
||||
"ble-passkey-display-reversed-digits-deprecation": {
|
||||
"help": "This option is part of the deprecation process. Set this to false to remove the deprecation notice. When set to true, the digits in the SecurityManager passkeyDiplay event are reversed. When set to false the digits are in the correct order.",
|
||||
"value": true,
|
||||
"macro_name": "BLE_PASSKEY_DISPLAY_REVERSED_DIGITS_DEPRECATION"
|
||||
},
|
||||
"trace-human-readable-enums": {
|
||||
"help": "More hexadecimal values in traces will be printed as human readable strings.",
|
||||
"value": false
|
||||
}
|
||||
},
|
||||
"target_overrides": {
|
||||
|
|
|
@ -7,6 +7,11 @@ add_subdirectory(gatt)
|
|||
add_subdirectory(generic)
|
||||
add_subdirectory(pal)
|
||||
|
||||
target_include_directories(mbed-ble
|
||||
INTERFACE
|
||||
.
|
||||
)
|
||||
|
||||
target_sources(mbed-ble
|
||||
INTERFACE
|
||||
BLE.cpp
|
||||
|
@ -14,6 +19,7 @@ target_sources(mbed-ble
|
|||
GattClient.cpp
|
||||
GattServer.cpp
|
||||
SecurityManager.cpp
|
||||
common/ble_trace_helpers.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(mbed-ble
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,120 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BLE_CLIAPP_BLE_TRACE_HELPERS_H
|
||||
#define BLE_CLIAPP_BLE_TRACE_HELPERS_H
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "pal/GapTypes.h"
|
||||
#include "pal/GapEvents.h"
|
||||
#include "dm_api.h"
|
||||
#include "common/UUID.h"
|
||||
|
||||
namespace ble {
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
void trace_le_supported_features(uint64_t feat);
|
||||
|
||||
const char* dm_callback_event_to_string(uint8_t event);
|
||||
const char* hci_opcode_to_string(uint16_t opcode);
|
||||
const char* attribute_error_code_to_string(uint8_t error);
|
||||
const char* attribute_opcode_to_string(uint8_t error);
|
||||
const char* ble_error_to_string(ble_error_t error);
|
||||
const char* att_client_callback_event_to_string(uint8_t code);
|
||||
const char* att_error_code_to_string(uint8_t code);
|
||||
#endif //MBED_CONF_MBED_TRACE_ENABLE
|
||||
|
||||
template<size_t size>
|
||||
const char* to_string(const ble::byte_array_t<size> &array)
|
||||
{
|
||||
return (mbed_trace_array)(array.data(), array.size());
|
||||
}
|
||||
|
||||
const char* to_string(const UUID& uuid);
|
||||
|
||||
const char *to_string(bool v);
|
||||
|
||||
const char *to_string(ble::SecurityManager::SecurityIOCapabilities_t capabilities);
|
||||
|
||||
const char *to_string(ble::io_capability_t capabilities);
|
||||
|
||||
const char *to_string(ble::SecurityManager::SecurityMode_t security_mode);
|
||||
|
||||
const char *passkey_str(const uint8_t* passkey);
|
||||
|
||||
const char *to_string(const ble::address_t& address);
|
||||
|
||||
const char *to_string(const ble::link_encryption_t encryption);
|
||||
|
||||
const char *to_string(Keypress_t keypress);
|
||||
|
||||
const char *to_string(ble::pairing_failure_t reason);
|
||||
|
||||
const char *to_string(target_peer_address_type_t type);
|
||||
|
||||
const char *to_string(privacy_mode_t mode);
|
||||
|
||||
const char *to_string(ble::advertising_type_t advType);
|
||||
|
||||
const char *to_string(ble::own_address_type_t addressType);
|
||||
|
||||
const char *to_string(ble::advertising_filter_policy_t policy);
|
||||
|
||||
const char *to_string(ble::phy_t phy);
|
||||
|
||||
const char *to_string(ble::scanning_filter_policy_t policy);
|
||||
|
||||
const char *to_string(ble::duplicates_filter_t filtering);
|
||||
|
||||
const char *to_string(ble::peer_address_type_t addressType);
|
||||
|
||||
const char *to_string(ble::initiator_filter_policy_t policy);
|
||||
|
||||
const char *to_string(ble::coded_symbol_per_bit_t sym);
|
||||
|
||||
const char *to_string(ble::local_disconnection_reason_t reason);
|
||||
|
||||
const char *to_string(ble::advertising_channel_map_t map);
|
||||
|
||||
const char *to_string(ble::connection_peer_address_type_t connection_peer_address_type);
|
||||
|
||||
const char *to_string(ble::whitelist_address_type_t whitelist_address_type);
|
||||
|
||||
const char *to_string(ble::hci_error_code_t error);
|
||||
|
||||
const char *to_string(ble::advertising_fragment_description_t fragment_description);
|
||||
|
||||
const char *to_string(ble::peripheral_privacy_configuration_t::resolution_strategy_t resolution_strategy);
|
||||
|
||||
const char *to_string(ble::GapEventType event_type);
|
||||
|
||||
const char *to_string(ble::received_advertising_type_t type);
|
||||
|
||||
const char *to_string(ble::connection_role_t role);
|
||||
|
||||
const char *to_string(ble::direct_address_type_t direct_address_type);
|
||||
|
||||
const char *to_string(ble::advertising_data_status_t data_status);
|
||||
|
||||
const char *to_string(ble::att_security_requirement_t security_requirement);
|
||||
|
||||
const char *to_string(GattAuthCallbackReply_t authorization_reply);
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif //BLE_CLIAPP_BLE_TRACE_HELPERS_H
|
|
@ -29,4 +29,5 @@ target_sources(mbed-ble-cordio
|
|||
stack_adaptation/wsf_cs.c
|
||||
stack_adaptation/wsf_mbed_os_adaptation.c
|
||||
stack_adaptation/wsf_os.c
|
||||
stack_adaptation/mbed_wsf_trace.c
|
||||
)
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
#include "bstream.h"
|
||||
#include "hci_mbed_os_adaptation.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLHC"
|
||||
|
||||
#define HCI_RESET_RAND_CNT 4
|
||||
|
||||
namespace ble {
|
||||
|
@ -69,12 +74,14 @@ CordioHCIDriver::CordioHCIDriver(CordioHCITransportDriver& transport_driver) :
|
|||
|
||||
void CordioHCIDriver::initialize()
|
||||
{
|
||||
tr_info("CordioHCIDriver initializing");
|
||||
_transport_driver.initialize();
|
||||
do_initialize();
|
||||
}
|
||||
|
||||
void CordioHCIDriver::terminate()
|
||||
{
|
||||
tr_info("CordioHCIDriver terminating");
|
||||
do_terminate();
|
||||
_transport_driver.terminate();
|
||||
}
|
||||
|
@ -275,19 +282,34 @@ bool CordioHCIDriver::get_random_static_address(ble::address_t& address)
|
|||
|
||||
void CordioHCIDriver::signal_reset_sequence_done()
|
||||
{
|
||||
tr_debug("Signal cordio HCI reset sequence done");
|
||||
hci_mbed_os_signal_reset_sequence_done();
|
||||
}
|
||||
|
||||
uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
const char *type_prefix;
|
||||
switch(type) {
|
||||
case 0x01: type_prefix = "CMD"; break;
|
||||
case 0x02: type_prefix = "ACL"; break;
|
||||
/* illegal packet */
|
||||
default: type_prefix = "ERR"; break;
|
||||
}
|
||||
tr_debug("HOST->LL %s %s", type_prefix, trace_array(pData, len));
|
||||
#endif
|
||||
return _transport_driver.write(type, len, pData);
|
||||
}
|
||||
|
||||
void CordioHCIDriver::on_host_stack_inactivity()
|
||||
{
|
||||
}
|
||||
|
||||
void CordioHCIDriver::handle_test_end(bool success, uint16_t packets)
|
||||
{
|
||||
MBED_ASSERT(_test_end_handler);
|
||||
tr_info("LE receiver mode ended (success: %s)", to_string(success));
|
||||
|
||||
if (_test_end_handler) {
|
||||
_test_end_handler(success, packets);
|
||||
_test_end_handler = nullptr;
|
||||
|
@ -299,10 +321,12 @@ ble_error_t CordioHCIDriver::rf_test_start_le_receiver_test(
|
|||
)
|
||||
{
|
||||
if (_test_end_handler) {
|
||||
tr_warning("Cannot start LE %s test mode - already started", "receiver");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!test_end_handler) {
|
||||
tr_warning("Cannot start LE %s test mode - invalid handler", "receiver");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -310,6 +334,8 @@ ble_error_t CordioHCIDriver::rf_test_start_le_receiver_test(
|
|||
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_RECEIVER_TEST, HCI_LEN_LE_RECEIVER_TEST);
|
||||
|
||||
if (buf) {
|
||||
tr_info("LE %s mode starter on channel %hhd", "receiver", channel);
|
||||
|
||||
uint8_t* p = buf + HCI_CMD_HDR_LEN;
|
||||
UINT8_TO_BSTREAM(p, channel);
|
||||
hciCmdSend(buf);
|
||||
|
@ -325,10 +351,12 @@ ble_error_t CordioHCIDriver::rf_test_start_le_transmitter_test(
|
|||
)
|
||||
{
|
||||
if (_test_end_handler) {
|
||||
tr_warning("Cannot start LE %s test mode - already started", "transmitter");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!test_end_handler) {
|
||||
tr_warning("Cannot start LE %s test mode - invalid handler", "transmitter");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -336,6 +364,8 @@ ble_error_t CordioHCIDriver::rf_test_start_le_transmitter_test(
|
|||
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_TRANSMITTER_TEST, HCI_LEN_LE_TRANSMITTER_TEST);
|
||||
|
||||
if (buf) {
|
||||
tr_info("LE %s mode starter on channel %hhd", "transmitter", channel);
|
||||
|
||||
uint8_t* p = buf + HCI_CMD_HDR_LEN;
|
||||
UINT8_TO_BSTREAM(p, channel);
|
||||
UINT8_TO_BSTREAM(p, length);
|
||||
|
@ -350,7 +380,10 @@ ble_error_t CordioHCIDriver::rf_test_start_le_transmitter_test(
|
|||
|
||||
ble_error_t CordioHCIDriver::rf_test_end()
|
||||
{
|
||||
MBED_ASSERT(_test_end_handler);
|
||||
|
||||
if (!_test_end_handler) {
|
||||
tr_info("Cannot end LE transmitter mode test - missing handler (test never started?)");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -358,6 +391,7 @@ ble_error_t CordioHCIDriver::rf_test_end()
|
|||
|
||||
if (buf) {
|
||||
hciCmdSend(buf);
|
||||
tr_info("LE transmitter mode ended");
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
#include "ble/driver/CordioHCITransportDriver.h"
|
||||
#include "ble/driver/CordioHCIDriver.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLHC"
|
||||
|
||||
extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len);
|
||||
|
||||
namespace ble {
|
||||
|
@ -40,6 +45,7 @@ void CordioHCITransportDriver::on_data_received(uint8_t* data, uint16_t len)
|
|||
|
||||
void CordioHCITransportDriver::set_data_received_handler(data_received_handler_t handler)
|
||||
{
|
||||
MBED_ASSERT(handler);
|
||||
data_received_handler = handler;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,19 @@
|
|||
"help": "Check connection complete event if it needs the addresses swapped due to bug in controller",
|
||||
"value": null,
|
||||
"macro_name": "CORDIO_RPA_SWAP_WORKAROUND"
|
||||
},
|
||||
"trace-pal-echoes": {
|
||||
"help": "Include 'echo' traces in PAL, i.e. function signature and argument prints",
|
||||
"value": 0
|
||||
},
|
||||
"trace-hci-packets": {
|
||||
"help": "If tracing is enabled at level DEBUG traces will include HCI packet traces.",
|
||||
"value": false
|
||||
},
|
||||
"trace-cordio-wsf-traces": {
|
||||
"help": "If tracing is enabled at level DEBUG traces will include WSF traces from Cordio packet traces.",
|
||||
"value": false,
|
||||
"macro_name": "WSF_TRACE_ENABLED"
|
||||
}
|
||||
},
|
||||
"target_overrides": {
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
#include "hci_drv.h"
|
||||
#include "bstream.h"
|
||||
|
||||
#include "stack_adaptation/mbed_wsf_trace.c"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLE "
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
|
@ -85,11 +90,21 @@ extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *p
|
|||
|
||||
extern "C" void hci_mbed_os_start_reset_sequence(void)
|
||||
{
|
||||
tr_debug("Cordio HCI reset started");
|
||||
ble_cordio_get_hci_driver().start_reset_sequence();
|
||||
}
|
||||
|
||||
extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t *msg)
|
||||
{
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
if (*msg == HCI_CMD_CMPL_EVT) {
|
||||
uint16_t opcode;
|
||||
uint8_t *peek_msg = msg + (HCI_EVT_HDR_LEN + 1 /* skip num packets */);
|
||||
BSTREAM_TO_UINT16(opcode, peek_msg);
|
||||
tr_debug("Reset sequence command complete: %s", ble::hci_opcode_to_string(opcode));
|
||||
}
|
||||
#endif // MBED_CONF_MBED_TRACE_ENABLE
|
||||
|
||||
ble_cordio_get_hci_driver().handle_reset_sequence(msg);
|
||||
}
|
||||
|
||||
|
@ -142,6 +157,7 @@ ble_error_t BLEInstanceBase::init(
|
|||
{
|
||||
switch (initialization_status) {
|
||||
case NOT_INITIALIZED:
|
||||
tr_info("Initialising BLE instance");
|
||||
_timer.reset();
|
||||
_timer.start();
|
||||
_event_queue.initialize(this);
|
||||
|
@ -150,6 +166,7 @@ ble_error_t BLEInstanceBase::init(
|
|||
return BLE_ERROR_NONE;
|
||||
|
||||
case INITIALIZING:
|
||||
tr_warning("Already initialising BLE instance");
|
||||
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
|
||||
case INITIALIZED:
|
||||
|
@ -167,6 +184,7 @@ bool BLEInstanceBase::hasInitialized() const
|
|||
|
||||
ble_error_t BLEInstanceBase::shutdown()
|
||||
{
|
||||
tr_info("shutting down BLE");
|
||||
if (initialization_status != INITIALIZED) {
|
||||
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
}
|
||||
|
@ -343,6 +361,7 @@ void BLEInstanceBase::processEvents()
|
|||
void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
||||
{
|
||||
if (msg == nullptr) {
|
||||
tr_warning("stack_handler received NULL message");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -366,17 +385,26 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
|||
};
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
// initialize extended module if supported
|
||||
tr_info("Reset sequence complete. Controller supported features:");
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
trace_le_supported_features(HciGetLeSupFeat());
|
||||
#endif // MBED_CONF_MBED_TRACE_ENABLE
|
||||
tr_info("Initialising extended features");
|
||||
if (HciGetLeSupFeat() & HCI_LE_SUP_FEAT_LE_EXT_ADV) {
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
tr_info("DmExtAdvInit");
|
||||
DmExtAdvInit();
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
#if BLE_ROLE_OBSERVER
|
||||
tr_info("DmExtScanInit");
|
||||
DmExtScanInit();
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#if BLE_ROLE_CENTRAL
|
||||
tr_info("DmExtConnMasterInit");
|
||||
DmExtConnMasterInit();
|
||||
#endif // BLE_ROLE_CENTRAL
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
tr_info("DmExtConnSlaveInit");
|
||||
DmExtConnSlaveInit();
|
||||
#endif // BLE_ROLE_PERIPHERAL
|
||||
}
|
||||
|
@ -394,6 +422,7 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
|||
// upcast to unhandled command complete event to access the payload
|
||||
hciUnhandledCmdCmplEvt_t *unhandled = (hciUnhandledCmdCmplEvt_t *) msg;
|
||||
if (unhandled->hdr.status == HCI_SUCCESS && unhandled->hdr.param == HCI_OPCODE_LE_TEST_END) {
|
||||
tr_info("Host received HCI_OPCODE_LE_TEST_END from controller - end test mode");
|
||||
// unhandled events are not parsed so we need to parse the payload ourselves
|
||||
uint8_t status;
|
||||
uint16_t packet_number;
|
||||
|
@ -414,6 +443,8 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
|||
|
||||
void BLEInstanceBase::device_manager_cb(dmEvt_t *dm_event)
|
||||
{
|
||||
tr_debug("stack_handler received %s", dm_callback_event_to_string(dm_event->hdr.event));
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
if (dm_event->hdr.status == HCI_SUCCESS && dm_event->hdr.event == DM_CONN_DATA_LEN_CHANGE_IND) {
|
||||
// this event can only happen after a connection has been established therefore gap is present
|
||||
|
@ -444,11 +475,13 @@ void BLEInstanceBase::connection_handler(dmEvt_t *dm_event)
|
|||
|
||||
switch (dm_event->hdr.event) {
|
||||
case DM_CONN_OPEN_IND:
|
||||
tr_debug("Connection %d - Initialise CCC table", connId);
|
||||
/* set up CCC table with uninitialized (all zero) values */
|
||||
AttsCccInitTable(connId, nullptr);
|
||||
break;
|
||||
case DM_CONN_CLOSE_IND:
|
||||
/* clear CCC table on connection close */
|
||||
tr_debug("Connection %d - Clear CCC table", connId);
|
||||
AttsCccClearTable(connId);
|
||||
break;
|
||||
default:
|
||||
|
@ -465,10 +498,16 @@ void BLEInstanceBase::stack_setup()
|
|||
{
|
||||
MBED_ASSERT(_hci_driver != nullptr);
|
||||
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
wsf_mbed_trace_init();
|
||||
#endif // MBED_CONF_MBED_TRACE_ENABLE
|
||||
|
||||
wsfHandlerId_t handlerId;
|
||||
|
||||
buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();
|
||||
|
||||
tr_info("Allocated %d bytes for Cordio", buf_pool_desc.buffer_size);
|
||||
|
||||
// use the buffer for the WSF heap
|
||||
SystemHeapStart = buf_pool_desc.buffer_memory;
|
||||
SystemHeapSize = buf_pool_desc.buffer_size;
|
||||
|
@ -489,6 +528,54 @@ void BLEInstanceBase::stack_setup()
|
|||
buf_pool_desc.buffer_size - bytes_used);
|
||||
}
|
||||
|
||||
tr_info("BLE features enabled:"
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
" EXTENDED_ADVERTISING"
|
||||
#endif
|
||||
#if BLE_FEATURE_GATT_CLIENT
|
||||
" GATT_CLIENT"
|
||||
#endif
|
||||
#if BLE_FEATURE_GATT_SERVER
|
||||
" GATT_SERVER"
|
||||
#endif
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
" PERIODIC_ADVERTISING"
|
||||
#endif
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
" PHY_MANAGEMENT"
|
||||
#endif
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
" PRIVACY"
|
||||
#endif
|
||||
#if BLE_FEATURE_SECURE_CONNECTIONS
|
||||
" SECURE_CONNECTIONS"
|
||||
#endif
|
||||
#if BLE_FEATURE_SECURITY
|
||||
" SECURITY"
|
||||
#endif
|
||||
#if BLE_FEATURE_SIGNING
|
||||
" SIGNING"
|
||||
#endif
|
||||
#if BLE_FEATURE_WHITELIST
|
||||
" WHITELIST"
|
||||
#endif
|
||||
);
|
||||
|
||||
tr_info("BLE roles enabled:"
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
" PERIPHERAL"
|
||||
#elif BLE_ROLE_BROADCASTER
|
||||
" BROADCASTER"
|
||||
#endif
|
||||
#if BLE_ROLE_CENTRAL
|
||||
" CENTRAL"
|
||||
#elif BLE_ROLE_OBSERVER
|
||||
" OBSERVER"
|
||||
#endif
|
||||
);
|
||||
|
||||
tr_info("Initialising Cordio host stack");
|
||||
|
||||
WsfTimerInit();
|
||||
|
||||
// Note: SecInit required for RandInit.
|
||||
|
@ -502,9 +589,11 @@ void BLEInstanceBase::stack_setup()
|
|||
#endif
|
||||
|
||||
handlerId = WsfOsSetNextHandler(HciHandler);
|
||||
tr_debug("HCI handler id: %x", handlerId);
|
||||
HciHandlerInit(handlerId);
|
||||
|
||||
handlerId = WsfOsSetNextHandler(DmHandler);
|
||||
tr_debug("DM handler id: %x", handlerId);
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
DmAdvInit();
|
||||
|
@ -546,6 +635,7 @@ void BLEInstanceBase::stack_setup()
|
|||
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
|
||||
tr_debug("L2C slave handler id: %x", handlerId);
|
||||
L2cSlaveHandlerInit(handlerId);
|
||||
#endif
|
||||
|
||||
|
@ -563,6 +653,7 @@ void BLEInstanceBase::stack_setup()
|
|||
|
||||
#if BLE_FEATURE_ATT
|
||||
handlerId = WsfOsSetNextHandler(AttHandler);
|
||||
tr_debug("ATT handler id: %x", handlerId);
|
||||
AttHandlerInit(handlerId);
|
||||
|
||||
#if BLE_FEATURE_GATT_SERVER
|
||||
|
@ -587,6 +678,7 @@ void BLEInstanceBase::stack_setup()
|
|||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
handlerId = WsfOsSetNextHandler(SmpHandler);
|
||||
tr_debug("SMP handler id: %x", handlerId);
|
||||
SmpHandlerInit(handlerId);
|
||||
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
|
@ -606,6 +698,7 @@ void BLEInstanceBase::stack_setup()
|
|||
#endif // BLE_FEATURE_SECURITY
|
||||
|
||||
stack_handler_id = WsfOsSetNextHandler(&BLEInstanceBase::stack_handler);
|
||||
tr_debug("stack handler id: %x", stack_handler_id);
|
||||
|
||||
HciSetMaxRxAclLen(MBED_CONF_CORDIO_RX_ACL_BUFFER_SIZE);
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
#include <new>
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLGS"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
|
@ -67,6 +72,7 @@ GattServer &GattServer::getInstance()
|
|||
|
||||
void GattServer::initialize()
|
||||
{
|
||||
tr_info("Initialize GattServer");
|
||||
#if BLE_FEATURE_SECURITY
|
||||
AttsAuthorRegister(atts_auth_cb);
|
||||
#endif
|
||||
|
@ -84,6 +90,10 @@ void GattServer::add_default_services()
|
|||
|
||||
ble_error_t GattServer::addService(GattService &service)
|
||||
{
|
||||
tr_info("Add service with UUID=%s and %d characteristic(s) to the Gatt Server",
|
||||
to_string(service.getUUID()),
|
||||
service.getCharacteristicCount());
|
||||
|
||||
add_default_services();
|
||||
// create and fill the service structure
|
||||
internal_service_t *att_service = new internal_service_t;
|
||||
|
@ -98,6 +108,7 @@ ble_error_t GattServer::addService(GattService &service)
|
|||
att_service->attGroup.pAttr =
|
||||
(attsAttr_t *) alloc_block(attributes_count * sizeof(attsAttr_t));
|
||||
if (att_service->attGroup.pAttr == nullptr) {
|
||||
tr_error("Failed to create Cordio attribute list");
|
||||
delete att_service;
|
||||
return BLE_ERROR_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
@ -121,6 +132,7 @@ ble_error_t GattServer::addService(GattService &service)
|
|||
// - att_service->attGroup.pAttr
|
||||
// - blocks allocated for characteristics value
|
||||
// NOTE: those are rightfully released when reset() is called.
|
||||
tr_error("Failed to insert characteristic");
|
||||
delete att_service;
|
||||
return err;
|
||||
}
|
||||
|
@ -197,8 +209,43 @@ ble_error_t GattServer::insert_characteristic(
|
|||
attsAttr_t *&attribute_it
|
||||
)
|
||||
{
|
||||
tr_info("Insert characteristic %s - "
|
||||
"valuePtr=%p, "
|
||||
"lenMax=%d, "
|
||||
"len=%d, "
|
||||
"hasVariableLength=%s, "
|
||||
"read_security=%s, "
|
||||
"write_security=%s, "
|
||||
"properties=[ %s%s%s%s%s%s%s%s], "
|
||||
"descriptor_count=%d",
|
||||
to_string(characteristic->getValueAttribute().getUUID()),
|
||||
characteristic->getValueAttribute().getValuePtr(),
|
||||
characteristic->getValueAttribute().getMaxLength(),
|
||||
characteristic->getValueAttribute().getLength(),
|
||||
to_string(characteristic->getValueAttribute().hasVariableLength()),
|
||||
to_string(characteristic->getValueAttribute().getReadSecurityRequirement()),
|
||||
to_string(characteristic->getValueAttribute().getWriteSecurityRequirement()),
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_BROADCAST
|
||||
? "BROADCAST " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_READ
|
||||
? "READ " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
|
||||
? "WRITE_WITHOUT_RESPONSE " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_WRITE
|
||||
? "WRITE " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_NOTIFY
|
||||
? "NOTIFY " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_INDICATE
|
||||
? "INDICATE " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES
|
||||
? "AUTHENTICATED_SIGNED_WRITES " : "",
|
||||
characteristic->getProperties() & GattCharacteristic::Properties_t::BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES
|
||||
? "EXTENDED_PROPERTIES " : "",
|
||||
characteristic->getDescriptorCount());
|
||||
|
||||
bool valid = is_characteristic_valid(characteristic);
|
||||
if (!valid) {
|
||||
tr_error("Characteristic is not valid");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -208,6 +255,7 @@ ble_error_t GattServer::insert_characteristic(
|
|||
insert_characteristic_declaration_attribute(characteristic, attribute_it);
|
||||
ble_error_t err = insert_characteristic_value_attribute(characteristic, attribute_it);
|
||||
if (err) {
|
||||
tr_error("Failed to insert value attribute");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -223,6 +271,7 @@ ble_error_t GattServer::insert_characteristic(
|
|||
);
|
||||
if (err) {
|
||||
return err;
|
||||
tr_error("Failed to insert descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,10 +279,14 @@ ble_error_t GattServer::insert_characteristic(
|
|||
if ((properties & UPDATE_PROPERTIES) && (cccd_created == false)) {
|
||||
err = insert_cccd(characteristic, attribute_it);
|
||||
if (err) {
|
||||
tr_error("Failed to insert implicit CCCD");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
tr_info("Successfully inserted characteristic %s: handle=%d",
|
||||
to_string(characteristic->getValueAttribute().getUUID()),
|
||||
characteristic->getValueHandle());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -282,6 +335,9 @@ void GattServer::insert_characteristic_declaration_attribute(
|
|||
attsAttr_t *&attribute_it
|
||||
)
|
||||
{
|
||||
tr_info("Insert declaration attribute in characteristic %s",
|
||||
to_string(characteristic->getValueAttribute().getUUID()));
|
||||
|
||||
const UUID &value_uuid = characteristic->getValueAttribute().getUUID();
|
||||
|
||||
// move the current handle to point to the value handle
|
||||
|
@ -311,6 +367,9 @@ ble_error_t GattServer::insert_characteristic_value_attribute(
|
|||
attsAttr_t *&attribute_it
|
||||
)
|
||||
{
|
||||
tr_info("Insert value attribute in characteristic %s",
|
||||
to_string(characteristic->getValueAttribute().getUUID()));
|
||||
|
||||
GattAttribute &value_attribute = characteristic->getValueAttribute();
|
||||
uint8_t properties = characteristic->getProperties();
|
||||
|
||||
|
@ -417,12 +476,15 @@ ble_error_t GattServer::insert_characteristic_value_attribute(
|
|||
characteristic->isWriteAuthorizationEnabled()
|
||||
) {
|
||||
if (_auth_callbacks_count >= MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT) {
|
||||
tr_error("Authorisation characteristic count cannot be greater than %d",
|
||||
MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT);
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
char_auth_callback *new_cb = (char_auth_callback *) alloc_block(sizeof(char_auth_callback));
|
||||
|
||||
if (!new_cb) {
|
||||
tr_error("Failed to allocate space on the heap for new R/W authorisation callbacks");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -458,6 +520,9 @@ ble_error_t GattServer::insert_descriptor(
|
|||
bool &cccd_created
|
||||
)
|
||||
{
|
||||
tr_info("Insert descriptor in characteristic %s",
|
||||
to_string(characteristic->getValueAttribute().getUUID()));
|
||||
|
||||
uint8_t properties = characteristic->getProperties();
|
||||
|
||||
currentHandle++;
|
||||
|
@ -481,16 +546,21 @@ ble_error_t GattServer::insert_descriptor(
|
|||
// handle the special case of a CCCD
|
||||
if (descriptor->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) {
|
||||
if (cccd_cnt >= MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT) {
|
||||
tr_error("CCCD count cannot be greater than/equal to %d",
|
||||
MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT);
|
||||
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
if (descriptor->isReadAllowed() == false ||
|
||||
descriptor->getReadSecurityRequirement() != att_security_requirement_t::NONE
|
||||
) {
|
||||
tr_error("The attribute must be readable and secure");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cccd_created = true;
|
||||
tr_info("cccd_created=%s", to_string(cccd_created));
|
||||
attribute_it->settings |= ATTS_SET_CCC;
|
||||
|
||||
cccds[cccd_cnt].handle = currentHandle;
|
||||
|
@ -587,7 +657,11 @@ ble_error_t GattServer::insert_cccd(
|
|||
attsAttr_t *&attribute_it
|
||||
)
|
||||
{
|
||||
tr_info("Insert CCCD in characteristic %s",
|
||||
to_string(characteristic->getValueAttribute().getUUID()));
|
||||
|
||||
if (cccd_cnt >= MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT) {
|
||||
tr_error("failed insert cccd: table full");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -626,6 +700,7 @@ ble_error_t GattServer::insert_cccd(
|
|||
false);
|
||||
|
||||
if(implicit_cccd == nullptr) {
|
||||
tr_error("failed to create implicit CCCD");
|
||||
currentHandle--;
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
@ -651,6 +726,7 @@ ble_error_t GattServer::read(
|
|||
uint8_t *att_value = nullptr;
|
||||
|
||||
if (AttsGetAttr(att_handle, &att_length, &att_value) != ATT_SUCCESS) {
|
||||
tr_error("Failed to read attribute %d: attribute not found", att_handle);
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -660,6 +736,9 @@ ble_error_t GattServer::read(
|
|||
|
||||
*buffer_length = att_length;
|
||||
|
||||
tr_debug("Read attribute %d - value=%s",
|
||||
att_handle,
|
||||
mbed_trace_array(buffer, *buffer_length));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -674,6 +753,9 @@ ble_error_t GattServer::read(
|
|||
uint8_t cccd_index;
|
||||
if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
|
||||
if (connection == DM_CONN_ID_NONE) {
|
||||
tr_error("Failed to read attribute %d on connection %d: unknown connection ID",
|
||||
att_handle,
|
||||
connection);
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
uint16_t cccd_value = AttsCccGet(connection, cccd_index);
|
||||
|
@ -684,6 +766,11 @@ ble_error_t GattServer::read(
|
|||
}
|
||||
|
||||
*buffer_length = cccd_length;
|
||||
|
||||
tr_debug("Connection %d: read attribute %d - value=%s",
|
||||
connection,
|
||||
att_handle,
|
||||
mbed_trace_array(buffer, *buffer_length));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -698,11 +785,19 @@ ble_error_t GattServer::write(
|
|||
bool local_only
|
||||
)
|
||||
{
|
||||
tr_info("Write attribute %d - "
|
||||
"value=%s, "
|
||||
"local_only=%s",
|
||||
att_handle,
|
||||
mbed_trace_array(buffer, len),
|
||||
to_string(local_only));
|
||||
|
||||
// Check to see if this is a CCCD, if it is the case update the value for all
|
||||
// connections
|
||||
uint8_t cccd_index;
|
||||
if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
|
||||
if (len != sizeof(uint16_t)) {
|
||||
tr_error("CCCDs must be 16 bits");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -720,6 +815,7 @@ ble_error_t GattServer::write(
|
|||
|
||||
// write the value to the attribute handle
|
||||
if (AttsSetAttr(att_handle, len, (uint8_t *) buffer) != ATT_SUCCESS) {
|
||||
tr_error("Invalid attribute length");
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -762,10 +858,19 @@ ble_error_t GattServer::write(
|
|||
bool local_only
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d: write attribute %d - "
|
||||
"value=%s, "
|
||||
"local_only=%s",
|
||||
connection,
|
||||
att_handle,
|
||||
mbed_trace_array(buffer, len),
|
||||
to_string(local_only));
|
||||
|
||||
// Check to see if this is a CCCD
|
||||
uint8_t cccd_index;
|
||||
if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
|
||||
if ((connection == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits
|
||||
tr_error("Unknown connection ID/length not 16 bits");
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -777,6 +882,7 @@ ble_error_t GattServer::write(
|
|||
|
||||
// write the value to the attribute handle
|
||||
if (AttsSetAttr(att_handle, len, (uint8_t *) buffer) != ATT_SUCCESS) {
|
||||
tr_error("Invalid attribute length");
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -817,16 +923,21 @@ ble_error_t GattServer::areUpdatesEnabled(
|
|||
uint16_t cccd_value = AttsCccGet(conn_id, idx);
|
||||
if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) {
|
||||
*enabled = true;
|
||||
tr_debug("Updates are enabled in characteristic %s",
|
||||
to_string(characteristic.getValueAttribute().getUUID()));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*enabled = false;
|
||||
tr_debug("Updates are not enabled in characteristic %s",
|
||||
to_string(characteristic.getValueAttribute().getUUID()));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
tr_error("Failed to determine if updates are enabled: characteristic %s not in CCCD table",
|
||||
to_string(characteristic.getValueAttribute().getUUID()));
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -837,6 +948,7 @@ ble_error_t GattServer::areUpdatesEnabled(
|
|||
)
|
||||
{
|
||||
if (connectionHandle == DM_CONN_ID_NONE) {
|
||||
tr_error("Connection %d: failed to determine if updates are enabled - unknown connection ID", connectionHandle);
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -848,9 +960,17 @@ ble_error_t GattServer::areUpdatesEnabled(
|
|||
} else {
|
||||
*enabled = false;
|
||||
}
|
||||
tr_debug("Connection %d: updates are%s enabled in characteristic %s",
|
||||
connectionHandle,
|
||||
*enabled ? "" : " not",
|
||||
to_string(characteristic.getValueAttribute().getUUID()));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
tr_error("Connection %d: failed to determine if updates are enabled - characteristic %s not in CCCD table",
|
||||
connectionHandle,
|
||||
to_string(characteristic.getValueAttribute().getUUID()));
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
|
@ -924,8 +1044,9 @@ GapAdvertisingData::Appearance GattServer::getAppearance()
|
|||
|
||||
ble_error_t GattServer::reset(ble::GattServer* server)
|
||||
{
|
||||
tr_info("Reset GattServer");
|
||||
/* Notify that the instance is about to shutdown */
|
||||
if(eventHandler) {
|
||||
if (eventHandler) {
|
||||
eventHandler->onShutdown(*server);
|
||||
}
|
||||
|
||||
|
@ -986,6 +1107,7 @@ void GattServer::att_cb(const attEvt_t *evt)
|
|||
{
|
||||
if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATT_MTU_UPDATE_IND) {
|
||||
ble::GattServer::EventHandler *handler = getInstance().getEventHandler();
|
||||
tr_info("Connection %d: Att MTU changed, new MTU size is %d bytes", evt->hdr.param, evt->mtu);
|
||||
if (handler) {
|
||||
handler->onAttMtuChange(evt->hdr.param, evt->mtu);
|
||||
}
|
||||
|
@ -1016,6 +1138,11 @@ uint8_t GattServer::atts_read_cb(
|
|||
auth_cb->read_cb.call(&read_auth_params);
|
||||
|
||||
if (read_auth_params.authorizationReply != AUTH_CALLBACK_REPLY_SUCCESS) {
|
||||
tr_warning("Request to read attribute %d on connection %d declined with authorization reply %s",
|
||||
handle,
|
||||
connId,
|
||||
to_string(read_auth_params.authorizationReply & 0xFF));
|
||||
|
||||
return read_auth_params.authorizationReply & 0xFF;
|
||||
}
|
||||
|
||||
|
@ -1023,6 +1150,11 @@ uint8_t GattServer::atts_read_cb(
|
|||
*pAttr->pLen = read_auth_params.len;
|
||||
}
|
||||
|
||||
tr_debug("Read attribute %d on connection %d - value=%s",
|
||||
handle,
|
||||
connId,
|
||||
mbed_trace_array(pAttr->pValue, *pAttr->pLen));
|
||||
|
||||
GattReadCallbackParams read_params = {
|
||||
connId,
|
||||
handle,
|
||||
|
@ -1046,6 +1178,9 @@ uint8_t GattServer::atts_write_cb(
|
|||
attsAttr_t *pAttr
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d: Write attribute %d, operation=%d, offset=%d, value=%s",
|
||||
connId, handle, operation, offset, mbed_trace_array(pValue, len));
|
||||
|
||||
char_auth_callback* auth_cb = getInstance().get_auth_callback(handle);
|
||||
if (auth_cb && auth_cb->write_cb) {
|
||||
GattWriteAuthCallbackParams write_auth_params = {
|
||||
|
@ -1060,6 +1195,11 @@ uint8_t GattServer::atts_write_cb(
|
|||
auth_cb->write_cb.call(&write_auth_params);
|
||||
|
||||
if (write_auth_params.authorizationReply != AUTH_CALLBACK_REPLY_SUCCESS) {
|
||||
tr_warning("Request to write attribute %d on connection %d declined with authorization reply %s",
|
||||
handle,
|
||||
connId,
|
||||
to_string(write_auth_params.authorizationReply & 0xFF));
|
||||
|
||||
return write_auth_params.authorizationReply & 0xFF;
|
||||
}
|
||||
}
|
||||
|
@ -1131,6 +1271,8 @@ uint8_t GattServer::atts_write_cb(
|
|||
|
||||
uint8_t GattServer::atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle)
|
||||
{
|
||||
tr_debug("Authenticate R/W request for attribute %d on connection %d", handle, connId);
|
||||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
// this CB is triggered when read or write of an attribute (either a value
|
||||
// handle or a descriptor) requires secure connection security.
|
||||
|
@ -1139,10 +1281,12 @@ uint8_t GattServer::atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t han
|
|||
link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED);
|
||||
ble_error_t err = security_manager.getLinkEncryption(connId, &encryption);
|
||||
if (err) {
|
||||
tr_error("Insufficient authentication");
|
||||
return ATT_ERR_AUTH;
|
||||
}
|
||||
|
||||
if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
|
||||
tr_error("The link must be secure and authenticated with a secure connection key");
|
||||
return ATT_ERR_AUTH;
|
||||
}
|
||||
|
||||
|
@ -1174,6 +1318,8 @@ void GattServer::add_generic_access_service()
|
|||
current_attribute->settings = 0;
|
||||
current_attribute->permissions = ATTS_PERMIT_READ;
|
||||
|
||||
tr_info("Add Generic Access Service to the Gatt Server: handle=%d", currentHandle);
|
||||
|
||||
// device name declaration
|
||||
currentHandle += 2; // note: incremented by two to get a pointer to the value handle
|
||||
++current_attribute;
|
||||
|
@ -1202,6 +1348,8 @@ void GattServer::add_generic_access_service()
|
|||
current_attribute->settings = ATTS_SET_VARIABLE_LEN;
|
||||
current_attribute->permissions = ATTS_PERMIT_READ;
|
||||
|
||||
tr_info("Add Device Name characteristic: handle=%d", currentHandle);
|
||||
|
||||
// appearance declaration
|
||||
currentHandle += 2; // note: incremented by two to get a pointer to the value handle
|
||||
++current_attribute;
|
||||
|
@ -1230,6 +1378,7 @@ void GattServer::add_generic_access_service()
|
|||
current_attribute->settings = 0;
|
||||
current_attribute->permissions = ATTS_PERMIT_READ;
|
||||
|
||||
tr_info("Add Appearance characteristic: handle=%d", currentHandle);
|
||||
|
||||
// peripheral preferred connection parameters declaration
|
||||
currentHandle += 2; // note: incremented by two to get a pointer to the value handle
|
||||
|
@ -1265,6 +1414,8 @@ void GattServer::add_generic_access_service()
|
|||
current_attribute->settings = 0;
|
||||
current_attribute->permissions = ATTS_PERMIT_READ;
|
||||
|
||||
tr_info("Add Peripheral Preferred Connection characteristic: handle=%d", currentHandle);
|
||||
|
||||
generic_access_service.service.endHandle = currentHandle;
|
||||
AttsAddGroup(&generic_access_service.service);
|
||||
}
|
||||
|
@ -1290,6 +1441,8 @@ void GattServer::add_generic_attribute_service()
|
|||
current_attribute->settings = 0;
|
||||
current_attribute->permissions = ATTS_PERMIT_READ;
|
||||
|
||||
tr_info("Add Generic Attribute Service to the Gatt Server: handle=%d", currentHandle);
|
||||
|
||||
// service changed declaration
|
||||
currentHandle += 2; // note: incremented by two to get a pointer to the value handle
|
||||
++current_attribute;
|
||||
|
@ -1317,6 +1470,8 @@ void GattServer::add_generic_attribute_service()
|
|||
current_attribute->settings = 0;
|
||||
current_attribute->permissions = 0;
|
||||
|
||||
tr_info("Add Service Changed characteristic: handle=%d", currentHandle);
|
||||
|
||||
// CCCD
|
||||
++current_attribute;
|
||||
current_attribute->pUuid = attCliChCfgUuid;
|
||||
|
@ -1528,6 +1683,9 @@ void GattServer::onConfirmationReceived(EventCallback_t callback)
|
|||
|
||||
void GattServer::setEventHandler(EventHandler *handler)
|
||||
{
|
||||
if (handler == nullptr) {
|
||||
tr_warning("Setting Gatt Server event handler to a null pointer");
|
||||
}
|
||||
eventHandler = handler;
|
||||
}
|
||||
|
||||
|
@ -1564,7 +1722,7 @@ void GattServer::handleEvent(
|
|||
{
|
||||
switch (type) {
|
||||
case GattServerEvents::GATT_EVENT_UPDATES_ENABLED:
|
||||
|
||||
tr_info("Updates enabled for attribute %d on connection %d", attributeHandle, connHandle);
|
||||
if(eventHandler) {
|
||||
GattUpdatesEnabledCallbackParams params({
|
||||
.connHandle = connHandle,
|
||||
|
@ -1579,7 +1737,7 @@ void GattServer::handleEvent(
|
|||
}
|
||||
break;
|
||||
case GattServerEvents::GATT_EVENT_UPDATES_DISABLED:
|
||||
|
||||
tr_info("Updates disabled for attribute %d on connection %d", attributeHandle, connHandle);
|
||||
if(eventHandler) {
|
||||
GattUpdatesDisabledCallbackParams params({
|
||||
.connHandle = connHandle,
|
||||
|
@ -1594,7 +1752,7 @@ void GattServer::handleEvent(
|
|||
}
|
||||
break;
|
||||
case GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED:
|
||||
|
||||
tr_debug("Confirmation received for attribute %d on connection %d", attributeHandle, connHandle);
|
||||
if(eventHandler) {
|
||||
GattConfirmationReceivedCallbackParams params({
|
||||
.connHandle = connHandle,
|
||||
|
@ -1610,7 +1768,7 @@ void GattServer::handleEvent(
|
|||
break;
|
||||
|
||||
case GattServerEvents::GATT_EVENT_DATA_SENT:
|
||||
|
||||
tr_debug("Data sent for attribute %d on connection %d", attributeHandle, connHandle);
|
||||
if(eventHandler) {
|
||||
GattDataSentCallbackParams params({
|
||||
.connHandle = connHandle,
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
#include "att_api.h"
|
||||
#include "att_defs.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLAT"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
|
@ -41,6 +46,7 @@ PalAttClient::~PalAttClient() = default;
|
|||
*/
|
||||
ble_error_t PalAttClient::exchange_mtu_request(connection_handle_t connection)
|
||||
{
|
||||
tr_info("Connection %d - AttcMtuReq mtu=%d", connection, pAttCfg->mtu);
|
||||
AttcMtuReq(connection, pAttCfg->mtu);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -65,6 +71,7 @@ ble_error_t PalAttClient::find_information_request(
|
|||
attribute_handle_range_t discovery_range
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - AttcFindInfoReq handles=[%d:%d]", connection_handle, discovery_range.begin, discovery_range.end);
|
||||
AttcFindInfoReq(
|
||||
connection_handle,
|
||||
discovery_range.begin,
|
||||
|
@ -84,6 +91,8 @@ ble_error_t PalAttClient::find_by_type_value_request(
|
|||
const Span<const uint8_t> &value
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcFindByTypeValueReq handles=[%d:%d] type=%d value=%s",
|
||||
connection_handle, discovery_range.begin, discovery_range.end, type, tr_array(value.data(), value.size()));
|
||||
AttcFindByTypeValueReq(
|
||||
connection_handle,
|
||||
discovery_range.begin,
|
||||
|
@ -105,6 +114,8 @@ ble_error_t PalAttClient::read_by_type_request(
|
|||
const UUID &type
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcReadByTypeReq handles=[%d:%d] uuid=%s",
|
||||
connection_handle, read_range.begin, read_range.end, to_string(type));
|
||||
AttcReadByTypeReq(
|
||||
connection_handle,
|
||||
read_range.begin,
|
||||
|
@ -124,6 +135,7 @@ ble_error_t PalAttClient::read_request(
|
|||
attribute_handle_t attribute_handle
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcReadReq handle=%d", connection_handle, attribute_handle);
|
||||
AttcReadReq(connection_handle, attribute_handle);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -137,6 +149,7 @@ ble_error_t PalAttClient::read_blob_request(
|
|||
uint16_t offset
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcReadLongReq handle=%d offset=%d", connection_handle, attribute_handle, offset);
|
||||
AttcReadLongReq(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -154,6 +167,8 @@ ble_error_t PalAttClient::read_multiple_request(
|
|||
const Span<const attribute_handle_t> &attribute_handles
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcReadMultipleReq handles=%s",
|
||||
connection_handle, tr_array((uint8_t*)attribute_handles.data(), attribute_handles.size()));
|
||||
AttcReadMultipleReq(
|
||||
connection_handle,
|
||||
attribute_handles.size(),
|
||||
|
@ -171,6 +186,8 @@ ble_error_t PalAttClient::read_by_group_type_request(
|
|||
const UUID &group_type
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcReadByGroupTypeReq handles=[%d:%d] uuid=%s",
|
||||
connection_handle, read_range.begin, read_range.end, to_string(group_type));
|
||||
AttcReadByGroupTypeReq(
|
||||
connection_handle,
|
||||
read_range.begin,
|
||||
|
@ -191,6 +208,8 @@ ble_error_t PalAttClient::write_request(
|
|||
const Span<const uint8_t> &value
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcWriteReq handle=%d value=%s",
|
||||
connection_handle, attribute_handle, tr_array(value.data(), value.size()));
|
||||
AttcWriteReq(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -209,6 +228,8 @@ ble_error_t PalAttClient::write_command(
|
|||
const Span<const uint8_t> &value
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcWriteCmd handle=%d value=%s",
|
||||
connection_handle, attribute_handle, tr_array(value.data(), value.size()));
|
||||
AttcWriteCmd(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -227,6 +248,8 @@ ble_error_t PalAttClient::signed_write_command(
|
|||
const Span<const uint8_t> &value
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcSignedWriteCmd handle=%d sign_counter=&d value=%s",
|
||||
connection_handle, attribute_handle, _local_sign_counter, tr_array(value.data(), value.size()));
|
||||
AttcSignedWriteCmd(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -261,6 +284,8 @@ ble_error_t PalAttClient::prepare_write_request(
|
|||
const Span<const uint8_t> &value
|
||||
)
|
||||
{
|
||||
tr_debug("Connection %d - AttcPrepareWriteReq handle=%d offset=%d value=%s",
|
||||
connection_handle, attribute_handle, offset, tr_array(value.data(), value.size()));
|
||||
AttcPrepareWriteReq(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -281,6 +306,8 @@ ble_error_t PalAttClient::execute_write_request(
|
|||
bool execute
|
||||
)
|
||||
{
|
||||
tr_debug("AttcExecuteWriteReq %d - execute=%s",
|
||||
connection_handle, to_string(execute));
|
||||
AttcExecuteWriteReq(
|
||||
connection_handle,
|
||||
execute
|
||||
|
@ -396,6 +423,7 @@ void PalAttClient::on_transaction_timeout(
|
|||
connection_handle_t connection_handle
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - transaction timed out", connection_handle);
|
||||
if (_transaction_timeout_cb) {
|
||||
_transaction_timeout_cb(connection_handle);
|
||||
}
|
||||
|
@ -404,6 +432,7 @@ void PalAttClient::on_transaction_timeout(
|
|||
#if BLE_FEATURE_GATT_CLIENT
|
||||
void PalAttClient::att_client_handler(const attEvt_t *event)
|
||||
{
|
||||
tr_debug("ATT event: %s status: %s", att_client_callback_event_to_string(event->hdr.event), att_error_code_to_string(event->hdr.status));
|
||||
if (event->hdr.status == ATT_SUCCESS && event->hdr.event == ATT_MTU_UPDATE_IND) {
|
||||
ble::impl::BLEInstanceBase &ble = BLEInstanceBase::deviceInstance();
|
||||
PalGattClientEventHandler *handler = ble.getPalGattClient().get_event_handler();
|
||||
|
|
|
@ -22,10 +22,16 @@
|
|||
#include "dm_main.h"
|
||||
#include "dm_conn.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLDM"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
namespace {
|
||||
|
||||
bool dummy_gap_event_handler(const wsfMsgHdr_t *msg)
|
||||
{
|
||||
return false;
|
||||
|
@ -102,6 +108,10 @@ address_t PalGap::get_random_address()
|
|||
|
||||
ble_error_t PalGap::set_random_address(const address_t &address)
|
||||
{
|
||||
tr_info("Set random address - "
|
||||
"address=%s",
|
||||
to_string(address));
|
||||
|
||||
device_random_address = address;
|
||||
DmDevSetRandAddr(const_cast<uint8_t *>(address.data()));
|
||||
return BLE_ERROR_NONE;
|
||||
|
@ -119,6 +129,26 @@ ble_error_t PalGap::set_advertising_parameters(
|
|||
advertising_filter_policy_t advertising_filter_policy
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set advertising parameters - "
|
||||
"advertising_interval_min=%d, "
|
||||
"advertising_interval_max=%d, "
|
||||
"advertising_type=%s, "
|
||||
"own_address_type=%s, "
|
||||
"peer_address_type=%s, "
|
||||
"peer_address=%s, "
|
||||
"advertising_channel_map=%s, "
|
||||
"advertising_filter_policy_t=%s",
|
||||
advertising_interval_min,
|
||||
advertising_interval_max,
|
||||
to_string(advertising_type),
|
||||
to_string(own_address_type),
|
||||
to_string(peer_address_type),
|
||||
to_string(peer_address),
|
||||
to_string(advertising_channel_map),
|
||||
to_string(advertising_filter_policy));
|
||||
#endif
|
||||
|
||||
DmAdvSetInterval(
|
||||
DM_ADV_HANDLE_DEFAULT,
|
||||
advertising_interval_min,
|
||||
|
@ -160,6 +190,14 @@ ble_error_t PalGap::set_advertising_data(
|
|||
const advertising_data_t &advertising_data
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set advertising data - "
|
||||
"advertising_data_length=%d, "
|
||||
"advertising_data=%s",
|
||||
advertising_data_length,
|
||||
mbed_trace_array(advertising_data.data(), advertising_data_length));
|
||||
#endif
|
||||
|
||||
DmAdvSetData(
|
||||
DM_ADV_HANDLE_DEFAULT,
|
||||
HCI_ADV_DATA_OP_COMP_FRAG,
|
||||
|
@ -170,12 +208,19 @@ ble_error_t PalGap::set_advertising_data(
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalGap::set_scan_response_data(
|
||||
uint8_t scan_response_data_length,
|
||||
const advertising_data_t &scan_response_data
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set scan response data - "
|
||||
"scan_response_data_length=%d, "
|
||||
"scan_response_data=%s",
|
||||
scan_response_data_length,
|
||||
mbed_trace_array(scan_response_data.data(), scan_response_data_length));
|
||||
#endif
|
||||
|
||||
DmAdvSetData(
|
||||
DM_ADV_HANDLE_DEFAULT,
|
||||
HCI_ADV_DATA_OP_COMP_FRAG,
|
||||
|
@ -189,6 +234,10 @@ ble_error_t PalGap::set_scan_response_data(
|
|||
|
||||
ble_error_t PalGap::advertising_enable(bool enable)
|
||||
{
|
||||
tr_info("Advertising enable - "
|
||||
"enable=%s",
|
||||
to_string(enable));
|
||||
|
||||
if (enable) {
|
||||
// The Cordio stack requires to start direct advertising with
|
||||
// the function DmConnAccept instead of the function DmAdvStart.
|
||||
|
@ -206,6 +255,7 @@ ble_error_t PalGap::advertising_enable(bool enable)
|
|||
direct_adv_cb->peer_address.data()
|
||||
);
|
||||
if (direct_adv_cb->connection_handle == DM_CONN_ID_NONE) {
|
||||
tr_error("unknown ID for pending callback");
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
} else {
|
||||
direct_adv_cb->state = direct_adv_cb_t::running;
|
||||
|
@ -247,6 +297,20 @@ ble_error_t PalGap::set_scan_parameters(
|
|||
scanning_filter_policy_t filter_policy
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set scan parameters - "
|
||||
"active_scanning=%s, "
|
||||
"scan_interval=%d, "
|
||||
"scan_window=%d, "
|
||||
"own_address_type=%s, "
|
||||
"filter_policy=%s",
|
||||
to_string(active_scanning),
|
||||
scan_interval,
|
||||
scan_window,
|
||||
to_string(own_address_type),
|
||||
to_string(filter_policy));
|
||||
#endif
|
||||
|
||||
use_active_scanning = active_scanning;
|
||||
DmScanSetInterval(HCI_INIT_PHY_LE_1M_BIT, &scan_interval, &scan_window);
|
||||
DmScanSetAddrType(own_address_type.value());
|
||||
|
@ -265,6 +329,12 @@ ble_error_t PalGap::scan_enable(
|
|||
bool filter_duplicates
|
||||
)
|
||||
{
|
||||
tr_info("Scan enable - "
|
||||
"enable=%s, "
|
||||
"filter_duplicates=%s",
|
||||
to_string(enable),
|
||||
to_string(filter_duplicates));
|
||||
|
||||
if (enable) {
|
||||
uint8_t scanType = use_active_scanning ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE;
|
||||
DmScanStart(
|
||||
|
@ -298,6 +368,34 @@ ble_error_t PalGap::create_connection(
|
|||
uint16_t maximum_connection_event_length
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Create Connection - "
|
||||
"scan_interval=%d, "
|
||||
"scan_window=%d, "
|
||||
"initiator_policy=%s, "
|
||||
"peer_address_type=%s, "
|
||||
"peer_address=%s, "
|
||||
"own_address_type=%s, "
|
||||
"connection_interval_min=%d, "
|
||||
"connection_interval_max=%d, "
|
||||
"connection_latency=%d, "
|
||||
"supervision_timout=%d, "
|
||||
"minimum_connection_event_length=%d, "
|
||||
"maximum_connection_event_length=%d",
|
||||
scan_interval,
|
||||
scan_window,
|
||||
to_string(initiator_policy),
|
||||
to_string(peer_address_type),
|
||||
to_string(peer_address),
|
||||
to_string(own_address_type),
|
||||
connection_interval_min,
|
||||
connection_interval_max,
|
||||
connection_latency,
|
||||
supervision_timeout,
|
||||
minimum_connection_event_length,
|
||||
maximum_connection_event_length);
|
||||
#endif
|
||||
|
||||
DmConnSetScanInterval(scan_interval, scan_window);
|
||||
#if BLE_FEATURE_WHITELIST
|
||||
DmDevSetFilterPolicy(DM_FILT_POLICY_MODE_INIT, initiator_policy.value());
|
||||
|
@ -322,6 +420,7 @@ ble_error_t PalGap::create_connection(
|
|||
);
|
||||
|
||||
if (connection_id == DM_CONN_ID_NONE) {
|
||||
tr_error("unknown ID for open connection");
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -368,6 +467,12 @@ ble_error_t PalGap::add_device_to_whitelist(
|
|||
address_t address
|
||||
)
|
||||
{
|
||||
tr_info("Add device to whitelist - "
|
||||
"address_type=%s,"
|
||||
"address=%s",
|
||||
to_string(address_type),
|
||||
to_string(address));
|
||||
|
||||
DmDevWhiteListAdd(
|
||||
address_type.value(),
|
||||
const_cast<uint8_t *>(address.data())
|
||||
|
@ -381,6 +486,12 @@ ble_error_t PalGap::remove_device_from_whitelist(
|
|||
address_t address
|
||||
)
|
||||
{
|
||||
tr_info("Remove device from whitelist - "
|
||||
"address_type=%s, "
|
||||
"address=%s",
|
||||
to_string(address_type),
|
||||
to_string(address));
|
||||
|
||||
DmDevWhiteListRemove(
|
||||
address_type.value(),
|
||||
const_cast<uint8_t *>(address.data())
|
||||
|
@ -400,7 +511,25 @@ ble_error_t PalGap::connection_parameters_update(
|
|||
uint16_t maximum_connection_event_length
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Connection %d: connection parameters update - "
|
||||
"connection_interval_min=%d, "
|
||||
"connection_interval_max=%d, "
|
||||
"connection_latency=%d, "
|
||||
"supervision_timeout=%d, "
|
||||
"minimum_connection_event_length=%d, "
|
||||
"maximum_connection_event_length=%d",
|
||||
connection,
|
||||
connection_interval_min,
|
||||
connection_interval_max,
|
||||
connection_latency,
|
||||
supervision_timeout,
|
||||
minimum_connection_event_length,
|
||||
maximum_connection_event_length);
|
||||
#endif
|
||||
|
||||
if (DmConnCheckIdle(connection) != 0) {
|
||||
tr_error("connection busy");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -431,6 +560,21 @@ ble_error_t PalGap::accept_connection_parameter_request(
|
|||
uint16_t maximum_connection_event_length
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d: accept connection parameter request - "
|
||||
"interval_min=%d, "
|
||||
"interval_max=%d, "
|
||||
"latency=%d, "
|
||||
"supervision_timeout=%d, "
|
||||
"minimum_connection_event_length=%d, "
|
||||
"maximum_connection_event_length=%d",
|
||||
connection_handle,
|
||||
interval_min,
|
||||
interval_max,
|
||||
latency,
|
||||
supervision_timeout,
|
||||
minimum_connection_event_length,
|
||||
maximum_connection_event_length);
|
||||
|
||||
hciConnSpec_t connection_spec = {
|
||||
interval_min,
|
||||
interval_max,
|
||||
|
@ -449,6 +593,11 @@ ble_error_t PalGap::reject_connection_parameter_request(
|
|||
hci_error_code_t rejection_reason
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d: reject_connection_parameter_request - "
|
||||
"rejection_reason=%s",
|
||||
connection_handle,
|
||||
to_string(rejection_reason));
|
||||
|
||||
DmRemoteConnParamReqNegReply(
|
||||
connection_handle,
|
||||
rejection_reason.value()
|
||||
|
@ -462,6 +611,13 @@ ble_error_t PalGap::disconnect(
|
|||
local_disconnection_reason_t disconnection_reason
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Connection %d: disconnect - "
|
||||
"disconnection_reason=%s",
|
||||
connection,
|
||||
to_string(disconnection_reason));
|
||||
#endif
|
||||
|
||||
DmConnClose(
|
||||
DM_CLIENT_ID_APP,
|
||||
connection,
|
||||
|
@ -475,11 +631,13 @@ ble_error_t PalGap::disconnect(
|
|||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
ble_error_t PalGap::read_phy(connection_handle_t connection)
|
||||
{
|
||||
tr_info("Connection %d: read phy", connection);
|
||||
if (is_feature_supported(controller_supported_features_t::LE_2M_PHY)
|
||||
|| is_feature_supported(controller_supported_features_t::LE_CODED_PHY)) {
|
||||
DmReadPhy(connection);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
tr_error("Only 1M PHY supported");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -488,6 +646,14 @@ ble_error_t PalGap::set_preferred_phys(
|
|||
const phy_set_t &rx_phys
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set preferred phys -"
|
||||
"tx_phys=%s, "
|
||||
"rx_phys=%s",
|
||||
to_string(tx_phys),
|
||||
to_string(rx_phys));
|
||||
#endif
|
||||
|
||||
DmSetDefaultPhy(
|
||||
create_all_phys_value(tx_phys, rx_phys),
|
||||
tx_phys.value(),
|
||||
|
@ -505,6 +671,17 @@ ble_error_t PalGap::set_phy(
|
|||
coded_symbol_per_bit_t coded_symbol
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Connection %d: set phy - "
|
||||
"tx_phys=%s, "
|
||||
"rx_phys=%s, "
|
||||
"coded_symbol=%s",
|
||||
connection,
|
||||
to_string(tx_phys),
|
||||
to_string(rx_phys),
|
||||
to_string(coded_symbol));
|
||||
#endif
|
||||
|
||||
/* if phy set is empty set corresponding all_phys bit to 1 */
|
||||
uint8_t all_phys = 0;
|
||||
if (tx_phys.value() == 0) {
|
||||
|
@ -869,6 +1046,11 @@ ble_error_t PalGap::set_advertising_set_random_address(
|
|||
const address_t &address
|
||||
)
|
||||
{
|
||||
tr_info("Advertising set %d: set random address - "
|
||||
"address=%s",
|
||||
advertising_handle,
|
||||
to_string(address));
|
||||
|
||||
DmAdvSetRandAddr(advertising_handle, address.data());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -891,15 +1073,57 @@ ble_error_t PalGap::set_extended_advertising_parameters(
|
|||
bool scan_request_notification
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Advertising set %d: set extended advertising parameters - "
|
||||
"event_properties:[%s%s%s%s%s%s%s ], "
|
||||
"primary_advertising_interval_min=%" PRIu32 ", "
|
||||
"primary_advertising_interval_max=%" PRIu32 ", "
|
||||
"primary_advertising_channel_map=%s, "
|
||||
"own_address_type=%s, "
|
||||
"peer_address_type=%s, "
|
||||
"peer_address=%s, "
|
||||
"advertising_filter_policy=%s, "
|
||||
"advertising_power=%d, "
|
||||
"primary_advertising_phy=%s, "
|
||||
"secondary_advertising_max_skip=%d, "
|
||||
"secondary_phy=%s, "
|
||||
"advertising_sid=%d, "
|
||||
"scan_request_notification=%s",
|
||||
advertising_handle,
|
||||
event_properties.connectable ? " connectable" : "",
|
||||
event_properties.scannable ? " scannable" : "",
|
||||
event_properties.directed ? " directed" : "",
|
||||
event_properties.high_duty_cycle ? " high_duty_cycle" : "",
|
||||
event_properties.use_legacy_pdu ? " use_legacy_pdu" : "",
|
||||
event_properties.omit_advertiser_address ? " omit_advertiser_address," : "",
|
||||
event_properties.include_tx_power ? " nclude_tx_power" : "",
|
||||
primary_advertising_interval_min,
|
||||
primary_advertising_interval_max,
|
||||
to_string(primary_advertising_channel_map),
|
||||
to_string(own_address_type),
|
||||
to_string(peer_address_type),
|
||||
to_string(peer_address),
|
||||
to_string(advertising_filter_policy),
|
||||
advertising_power,
|
||||
to_string(primary_advertising_phy),
|
||||
secondary_advertising_max_skip,
|
||||
to_string(secondary_phy),
|
||||
advertising_sid,
|
||||
to_string(scan_request_notification));
|
||||
#endif
|
||||
|
||||
uint8_t adv_type;
|
||||
|
||||
if (event_properties.use_legacy_pdu) {
|
||||
if (event_properties.directed == false) {
|
||||
tr_info("Legacy PDU w/undirected advertising event");
|
||||
if (event_properties.high_duty_cycle) {
|
||||
tr_error("cannot use high duty cycle");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (event_properties.connectable && event_properties.scannable == false) {
|
||||
tr_error("must be scannable if connectable");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -911,11 +1135,14 @@ ble_error_t PalGap::set_extended_advertising_parameters(
|
|||
adv_type = DM_ADV_NONCONN_UNDIRECT;
|
||||
}
|
||||
} else {
|
||||
tr_info("Legacy PDU w/directed advertising event");
|
||||
if (event_properties.scannable) {
|
||||
tr_error("cannot be scannable");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (event_properties.connectable == false) {
|
||||
tr_error("must be connectable");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -927,7 +1154,9 @@ ble_error_t PalGap::set_extended_advertising_parameters(
|
|||
}
|
||||
} else {
|
||||
if (event_properties.directed == false) {
|
||||
tr_info("Extended PDU w/undirected advertising event");
|
||||
if (event_properties.high_duty_cycle) {
|
||||
tr_error("cannot use high duty cycle");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -946,6 +1175,7 @@ ble_error_t PalGap::set_extended_advertising_parameters(
|
|||
// standpoint
|
||||
|
||||
if (event_properties.connectable && event_properties.scannable) {
|
||||
tr_error("cannot be scannable if connectable");
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
} else if (event_properties.connectable) {
|
||||
if (event_properties.high_duty_cycle) {
|
||||
|
@ -1022,6 +1252,17 @@ ble_error_t PalGap::set_periodic_advertising_parameters(
|
|||
bool advertise_power
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Advertising set %d: set periodic advertising parameters - "
|
||||
"periodic_advertising_min=%s, "
|
||||
"periodic_advertising_max=%s, "
|
||||
"advertise_power=%s",
|
||||
advertising_handle,
|
||||
to_string(periodic_advertising_min),
|
||||
to_string(periodic_advertising_max),
|
||||
to_string(advertise_power));
|
||||
#endif
|
||||
|
||||
DmPerAdvIncTxPwr(advertising_handle, advertise_power);
|
||||
DmPerAdvSetInterval(
|
||||
advertising_handle,
|
||||
|
@ -1043,6 +1284,19 @@ ble_error_t PalGap::set_extended_advertising_data(
|
|||
const uint8_t *advertising_data
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Advertising set %d: set extended advertising data - "
|
||||
"operation=%s, "
|
||||
"minimize_fragmentation=%s, "
|
||||
"advertising_data_size=%d, "
|
||||
"advertising_data=%s",
|
||||
advertising_handle,
|
||||
to_string(operation),
|
||||
to_string(minimize_fragmentation),
|
||||
advertising_data_size,
|
||||
mbed_trace_array(advertising_data, advertising_data_size));
|
||||
#endif
|
||||
|
||||
uint8_t frag_pref = minimize_fragmentation ?
|
||||
HCI_ADV_DATA_FRAG_PREF_NO_FRAG :
|
||||
HCI_ADV_DATA_FRAG_PREF_FRAG;
|
||||
|
@ -1068,6 +1322,17 @@ ble_error_t PalGap::set_periodic_advertising_data(
|
|||
const uint8_t *advertising_data
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Advertising set %d: set periodic advertising data - "
|
||||
"fragment_description=%s, "
|
||||
"advertising_data_size=%d, "
|
||||
"advertising_data=%s",
|
||||
advertising_handle,
|
||||
to_string(fragment_description),
|
||||
advertising_data_size,
|
||||
mbed_trace_array(advertising_data, advertising_data_size));
|
||||
#endif
|
||||
|
||||
DmPerAdvSetData(
|
||||
advertising_handle,
|
||||
fragment_description.value(),
|
||||
|
@ -1087,6 +1352,19 @@ ble_error_t PalGap::set_extended_scan_response_data(
|
|||
const uint8_t *scan_response_data
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Advertising data %d: set extended scan response data - "
|
||||
"operation=%s, "
|
||||
"minimize_fragmentation=%s, "
|
||||
"scan_response_data_size=%d, "
|
||||
"scan_response_data=%s",
|
||||
advertising_handle,
|
||||
to_string(operation),
|
||||
to_string(minimize_fragmentation),
|
||||
scan_response_data_size,
|
||||
mbed_trace_array(scan_response_data, scan_response_data_size));
|
||||
#endif
|
||||
|
||||
uint8_t frag_pref = minimize_fragmentation ?
|
||||
HCI_ADV_DATA_FRAG_PREF_NO_FRAG :
|
||||
HCI_ADV_DATA_FRAG_PREF_FRAG;
|
||||
|
@ -1112,7 +1390,14 @@ ble_error_t PalGap::extended_advertising_enable(
|
|||
const uint8_t *in_max_extended_advertising_events
|
||||
)
|
||||
{
|
||||
tr_info("Extended advertising enable - "
|
||||
"enable=%s, "
|
||||
"number_of_sets=%d",
|
||||
to_string(enable),
|
||||
number_of_sets);
|
||||
|
||||
if (number_of_sets > DM_NUM_ADV_SETS) {
|
||||
tr_error("number of sets cannot be greater than %d", DM_NUM_ADV_SETS);
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
@ -1143,6 +1428,7 @@ ble_error_t PalGap::extended_advertising_enable(
|
|||
direct_adv_cb->peer_address.data()
|
||||
);
|
||||
if (direct_adv_cb->connection_handle == DM_CONN_ID_NONE) {
|
||||
tr_error("unknown connection ID %d", direct_adv_cb->connection_handle);
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
} else {
|
||||
direct_adv_cb->state = direct_adv_cb_t::running;
|
||||
|
@ -1201,6 +1487,11 @@ ble_error_t PalGap::periodic_advertising_enable(
|
|||
advertising_handle_t advertising_handle
|
||||
)
|
||||
{
|
||||
tr_info("Advertising set %d: periodic advertsing enable - "
|
||||
"enable=%s",
|
||||
advertising_handle,
|
||||
to_string(enable));
|
||||
|
||||
if (enable) {
|
||||
DmPerAdvStart(advertising_handle);
|
||||
} else {
|
||||
|
@ -1265,6 +1556,16 @@ ble_error_t PalGap::set_extended_scan_parameters(
|
|||
const uint16_t *scan_window
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Set extended scan parameters - "
|
||||
"own_address_type=%s, "
|
||||
"filter_policy=%s, "
|
||||
"scanning_phys=%s",
|
||||
to_string(own_address_type),
|
||||
to_string(filter_policy),
|
||||
to_string(scanning_phys));
|
||||
#endif
|
||||
|
||||
DmScanSetAddrType(own_address_type.value());
|
||||
|
||||
for (size_t i = 0, count = scanning_phys.count(); i < count; ++i) {
|
||||
|
@ -1299,6 +1600,16 @@ ble_error_t PalGap::extended_scan_enable(
|
|||
uint16_t period
|
||||
)
|
||||
{
|
||||
tr_info("Extended scan enable - "
|
||||
"enable=%s, "
|
||||
"filter_duplicates=%s, "
|
||||
"duration=%d, "
|
||||
"period=%d",
|
||||
to_string(enable),
|
||||
to_string(filter_duplicates),
|
||||
duration,
|
||||
period);
|
||||
|
||||
if (enable) {
|
||||
uint32_t duration_ms = duration * 10;
|
||||
|
||||
|
@ -1330,6 +1641,20 @@ ble_error_t PalGap::periodic_advertising_create_sync(
|
|||
uint16_t sync_timeout
|
||||
)
|
||||
{
|
||||
tr_info("Periodic advertising create sync - "
|
||||
"use_periodic_advertiser_list=%s, "
|
||||
"advertising_sid=%d, "
|
||||
"peer_address_type=%s, "
|
||||
"peer_address=%s, "
|
||||
"allowed_skip=%d, "
|
||||
"sync_timeout=%d",
|
||||
to_string(use_periodic_advertiser_list),
|
||||
advertising_sid,
|
||||
to_string(peer_address_type),
|
||||
to_string(peer_address),
|
||||
allowed_skip,
|
||||
sync_timeout);
|
||||
|
||||
DmDevSetExtFilterPolicy(
|
||||
DM_ADV_HANDLE_DEFAULT,
|
||||
DM_FILT_POLICY_MODE_SYNC,
|
||||
|
@ -1345,6 +1670,7 @@ ble_error_t PalGap::periodic_advertising_create_sync(
|
|||
);
|
||||
|
||||
if (sync_id == DM_SYNC_ID_NONE) {
|
||||
tr_error("unknown sync ID %d", sync_id);
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
} else {
|
||||
/* this is not the real handle, this is CORDIO internal handle but the user doesn't need to know that */
|
||||
|
@ -1375,6 +1701,16 @@ ble_error_t PalGap::add_device_to_periodic_advertiser_list(
|
|||
uint8_t advertising_sid
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Add device to periodic advertiser list - "
|
||||
"advertiser_address_type=%s, "
|
||||
"advertiser_address=%s, "
|
||||
"advertiser_sid=%d",
|
||||
to_string(advertiser_address_type),
|
||||
to_string(advertiser_address),
|
||||
advertising_sid);
|
||||
#endif
|
||||
|
||||
DmAddDeviceToPerAdvList(
|
||||
advertiser_address_type.value(),
|
||||
const_cast<uint8_t *>(advertiser_address.data()),
|
||||
|
@ -1390,6 +1726,16 @@ ble_error_t PalGap::remove_device_from_periodic_advertiser_list(
|
|||
uint8_t advertising_sid
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Remove device from periodic advertiser list - "
|
||||
"advertiser_address_type=%s, "
|
||||
"advertiser_address=%s, "
|
||||
"advertiser_sid=%d",
|
||||
to_string(advertiser_address_type),
|
||||
to_string(advertiser_address),
|
||||
advertising_sid);
|
||||
#endif
|
||||
|
||||
DmRemoveDeviceFromPerAdvList(
|
||||
advertiser_address_type.value(),
|
||||
const_cast<uint8_t *>(advertiser_address.data()),
|
||||
|
@ -1430,6 +1776,20 @@ ble_error_t PalGap::extended_create_connection(
|
|||
const uint16_t *maximum_connection_event_lengths
|
||||
)
|
||||
{
|
||||
#if MBED_CONF_CORDIO_TRACE_PAL_ECHOES
|
||||
tr_info("Extended create connection - "
|
||||
"initiator_policy=%s, "
|
||||
"own_address_type=%s, "
|
||||
"peer_address_type=%s, "
|
||||
"peer_address=%s, "
|
||||
"initiating_phys=%s",
|
||||
to_string(initiator_policy),
|
||||
to_string(own_address_type),
|
||||
to_string(peer_address_type),
|
||||
to_string(peer_address),
|
||||
to_string(initiating_phys));
|
||||
#endif
|
||||
|
||||
DmExtConnSetScanInterval(
|
||||
initiating_phys.value(),
|
||||
const_cast<uint16_t *>(scan_intervals),
|
||||
|
@ -1476,10 +1836,20 @@ ble_error_t PalGap::update_direct_advertising_parameters(
|
|||
advertising_peer_address_type_t peer_address_type
|
||||
)
|
||||
{
|
||||
tr_info("Advertising set %d: update direct advertising parameters - "
|
||||
"advertising_type=%d, "
|
||||
"peer_address=%s, "
|
||||
"peer_address_type=%s",
|
||||
advertising_handle,
|
||||
advertising_type,
|
||||
to_string(peer_address),
|
||||
to_string(peer_address_type));
|
||||
|
||||
// The case where a direct advertising is running and parameters are updated
|
||||
// is considered to be a programming error. User should stop advertising first.
|
||||
direct_adv_cb_t *running = get_running_direct_adv_cb(advertising_handle);
|
||||
if (running) {
|
||||
tr_error("trying to update parameters but direct advertising is running");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -1506,6 +1876,7 @@ ble_error_t PalGap::update_direct_advertising_parameters(
|
|||
advertising_type == DM_ADV_CONN_DIRECT_LO_DUTY) {
|
||||
direct_adv_cb_t *adv_cb = get_free_direct_adv_cb();
|
||||
if (!adv_cb) {
|
||||
tr_error("failed to acquire a cb");
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
}
|
||||
adv_cb->state = direct_adv_cb_t::pending;
|
||||
|
|
|
@ -19,24 +19,32 @@
|
|||
|
||||
#include "PalPrivateAddressControllerImpl.h"
|
||||
#include "dm_api.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLPR"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
ble_error_t PalPrivateAddressController::initialize()
|
||||
{
|
||||
tr_info("Initialize privacy PAL");
|
||||
DmPrivInit();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::terminate()
|
||||
{
|
||||
tr_info("Terminate privacy PAL");
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::generate_resolvable_private_address(const irk_t& local_irk)
|
||||
{
|
||||
tr_info("PAL start generation of RPA from local irk: %s", to_string(local_irk));
|
||||
if (_generating_rpa) {
|
||||
tr_error("PAL can't generate RPA, it is busy handling a previous request");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -50,6 +58,7 @@ address_t PalPrivateAddressController::generate_non_resolvable_private_address()
|
|||
address_t address;
|
||||
SecRand(address.data(), address.size());
|
||||
DM_RAND_ADDR_SET(address, DM_RAND_ADDR_NONRESOLV);
|
||||
tr_info("Non resolvable private address generated: %s", to_string(address));
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -59,9 +68,11 @@ ble_error_t PalPrivateAddressController::resolve_private_address(
|
|||
)
|
||||
{
|
||||
if (_resolving_rpa) {
|
||||
tr_error("Failed to start resolution of RPA: Handling a previous request");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
tr_debug("Start resolution of private address: address=%s, irk=%s", to_string(address), to_string(irk));
|
||||
DmPrivResolveAddr(
|
||||
const_cast<uint8_t*>(address.data()),
|
||||
const_cast<uint8_t*>(irk.data()),
|
||||
|
@ -77,6 +88,7 @@ bool PalPrivateAddressController::is_ll_privacy_supported()
|
|||
|
||||
ble_error_t PalPrivateAddressController::set_ll_address_resolution(bool enable)
|
||||
{
|
||||
tr_info("Enable LL private address resolution");
|
||||
DmPrivSetAddrResEnable(enable);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -86,9 +98,11 @@ ble_error_t PalPrivateAddressController::set_ll_resolvable_private_address_timeo
|
|||
)
|
||||
{
|
||||
if (HciLlPrivacySupported() == false) {
|
||||
tr_error("Operation not supported by LL: RPA generation");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
tr_info("Set LL resolvable private address generation timeout: %d s", timeout.value());
|
||||
DmPrivSetResolvablePrivateAddrTimeout(timeout.value());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -106,8 +120,12 @@ ble_error_t PalPrivateAddressController::add_device_to_resolving_list(
|
|||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
tr_error("Operation not supported by LL: RPA resolution");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
tr_info("Add RPA to LL resolving list: peer address=%s, type=%s, peer irk=%s, local irk=%s",
|
||||
to_string(peer_identity_address), to_string(peer_address_type), to_string(peer_irk), to_string(local_irk));
|
||||
DmPrivAddDevToResList(
|
||||
peer_address_type.value(),
|
||||
peer_identity_address.data(),
|
||||
|
@ -130,9 +148,12 @@ ble_error_t PalPrivateAddressController::remove_device_from_resolving_list(
|
|||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
tr_error("Operation not supported by LL: RPA resolution");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
tr_info("Remove RPA from LL resolving list: peer address=%s, type=%s",
|
||||
to_string(peer_identity_address), to_string(peer_address_type));
|
||||
DmPrivRemDevFromResList(peer_address_type.value(), peer_identity_address.data(), 0);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -144,8 +165,11 @@ ble_error_t PalPrivateAddressController::set_peer_privacy_mode(
|
|||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
tr_error("Operation not supported by LL: privacy");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
tr_info("Set privacy mode: peer address=%s, type=%s, mode=%s",
|
||||
to_string(peer_address), to_string(peer_address_type), to_string(privacy_mode));
|
||||
DmPrivSetPrivacyMode(
|
||||
peer_address_type.value(),
|
||||
peer_address.data(),
|
||||
|
@ -157,9 +181,11 @@ ble_error_t PalPrivateAddressController::set_peer_privacy_mode(
|
|||
ble_error_t PalPrivateAddressController::clear_resolving_list()
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
tr_error("Operation not supported by LL: privacy resolving list");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
tr_info("Clear LL resolving list");
|
||||
DmPrivClearResList();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -177,17 +203,17 @@ PalPrivateAddressController& PalPrivateAddressController::instance()
|
|||
|
||||
bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg)
|
||||
{
|
||||
if (msg == nullptr) {
|
||||
return false;
|
||||
}
|
||||
MBED_ASSERT(msg);
|
||||
|
||||
auto* handler = instance()._event_handler;
|
||||
|
||||
switch (msg->event) {
|
||||
case DM_PRIV_GENERATE_ADDR_IND: {
|
||||
tr_info("Privacy handling: DM_PRIV_GENERATE_ADDR_IND");
|
||||
instance()._generating_rpa = false;
|
||||
|
||||
if (!handler) {
|
||||
tr_warning("No user handler registered for PAL privacy");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -217,7 +243,15 @@ bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg)
|
|||
case DM_PRIV_REM_DEV_FROM_RES_LIST_IND: // Device removed from resolving list
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND: // Resolving list cleared
|
||||
{
|
||||
tr_info("Privacy handling: %s",
|
||||
msg->event == DM_PRIV_ADD_DEV_TO_RES_LIST_IND ?
|
||||
"DM_PRIV_ADD_DEV_TO_RES_LIST_IND" :
|
||||
msg->event == DM_PRIV_ADD_DEV_TO_RES_LIST_IND ?
|
||||
"DM_PRIV_REM_DEV_FROM_RES_LIST_IND" :
|
||||
"DM_PRIV_CLEAR_RES_LIST_IND"
|
||||
);
|
||||
if (!handler) {
|
||||
tr_warning("No user handler registered for PAL privacy");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
#include "wsf_os.h"
|
||||
#include "hci_core.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLSM"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
|
@ -51,6 +56,7 @@ PalSecurityManager::~PalSecurityManager()
|
|||
|
||||
ble_error_t PalSecurityManager::initialize()
|
||||
{
|
||||
tr_info("Initialize PAL SM");
|
||||
// reset local state
|
||||
_use_default_passkey = false;
|
||||
_default_passkey = 0;
|
||||
|
@ -73,6 +79,7 @@ ble_error_t PalSecurityManager::initialize()
|
|||
|
||||
ble_error_t PalSecurityManager::terminate()
|
||||
{
|
||||
tr_info("Terminate PAL SM");
|
||||
#if BLE_FEATURE_SIGNING
|
||||
cleanup_peer_csrks();
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
|
@ -82,6 +89,7 @@ ble_error_t PalSecurityManager::terminate()
|
|||
|
||||
ble_error_t PalSecurityManager::reset()
|
||||
{
|
||||
tr_info("Reset PAL SM");
|
||||
#if BLE_FEATURE_SIGNING
|
||||
cleanup_peer_csrks();
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
|
@ -134,6 +142,7 @@ ble_error_t PalSecurityManager::set_authentication_timeout(
|
|||
connection_handle_t connection, uint16_t timeout_in_10ms
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - pass authentication timeout %d to the stack", connection, timeout_in_10ms);
|
||||
DmWriteAuthPayloadTimeout(connection, timeout_in_10ms);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -153,6 +162,7 @@ ble_error_t PalSecurityManager::slave_security_request(
|
|||
AuthenticationMask authentication
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Pass slave security to the stack: authentication = %02x", connection, authentication.value());
|
||||
DmSecSlaveReq(connection, authentication.value());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -171,6 +181,8 @@ ble_error_t PalSecurityManager::enable_encryption(
|
|||
bool mitm
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Enable encryption: lth = %s, rand = %s, ediv = %s, mitm = %s",
|
||||
connection, to_string(ltk), to_string(rand), to_string(ediv), to_string(mitm));
|
||||
dmSecLtk_t sec_ltk;
|
||||
memcpy(sec_ltk.key, ltk.data(), ltk.size());
|
||||
memcpy(sec_ltk.rand, rand.data(), rand.size());
|
||||
|
@ -192,6 +204,8 @@ ble_error_t PalSecurityManager::enable_encryption(
|
|||
bool mitm
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Enable SC encryption: ltk = %s, mitm = %s",
|
||||
connection, to_string(ltk), to_string(mitm));
|
||||
dmSecLtk_t sec_ltk = {0};
|
||||
memcpy(sec_ltk.key, ltk.data(), ltk.size());
|
||||
|
||||
|
@ -213,6 +227,7 @@ ble_error_t PalSecurityManager::encrypt_data(
|
|||
encryption_block_t &data
|
||||
)
|
||||
{
|
||||
tr_warning("PAL Encrypt data not implemented");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -229,6 +244,8 @@ ble_error_t PalSecurityManager::set_ltk(
|
|||
bool secure_connections
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - send ltk response: ltk = %s, mitm = %s, sc = %s ",
|
||||
connection, to_string(ltk), to_string(mitm), to_string(secure_connections));
|
||||
uint8_t security_level = DM_SEC_LEVEL_NONE;
|
||||
if (secure_connections) {
|
||||
security_level = DM_SEC_LEVEL_ENC_LESC;
|
||||
|
@ -252,6 +269,7 @@ ble_error_t PalSecurityManager::set_ltk_not_found(
|
|||
connection_handle_t connection
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Reply LTK not found", connection);
|
||||
DmSecLtkRsp(
|
||||
connection,
|
||||
/* key found */ false,
|
||||
|
@ -265,6 +283,7 @@ ble_error_t PalSecurityManager::set_ltk_not_found(
|
|||
|
||||
ble_error_t PalSecurityManager::set_irk(const irk_t &irk)
|
||||
{
|
||||
tr_info("Set stack local IRK: %s", to_string(irk));
|
||||
_irk = irk;
|
||||
DmSecSetLocalIrk(_irk.data());
|
||||
return BLE_ERROR_NONE;
|
||||
|
@ -275,6 +294,7 @@ ble_error_t PalSecurityManager::set_identity_address(
|
|||
bool public_address
|
||||
)
|
||||
{
|
||||
tr_info("Set stack local identity address: address = %s, public = %s", to_string(address), to_string(public_address));
|
||||
DmSecSetLocalIdentityAddr(
|
||||
address.data(),
|
||||
public_address ? DM_ADDR_PUBLIC : DM_ADDR_RANDOM
|
||||
|
@ -288,6 +308,7 @@ ble_error_t PalSecurityManager::set_csrk(
|
|||
sign_count_t sign_counter
|
||||
)
|
||||
{
|
||||
tr_info("Set stack local CSRK: CSRK = %s, sign counter = %" PRIu32, to_string(csrk), sign_counter);
|
||||
_csrk = csrk;
|
||||
DmSecSetLocalCsrk(_csrk.data());
|
||||
#if BLE_FEATURE_GATT_CLIENT
|
||||
|
@ -307,9 +328,13 @@ ble_error_t PalSecurityManager::set_peer_csrk(
|
|||
)
|
||||
{
|
||||
if (connection == 0 || connection > DM_CONN_MAX) {
|
||||
tr_error("Connection %d - Imposible to set stack peer CSRK, invalid connection ID", connection);
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
tr_info("Connection %d - Set stack peer CSRK: CSRK = %s, authenticated = %s, sign_counter = %" PRIu32,
|
||||
connection, to_string(csrk), to_string(authenticated), sign_counter);
|
||||
|
||||
size_t connection_index = connection - 1;
|
||||
|
||||
if (_peer_csrks[connection_index]) {
|
||||
|
@ -330,9 +355,12 @@ ble_error_t PalSecurityManager::set_peer_csrk(
|
|||
ble_error_t PalSecurityManager::remove_peer_csrk(connection_handle_t connection)
|
||||
{
|
||||
if (connection == 0 || connection > DM_CONN_MAX) {
|
||||
tr_error("Connection %d - Imposible to set stack peer CSRK, invalid connection ID", connection);
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
tr_info("Connection %d - Remove stack peer CSRK", connection);
|
||||
|
||||
size_t connection_index = connection - 1;
|
||||
|
||||
if (_peer_csrks[connection_index]) {
|
||||
|
@ -352,6 +380,9 @@ ble_error_t PalSecurityManager::remove_peer_csrk(connection_handle_t connection)
|
|||
|
||||
ble_error_t PalSecurityManager::set_display_passkey(passkey_num_t passkey)
|
||||
{
|
||||
PasskeyAscii ascii_passkey(passkey);
|
||||
tr_info("Set stack display passkey: %s", passkey_str(ascii_passkey.value()));
|
||||
|
||||
if (passkey) {
|
||||
_use_default_passkey = true;
|
||||
_default_passkey = passkey;
|
||||
|
@ -364,6 +395,7 @@ ble_error_t PalSecurityManager::set_display_passkey(passkey_num_t passkey)
|
|||
|
||||
ble_error_t PalSecurityManager::set_io_capability(io_capability_t io_capability)
|
||||
{
|
||||
tr_info("Set stack I/O capabilities: %s", to_string(io_capability));
|
||||
pSmpCfg->ioCap = io_capability.value();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -374,6 +406,7 @@ ble_error_t PalSecurityManager::set_encryption_key_requirements(
|
|||
uint8_t max_encryption_key_size
|
||||
)
|
||||
{
|
||||
tr_info("Set stack encryption key requirements: [%d : %d]", min_encryption_key_size, max_encryption_key_size);
|
||||
if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) ||
|
||||
(min_encryption_key_size > max_encryption_key_size)) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -398,6 +431,8 @@ ble_error_t PalSecurityManager::send_pairing_request(
|
|||
KeyDistribution responder_dist
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - send pairing request: oob = %s, auth = %02X, initiator dist = %02x, responder dist = %02X",
|
||||
connection, to_string(oob_data_flag), authentication_requirements.value(), initiator_dist.value(), responder_dist.value());
|
||||
DmSecPairReq(
|
||||
connection,
|
||||
oob_data_flag,
|
||||
|
@ -419,6 +454,8 @@ ble_error_t PalSecurityManager::send_pairing_response(
|
|||
KeyDistribution responder_dist
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Send pairing response: oob = %s, auth = %02X, initiator dist = %02x, responder dist = %02X",
|
||||
connection, to_string(oob_data_flag), authentication_requirements.value(), initiator_dist.value(), responder_dist.value());
|
||||
DmSecPairRsp(
|
||||
connection,
|
||||
oob_data_flag,
|
||||
|
@ -436,6 +473,7 @@ ble_error_t PalSecurityManager::cancel_pairing(
|
|||
connection_handle_t connection, pairing_failure_t reason
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - cancel pairing: reason = %s", connection, to_string(reason));
|
||||
DmSecCancelReq(connection, reason.value());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -444,6 +482,7 @@ ble_error_t PalSecurityManager::cancel_pairing(
|
|||
ble_error_t PalSecurityManager::get_random_data(byte_array_t<8> &random_data)
|
||||
{
|
||||
SecRand(random_data.data(), random_data.size());
|
||||
tr_info("Stack generated random data: %s", to_string(random_data));
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -456,6 +495,7 @@ ble_error_t PalSecurityManager::passkey_request_reply(
|
|||
connection_handle_t connection, passkey_num_t passkey
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Reply with passkey %s", connection, passkey_str(PasskeyAscii(passkey).value()));
|
||||
DmSecAuthRsp(
|
||||
connection,
|
||||
/* datalength */ 3,
|
||||
|
@ -471,6 +511,7 @@ ble_error_t PalSecurityManager::legacy_pairing_oob_request_reply(
|
|||
const oob_tk_t &oob_data
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Reply with legacy OOB data %s", connection, to_string(oob_data));
|
||||
DmSecAuthRsp(
|
||||
connection,
|
||||
/* data length */16,
|
||||
|
@ -485,6 +526,7 @@ ble_error_t PalSecurityManager::confirmation_entered(
|
|||
connection_handle_t connection, bool confirmation
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Send confirmation entered: %s", connection, to_string(confirmation));
|
||||
DmSecCompareRsp(connection, confirmation);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -497,6 +539,7 @@ ble_error_t PalSecurityManager::send_keypress_notification(
|
|||
connection_handle_t connection, ble::Keypress_t keypress
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Send keypress notification: %s", connection, to_string(keypress));
|
||||
DmSecKeypressReq(connection, keypress);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -504,6 +547,7 @@ ble_error_t PalSecurityManager::send_keypress_notification(
|
|||
|
||||
ble_error_t PalSecurityManager::generate_secure_connections_oob()
|
||||
{
|
||||
tr_info("Start generation of SC OOB");
|
||||
uint8_t oobLocalRandom[SMP_RAND_LEN];
|
||||
SecRand(oobLocalRandom, SMP_RAND_LEN);
|
||||
DmSecCalcOobReq(oobLocalRandom, _public_key_x);
|
||||
|
@ -518,6 +562,8 @@ ble_error_t PalSecurityManager::secure_connections_oob_request_reply(
|
|||
const oob_confirm_t &peer_confirm
|
||||
)
|
||||
{
|
||||
tr_info("Connection %d - Reply to SC OOB request: local_random = %s, peer_random = %s, peer_confirm = %s",
|
||||
connection, to_string(local_random), to_string(peer_random), to_string(peer_confirm));
|
||||
dmSecLescOobCfg_t oob_config = {0};
|
||||
|
||||
memcpy(oob_config.localRandom, local_random.data(), local_random.size());
|
||||
|
@ -546,12 +592,15 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
PalSecurityManager &self = get_security_manager();
|
||||
PalSecurityManagerEventHandler *handler = self.get_event_handler();
|
||||
|
||||
if ((msg == nullptr) || (handler == nullptr)) {
|
||||
if (handler == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MBED_ASSERT(msg);
|
||||
|
||||
switch (msg->event) {
|
||||
case DM_SEC_PAIR_CMPL_IND: {
|
||||
tr_info("Handling event DM_SEC_PAIR_CMPL_IND");
|
||||
auto *evt = (dmSecPairCmplIndEvt_t *) msg;
|
||||
// Note: authentication and bonding flags present in the auth field
|
||||
handler->on_pairing_completed(evt->hdr.param);
|
||||
|
@ -559,6 +608,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_PAIR_FAIL_IND: {
|
||||
tr_info("Handling event DM_SEC_PAIR_FAIL_IND");
|
||||
connection_handle_t connection = msg->param;
|
||||
uint8_t status = msg->status;
|
||||
|
||||
|
@ -587,6 +637,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_ENCRYPT_IND: {
|
||||
tr_info("Handling event DM_SEC_ENCRYPT_IND");
|
||||
auto *evt = (dmSecEncryptIndEvt_t *) msg;
|
||||
// note: the field usingLtk of the message indicates if an LTK was
|
||||
// used to encrypt the link
|
||||
|
@ -596,12 +647,14 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_ENCRYPT_FAIL_IND: {
|
||||
tr_info("Handling event DM_SEC_ENCRYPT_FAIL_IND");
|
||||
// note: msg->status contains the encryption failure status
|
||||
handler->on_link_encryption_result(msg->param, link_encryption_t::NOT_ENCRYPTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
case DM_SEC_AUTH_REQ_IND: {
|
||||
tr_info("Handling event DM_SEC_AUTH_REQ_IND");
|
||||
auto *evt = (dmSecAuthReqIndEvt_t *) msg;
|
||||
connection_handle_t connection = evt->hdr.param;
|
||||
|
||||
|
@ -618,6 +671,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
connection,
|
||||
get_security_manager()._default_passkey
|
||||
);
|
||||
tr_info("Use default passkey");
|
||||
DmSecAuthRsp(
|
||||
connection,
|
||||
/* data length */ SMP_PIN_LEN,
|
||||
|
@ -625,6 +679,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
);
|
||||
} else {
|
||||
/* generate random passkey, limit to 6 digit max */
|
||||
tr_info("Generate random passkey");
|
||||
passkey_num_t passkey;
|
||||
SecRand((uint8_t *) &passkey, sizeof(passkey));
|
||||
passkey %= 1000000;
|
||||
|
@ -640,6 +695,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_KEY_IND: {
|
||||
tr_info("Handling event DM_SEC_KEY_IND");
|
||||
// NOTE: also report security level and encryption key len
|
||||
auto *evt = (dmSecKeyIndEvt_t *) msg;
|
||||
connection_handle_t connection = evt->hdr.param;
|
||||
|
@ -697,6 +753,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_LTK_REQ_IND: {
|
||||
tr_info("Handling event DM_SEC_LTK_REQ_IND");
|
||||
uint8_t null_rand[HCI_RAND_LEN] = {0};
|
||||
auto *evt = (hciLeLtkReqEvt_t *) msg;
|
||||
|
||||
|
@ -717,6 +774,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
case DM_SEC_PAIR_IND: {
|
||||
tr_info("Handling event DM_SEC_PAIR_IND");
|
||||
auto *evt = (dmSecPairIndEvt_t *) msg;
|
||||
handler->on_pairing_request(
|
||||
/* connection */ evt->hdr.param,
|
||||
|
@ -731,6 +789,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
|
||||
#if BLE_ROLE_CENTRAL
|
||||
case DM_SEC_SLAVE_REQ_IND: {
|
||||
tr_info("Handling event DM_SEC_SLAVE_REQ_IND");
|
||||
auto *evt = (dmSecPairIndEvt_t *) msg;
|
||||
handler->on_slave_security_request(
|
||||
/* connection */ evt->hdr.param,
|
||||
|
@ -742,6 +801,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
|
||||
#if BLE_FEATURE_SECURE_CONNECTIONS
|
||||
case DM_SEC_CALC_OOB_IND: {
|
||||
tr_info("Handling event DM_SEC_CALC_OOB_IND");
|
||||
auto *evt = (dmSecOobCalcIndEvt_t *) msg;
|
||||
handler->on_secure_connections_oob_generated(
|
||||
evt->random,
|
||||
|
@ -751,7 +811,12 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_ECC_KEY_IND: {
|
||||
tr_info("Handling event DM_SEC_ECC_KEY_IND");
|
||||
auto *evt = (secEccMsg_t *) msg;
|
||||
tr_info("ECC Keys generated: public key x=%s, public key y=%s, private key=%s",
|
||||
tr_array(evt->data.key.pubKey_x, SEC_ECC_KEY_LEN),
|
||||
tr_array(evt->data.key.pubKey_y, SEC_ECC_KEY_LEN),
|
||||
tr_array(evt->data.key.privKey, SEC_ECC_KEY_LEN));
|
||||
DmSecSetEccKey(&evt->data.key);
|
||||
memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(self._public_key_x));
|
||||
self._lesc_keys_generated = true;
|
||||
|
@ -759,6 +824,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_COMPARE_IND: {
|
||||
tr_info("Handling event DM_SEC_COMPARE_IND");
|
||||
auto *evt = (dmSecCnfIndEvt_t *) msg;
|
||||
handler->on_passkey_display(
|
||||
/* connection */ evt->hdr.param,
|
||||
|
@ -769,6 +835,7 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
|
||||
case DM_SEC_KEYPRESS_IND: {
|
||||
tr_info("Handling event DM_SEC_KEYPRESS_IND");
|
||||
auto *evt = (dmSecKeypressIndEvt_t *) msg;
|
||||
handler->on_keypress_notification(
|
||||
/* connection */ evt->hdr.param,
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "mbed_wsf_trace.h"
|
||||
#include "platform/mbed_critical.h"
|
||||
|
||||
#define TRACE_GROUP "BLCO"
|
||||
|
||||
static bool_t wsf_mbed_trace_printf_cb(const uint8_t *pBuf, uint32_t len)
|
||||
{
|
||||
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
|
||||
if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
/* we need to strip the newline at the end*/
|
||||
if (len > 1) {
|
||||
tr_debug("%.*s", (int) (len - 1), pBuf);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wsf_mbed_trace_init()
|
||||
{
|
||||
tr_info("WSF Cordio tracing enabled");
|
||||
WsfTraceEnable(true);
|
||||
WsfTraceRegisterHandler(&wsf_mbed_trace_printf_cb);
|
||||
}
|
||||
|
||||
#if MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
#define TRACE_GROUP "BLHC"
|
||||
void wsf_mbed_trace_hci(const uint8_t *pBuf, uint32_t len, const uint8_t *prefix)
|
||||
{
|
||||
tr_debug("LL->HOST %s %s", prefix, trace_array(pBuf, len));
|
||||
}
|
||||
#endif // MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
|
||||
#endif // MBED_CONF_MBED_TRACE_ENABLE
|
|
@ -0,0 +1,37 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_WSF_TRACE_H_
|
||||
#define MBED_WSF_TRACE_H_
|
||||
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
void wsf_mbed_trace_init();
|
||||
|
||||
#if MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
void wsf_mbed_trace_hci(const uint8_t *pBuf, uint32_t len, const uint8_t *prefix);
|
||||
|
||||
#define HCI_PDUMP_CMD(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "CMD")
|
||||
#define HCI_PDUMP_EVT(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "EVT")
|
||||
#define HCI_PDUMP_TX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_TX")
|
||||
#define HCI_PDUMP_RX_ACL(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ACL_RX")
|
||||
#define HCI_PDUMP_TX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_TX")
|
||||
#define HCI_PDUMP_RX_ISO(len, pBuf) wsf_mbed_trace_hci(len, pBuf, "ISO_RX")
|
||||
#endif // MBED_CONF_CORDIO_TRACE_HCI_PACKETS
|
||||
|
||||
#endif // MBED_CONF_MBED_TRACE_ENABLE
|
||||
|
||||
#endif // MBED_WSF_TRACE_H_
|
|
@ -12,6 +12,8 @@ target_sources(mbed-ble
|
|||
GapImpl.cpp
|
||||
GattClientImpl.cpp
|
||||
KVStoreSecurityDb.cpp
|
||||
MemorySecurityDb.cpp
|
||||
PrivateAddressController.cpp
|
||||
SecurityDb.cpp
|
||||
SecurityManagerImpl.cpp
|
||||
)
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
|
||||
#include "FileSecurityDb.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLDB"
|
||||
|
||||
namespace ble {
|
||||
|
||||
const uint16_t DB_VERSION = 1;
|
||||
|
@ -73,6 +78,7 @@ typedef SecurityDb::entry_handle_t entry_handle_t;
|
|||
FileSecurityDb::FileSecurityDb(FILE *db_file)
|
||||
: SecurityDb(),
|
||||
_db_file(db_file) {
|
||||
tr_info("File Security DB initialised to store %d entries", get_entry_count());
|
||||
/* init the offset in entries so they point to file positions */
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
_entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE;
|
||||
|
@ -84,9 +90,18 @@ FileSecurityDb::~FileSecurityDb()
|
|||
fclose(_db_file);
|
||||
}
|
||||
|
||||
FileSecurityDb::entry_t* FileSecurityDb::as_entry(entry_handle_t db_handle) {
|
||||
entry_t* entry = reinterpret_cast<entry_t*>(db_handle);
|
||||
if (!entry) {
|
||||
tr_error("Invalid security DB handle used");
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
FILE* FileSecurityDb::open_db_file(const char *db_path)
|
||||
{
|
||||
if (!db_path) {
|
||||
tr_error("Invalid security DB path");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -96,9 +111,11 @@ FILE* FileSecurityDb::open_db_file(const char *db_path)
|
|||
if (!db_file) {
|
||||
/* file doesn't exist, create it */
|
||||
db_file = fopen(db_path, "wb+");
|
||||
tr_warning("Security DB didn't exist, creating new one");
|
||||
}
|
||||
|
||||
if (!db_file) {
|
||||
tr_error("Failed to create security DB");
|
||||
/* failed to create a file, abort */
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -115,9 +132,11 @@ FILE* FileSecurityDb::open_db_file(const char *db_path)
|
|||
/* if file size differs from database size init the file */
|
||||
fseek(db_file, 0, SEEK_END);
|
||||
if (ftell(db_file) != DB_SIZE) {
|
||||
tr_warning("Invalid security DB, reinit");
|
||||
init = true;
|
||||
}
|
||||
} else {
|
||||
tr_info("Empty security DB, reinit");
|
||||
init = true;
|
||||
}
|
||||
|
||||
|
@ -130,6 +149,7 @@ FILE* FileSecurityDb::open_db_file(const char *db_path)
|
|||
|
||||
FILE* FileSecurityDb::erase_db_file(FILE* db_file)
|
||||
{
|
||||
tr_info("Erasing security DB");
|
||||
fseek(db_file, 0, SEEK_SET);
|
||||
|
||||
/* zero the file */
|
||||
|
@ -137,6 +157,7 @@ FILE* FileSecurityDb::erase_db_file(FILE* db_file)
|
|||
size_t count = DB_SIZE / 4;
|
||||
while (count--) {
|
||||
if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) {
|
||||
tr_error("Failed to write Security DB to file");
|
||||
fclose(db_file);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -144,6 +165,7 @@ FILE* FileSecurityDb::erase_db_file(FILE* db_file)
|
|||
|
||||
if (fflush(db_file)) {
|
||||
fclose(db_file);
|
||||
tr_error("Failed to write Security DB to file");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -172,6 +194,7 @@ void FileSecurityDb::set_entry_local_ltk(
|
|||
|
||||
entry->flags.ltk_sent = true;
|
||||
|
||||
tr_info("Write DB entry %d: local ltk %s", get_index(db_handle), to_string(ltk));
|
||||
db_write(<k, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK);
|
||||
}
|
||||
|
||||
|
@ -186,6 +209,7 @@ void FileSecurityDb::set_entry_local_ediv_rand(
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Write DB entry %d: local ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV);
|
||||
db_write(&rand, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND);
|
||||
}
|
||||
|
@ -206,6 +230,7 @@ void FileSecurityDb::set_entry_peer_ltk(
|
|||
|
||||
entry->flags.ltk_stored = true;
|
||||
|
||||
tr_info("Write DB entry %d: peer ltk %s", get_index(db_handle), to_string(ltk));
|
||||
db_write(<k, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK);
|
||||
}
|
||||
|
||||
|
@ -220,6 +245,7 @@ void FileSecurityDb::set_entry_peer_ediv_rand(
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Write DB entry %d: peer ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV);
|
||||
db_write(&rand, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND);
|
||||
}
|
||||
|
@ -236,6 +262,7 @@ void FileSecurityDb::set_entry_peer_irk(
|
|||
|
||||
entry->flags.irk_stored = true;
|
||||
|
||||
tr_info("Write DB entry %d: peer irk %s", get_index(db_handle), to_string(irk));
|
||||
db_write(&irk, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK);
|
||||
}
|
||||
|
||||
|
@ -250,6 +277,7 @@ void FileSecurityDb::set_entry_peer_bdaddr(
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Write DB entry %d: %s peer address %s", get_index(db_handle), address_is_public? "public" : "private", to_string(peer_address));
|
||||
db_write(&peer_address, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS);
|
||||
db_write(&address_is_public, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC);
|
||||
}
|
||||
|
@ -266,6 +294,7 @@ void FileSecurityDb::set_entry_peer_csrk(
|
|||
|
||||
entry->flags.csrk_stored = true;
|
||||
|
||||
tr_info("Write DB entry %d: peer csrk %s", get_index(db_handle), to_string(csrk));
|
||||
db_write(&csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING);
|
||||
}
|
||||
|
||||
|
@ -285,6 +314,8 @@ void FileSecurityDb::set_local_csrk(
|
|||
)
|
||||
{
|
||||
this->SecurityDb::set_local_csrk(csrk);
|
||||
|
||||
tr_info("Write DB: local csrk %s", to_string(csrk));
|
||||
db_write(&_local_csrk, DB_OFFSET_LOCAL_CSRK);
|
||||
}
|
||||
|
||||
|
@ -295,6 +326,8 @@ void FileSecurityDb::set_local_identity(
|
|||
)
|
||||
{
|
||||
this->SecurityDb::set_local_identity(irk, identity_address, public_address);
|
||||
|
||||
tr_info("Write DB: %s peer address %s", public_address? "public" : "private", to_string(identity_address));
|
||||
db_write(&_local_identity, DB_OFFSET_LOCAL_IDENTITY);
|
||||
}
|
||||
|
||||
|
@ -313,6 +346,7 @@ void FileSecurityDb::restore()
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Valid DB file - restoring security DB from file");
|
||||
db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY);
|
||||
db_read(&_local_csrk, DB_OFFSET_LOCAL_CSRK);
|
||||
db_read(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT);
|
||||
|
@ -332,6 +366,7 @@ void FileSecurityDb::sync(entry_handle_t db_handle)
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Synchronising security DB entry %d with file", get_index(db_handle));
|
||||
db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT);
|
||||
db_write(&entry->flags, entry->file_offset + DB_STORE_OFFSET_FLAGS);
|
||||
db_write(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT);
|
||||
|
@ -339,6 +374,7 @@ void FileSecurityDb::sync(entry_handle_t db_handle)
|
|||
|
||||
void FileSecurityDb::set_restore(bool reload)
|
||||
{
|
||||
tr_info("Security DB set to restore on reset: %s", to_string(reload));
|
||||
db_write(&reload, DB_OFFSET_RESTORE);
|
||||
}
|
||||
|
||||
|
@ -365,6 +401,8 @@ void FileSecurityDb::reset_entry(entry_handle_t db_entry)
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Reseting security DB entry %d", get_index(db_entry));
|
||||
|
||||
fseek(_db_file, entry->file_offset, SEEK_SET);
|
||||
const uint32_t zero = 0;
|
||||
size_t count = DB_SIZE_STORE / 4;
|
||||
|
|
|
@ -37,9 +37,7 @@ private:
|
|||
size_t file_offset;
|
||||
};
|
||||
|
||||
static entry_t* as_entry(entry_handle_t db_handle) {
|
||||
return reinterpret_cast<entry_t*>(db_handle);
|
||||
}
|
||||
static entry_t* as_entry(entry_handle_t db_handle);
|
||||
|
||||
template<class T>
|
||||
void db_read(T *value, long int offset) {
|
||||
|
@ -161,6 +159,11 @@ private:
|
|||
*/
|
||||
static FILE* erase_db_file(FILE* db_file);
|
||||
|
||||
uint8_t get_index(const entry_handle_t db_handle) const
|
||||
{
|
||||
return reinterpret_cast<entry_t*>(db_handle) - _entries;
|
||||
}
|
||||
|
||||
private:
|
||||
entry_t _entries[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
||||
FILE *_db_file;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -907,6 +907,8 @@ private:
|
|||
|
||||
ScanState _scan_state = ScanState::idle;
|
||||
|
||||
void set_scan_state(ScanState state);
|
||||
|
||||
scan_duration_t _scan_requested_duration = scan_duration_t::forever();
|
||||
duplicates_filter_t _scan_requested_filtering = duplicates_filter_t::DISABLE;
|
||||
scan_period_t _scan_requested_period = scan_period_t(0);
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include "source/pal/AttServerMessage.h"
|
||||
#include "source/BLEInstanceBase.h"
|
||||
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLGC"
|
||||
|
||||
using ble::AttServerMessage;
|
||||
using ble::AttReadResponse;
|
||||
using ble::AttReadBlobResponse;
|
||||
|
@ -113,7 +117,7 @@ struct GattClient::ProcedureControlBlock {
|
|||
/*
|
||||
* Procedure control block for the discovery process.
|
||||
*/
|
||||
|
||||
#define TRACE_CLASS "DiscoveryControlBlock"
|
||||
struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
||||
using ProcedureControlBlock::connection_handle;
|
||||
|
||||
|
@ -144,11 +148,13 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void handle_timeout_error(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s timed out", TRACE_CLASS);
|
||||
terminate(client);
|
||||
}
|
||||
|
||||
void abort(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s aborted", TRACE_CLASS);
|
||||
terminate(client);
|
||||
}
|
||||
|
||||
|
@ -179,6 +185,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
case AttributeOpcode::ERROR_RESPONSE: {
|
||||
const auto &error = static_cast<const AttErrorResponse &>(message);
|
||||
if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
|
||||
tr_warning("%s terminating early due to %s", TRACE_CLASS, attribute_error_code_to_string(error.error_code));
|
||||
terminate(client);
|
||||
return;
|
||||
}
|
||||
|
@ -206,6 +213,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
void handle_service_discovered(GattClient *client, const Response &response)
|
||||
{
|
||||
if (!response.size()) {
|
||||
tr_error("%s terminating due to malformed message", TRACE_CLASS);
|
||||
terminate(client);
|
||||
return;
|
||||
}
|
||||
|
@ -216,6 +224,8 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
end_handle = get_end_handle(response[i]);
|
||||
UUID uuid = get_uuid(response[i]);
|
||||
|
||||
tr_debug("Discovered service UUID: %s [0x%x:0x%x])", to_string(uuid), start_handle, end_handle);
|
||||
|
||||
if (!characteristic_callback) {
|
||||
DiscoveredService discovered_service;
|
||||
discovered_service.setup(uuid, start_handle, end_handle);
|
||||
|
@ -250,11 +260,13 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
void start_characteristic_discovery(GattClient *client)
|
||||
{
|
||||
if (!services_discovered) {
|
||||
tr_error("%s terminating due to services list structure null", TRACE_CLASS);
|
||||
terminate(client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!characteristic_callback) {
|
||||
tr_error("%s terminating due missing characteristic callback", TRACE_CLASS);
|
||||
terminate(client);
|
||||
return;
|
||||
}
|
||||
|
@ -293,6 +305,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
last_characteristic = characteristic_t(
|
||||
client, connection_handle, response[i].handle, response[i].value
|
||||
);
|
||||
tr_debug("Discovered char handle: 0x%x value: %s", response[i].handle, tr_array(response[i].value.data(), response[i].value.size()));
|
||||
}
|
||||
|
||||
// check if all the characteristics of the service has been discovered
|
||||
|
@ -308,6 +321,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
);
|
||||
|
||||
if (err) {
|
||||
tr_error("%s terminating early due to %s", TRACE_CLASS, ble_error_to_string(err));
|
||||
terminate(client);
|
||||
}
|
||||
}
|
||||
|
@ -328,6 +342,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
delete old;
|
||||
|
||||
if (!services_discovered) {
|
||||
tr_debug("Service discovery complete");
|
||||
terminate(client);
|
||||
} else {
|
||||
start_characteristic_discovery(client);
|
||||
|
@ -473,7 +488,7 @@ struct GattClient::DiscoveryControlBlock final : public ProcedureControlBlock {
|
|||
bool done;
|
||||
};
|
||||
|
||||
|
||||
#define TRACE_CLASS "ReadControlBlock"
|
||||
struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
||||
using ProcedureControlBlock::connection_handle;
|
||||
|
||||
|
@ -494,6 +509,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void handle_timeout_error(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s timed out", TRACE_CLASS);
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -507,6 +523,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void abort(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s aborted", TRACE_CLASS);
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -543,6 +560,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
default: {
|
||||
// should not happen, terminate the procedure and notify client with an error
|
||||
// in such case
|
||||
tr_error("%s terminated unexpectedly due to unhandled opcode 0x%x", TRACE_CLASS, (int)message.opcode);
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -583,11 +601,13 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
response.len = (current_offset + read_response.size()) - offset;
|
||||
response.data = data;
|
||||
}
|
||||
tr_info("Read response complete - received %d bytes", read_response.size());
|
||||
terminate(client, response);
|
||||
} else {
|
||||
// allocation which will contain the response data plus the next one.
|
||||
data = (uint8_t *) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2));
|
||||
if (data == nullptr) {
|
||||
tr_error("%s terminated due to OoM error", TRACE_CLASS);
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -601,6 +621,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
}
|
||||
|
||||
memcpy(data + (current_offset - offset), read_response.data(), read_response.size());
|
||||
tr_info("Read response partial - received %d bytes", read_response.size());
|
||||
current_offset = current_offset + read_response.size();
|
||||
ble_error_t err = client->_pal_client.read_attribute_blob(
|
||||
connection_handle,
|
||||
|
@ -609,6 +630,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
);
|
||||
|
||||
if (err) {
|
||||
tr_error("%s terminated because reading attribute failed", TRACE_CLASS);
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -656,6 +678,8 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
break;
|
||||
}
|
||||
|
||||
tr_error("%s error: %s", TRACE_CLASS, attribute_error_code_to_string(error.error_code));
|
||||
|
||||
GattReadCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -677,7 +701,7 @@ struct GattClient::ReadControlBlock final : public ProcedureControlBlock {
|
|||
/*
|
||||
* Control block for the write process
|
||||
*/
|
||||
|
||||
#define TRACE_CLASS "WriteControlBlock"
|
||||
struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
||||
using ProcedureControlBlock::connection_handle;
|
||||
|
||||
|
@ -699,6 +723,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void handle_timeout_error(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s timed out", TRACE_CLASS);
|
||||
GattWriteCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -711,6 +736,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void abort(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s aborted", TRACE_CLASS);
|
||||
GattWriteCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -748,6 +774,8 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
break;
|
||||
|
||||
default: {
|
||||
tr_error("%s terminated due unhandled opcode 0x%x", TRACE_CLASS, (int)message.opcode);
|
||||
|
||||
GattWriteCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -763,6 +791,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
|
||||
void handle_write_response(GattClient* client, const AttWriteResponse& write_response)
|
||||
{
|
||||
tr_debug("write executed successfully");
|
||||
GattWriteCallbackParams response = {
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
|
@ -778,6 +807,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
{
|
||||
ble_error_t err = BLE_ERROR_UNSPECIFIED;
|
||||
offset += write_response.partial_value.size();
|
||||
tr_info("Prepared write partially complete offset=%d", offset);
|
||||
uint16_t data_left = write_length - offset; /* offset is guaranteed to be less of equal to write_length */
|
||||
if (data_left) {
|
||||
uint16_t chunk_size = client->get_mtu(connection_handle) - PREPARE_WRITE_HEADER_LENGTH;
|
||||
|
@ -798,6 +828,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
}
|
||||
|
||||
if (err) {
|
||||
tr_error("%s failed due to %s - clearing the queue", TRACE_CLASS, ble_error_to_string(err));
|
||||
clear_prepare_queue(client, err, AttErrorResponse::UNLIKELY_ERROR);
|
||||
}
|
||||
}
|
||||
|
@ -805,6 +836,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
void handle_execute_write_response(GattClient* client, const AttExecuteWriteResponse& execute_response)
|
||||
{
|
||||
if (prepare_success) {
|
||||
tr_debug("Prepared write executed successfully");
|
||||
status = BLE_ERROR_NONE;
|
||||
error_code = 0x00;
|
||||
}
|
||||
|
@ -865,6 +897,8 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
break;
|
||||
}
|
||||
|
||||
tr_error("%s error: %s", TRACE_CLASS, attribute_error_code_to_string(error.error_code));
|
||||
|
||||
if (error.request_opcode == AttributeOpcode(AttributeOpcode::PREPARE_WRITE_REQUEST)) {
|
||||
clear_prepare_queue(client, status, error.error_code);
|
||||
} else {
|
||||
|
@ -892,7 +926,7 @@ struct GattClient::WriteControlBlock final : public ProcedureControlBlock {
|
|||
/*
|
||||
* Control block for the descriptor discovery process
|
||||
*/
|
||||
|
||||
#define TRACE_CLASS "DescriptorDiscoveryControlBlock"
|
||||
struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureControlBlock {
|
||||
using ProcedureControlBlock::connection_handle;
|
||||
|
||||
|
@ -913,6 +947,8 @@ struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureContr
|
|||
|
||||
ble_error_t start(GattClient *client)
|
||||
{
|
||||
tr_info("Discover descriptor for char handle=%d",
|
||||
characteristic.getDeclHandle());
|
||||
return client->_pal_client.discover_characteristics_descriptors(
|
||||
connection_handle,
|
||||
attribute_handle_range(
|
||||
|
@ -924,11 +960,13 @@ struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureContr
|
|||
|
||||
void handle_timeout_error(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s timed out", TRACE_CLASS);
|
||||
terminate(client, BLE_ERROR_UNSPECIFIED);
|
||||
}
|
||||
|
||||
void abort(GattClient *client) final
|
||||
{
|
||||
tr_warning("%s aborted", TRACE_CLASS);
|
||||
terminate(client, BLE_ERROR_INVALID_STATE);
|
||||
}
|
||||
|
||||
|
@ -955,6 +993,7 @@ struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureContr
|
|||
|
||||
void handle_error(GattClient *client, const AttErrorResponse &error)
|
||||
{
|
||||
tr_error("%s error: %s", TRACE_CLASS, attribute_error_code_to_string(error.error_code));
|
||||
if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) {
|
||||
terminate(client, BLE_ERROR_NONE);
|
||||
} else {
|
||||
|
@ -965,6 +1004,8 @@ struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureContr
|
|||
void handle_response(GattClient *client, const AttFindInformationResponse &response)
|
||||
{
|
||||
for (size_t i = 0; i < response.size(); ++i) {
|
||||
tr_info("Discovered descriptor handle=%d uuid=%s for char handle=%d",
|
||||
response[i].handle, to_string(response[i].uuid), characteristic.getDeclHandle());
|
||||
DiscoveredCharacteristicDescriptor descriptor(
|
||||
&ble::BLE::Instance().gattClient(), connection_handle, response[i].handle, response[i].uuid
|
||||
);
|
||||
|
@ -993,6 +1034,10 @@ struct GattClient::DescriptorDiscoveryControlBlock final : public ProcedureContr
|
|||
|
||||
void terminate(GattClient *client, ble_error_t status, uint8_t error_code = 0x00)
|
||||
{
|
||||
if (status != BLE_ERROR_NONE) {
|
||||
tr_warning("%s terminated due to %s %s", TRACE_CLASS, ble_error_to_string(status), attribute_error_code_to_string(error_code));
|
||||
}
|
||||
|
||||
client->remove_control_block(this);
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
||||
characteristic,
|
||||
|
@ -1039,8 +1084,10 @@ ble_error_t GattClient::launchServiceDiscovery(
|
|||
const UUID &matching_characteristic_uuid
|
||||
)
|
||||
{
|
||||
tr_info("Launching service discovery (service: %s char: %s)", to_string(matching_service_uuid), to_string(matching_characteristic_uuid));
|
||||
// verify that there is no other procedures going on this connection
|
||||
if (_is_reseting || get_control_block(connection_handle)) {
|
||||
tr_error("cannot launch service discovery");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -1059,6 +1106,7 @@ ble_error_t GattClient::launchServiceDiscovery(
|
|||
);
|
||||
|
||||
if (discovery_pcb == nullptr) {
|
||||
tr_error("Failed to allocate DiscoveryControlBlock");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -1082,6 +1130,7 @@ ble_error_t GattClient::launchServiceDiscovery(
|
|||
}
|
||||
|
||||
if (err) {
|
||||
tr_error("Discovery failed due to %s", ble_error_to_string(err));
|
||||
remove_control_block(discovery_pcb);
|
||||
delete discovery_pcb;
|
||||
}
|
||||
|
@ -1095,6 +1144,7 @@ ble_error_t GattClient::discoverServices(
|
|||
const UUID &matchingServiceUUID
|
||||
)
|
||||
{
|
||||
tr_info("Discover services with uuid=%s", to_string(matchingServiceUUID));
|
||||
/* We take advantage of the property
|
||||
* that providing nullptr for the characteristic callback results in
|
||||
* characteristic discovery being skipped for each matching
|
||||
|
@ -1112,6 +1162,7 @@ ble_error_t GattClient::discoverServices(
|
|||
GattAttribute::Handle_t endHandle
|
||||
)
|
||||
{
|
||||
tr_warning("discoverServices based on handle range not implemented");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -1132,6 +1183,7 @@ bool GattClient::isServiceDiscoveryActive() const
|
|||
|
||||
void GattClient::terminateServiceDiscovery()
|
||||
{
|
||||
tr_info("Terminate service discovery");
|
||||
ProcedureControlBlock *pcb = control_blocks;
|
||||
while (pcb) {
|
||||
if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) {
|
||||
|
@ -1150,6 +1202,7 @@ ble_error_t GattClient::read(
|
|||
{
|
||||
// verify that there is no other procedures going on this connection
|
||||
if (_is_reseting || get_control_block(connection_handle)) {
|
||||
tr_error("cannot launch attribute read");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -1160,6 +1213,7 @@ ble_error_t GattClient::read(
|
|||
);
|
||||
|
||||
if (read_pcb == nullptr) {
|
||||
tr_error("Attribute read failed due to allocation error");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -1167,6 +1221,8 @@ ble_error_t GattClient::read(
|
|||
|
||||
ble_error_t err = BLE_ERROR_NONE;
|
||||
|
||||
tr_debug("Connection %d - read attribute %d offset %d", connection_handle, attribute_handle, offset);
|
||||
|
||||
if (offset == 0) {
|
||||
err = _pal_client.read_attribute_value(
|
||||
connection_handle, attribute_handle
|
||||
|
@ -1178,6 +1234,7 @@ ble_error_t GattClient::read(
|
|||
}
|
||||
|
||||
if (err) {
|
||||
tr_error("Attribute read failed due %s", ble_error_to_string(err));
|
||||
remove_control_block(read_pcb);
|
||||
delete read_pcb;
|
||||
}
|
||||
|
@ -1195,9 +1252,12 @@ ble_error_t GattClient::write(
|
|||
) const
|
||||
{
|
||||
if (_is_reseting || get_control_block(connection_handle)) {
|
||||
tr_error("cannot launch attibute write");
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
tr_debug("Connection %d - write attribute %d value %s", connection_handle, attribute_handle, tr_array(value, length));
|
||||
|
||||
uint16_t mtu = get_mtu(connection_handle);
|
||||
|
||||
#if BLE_FEATURE_SIGNING
|
||||
|
@ -1218,6 +1278,7 @@ ble_error_t GattClient::write(
|
|||
#endif // BLE_FEATURE_SIGNING
|
||||
if (cmd == GATT_OP_WRITE_CMD) {
|
||||
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||
tr_error("Writes need to fit in a single message");
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
return _pal_client.write_without_response(
|
||||
|
@ -1228,6 +1289,7 @@ ble_error_t GattClient::write(
|
|||
#if BLE_FEATURE_SIGNING
|
||||
} else if (cmd == GATT_OP_SIGNED_WRITE_CMD) {
|
||||
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) {
|
||||
tr_error("Signed writes need to fit in single message");
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
ble_error_t status = _pal_client.signed_write_without_response(
|
||||
|
@ -1247,6 +1309,7 @@ ble_error_t GattClient::write(
|
|||
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||
data = (uint8_t *) malloc(length);
|
||||
if (data == nullptr) {
|
||||
tr_err("Write failed due to allocation error");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
memcpy(data, value, length);
|
||||
|
@ -1261,6 +1324,7 @@ ble_error_t GattClient::write(
|
|||
|
||||
if (write_pcb == nullptr) {
|
||||
free(data);
|
||||
tr_err("Write failed due to allocation error");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -1283,6 +1347,7 @@ ble_error_t GattClient::write(
|
|||
}
|
||||
|
||||
if (err) {
|
||||
tr_error("Write request failed due to %s", ble_error_to_string(err));
|
||||
remove_control_block(write_pcb);
|
||||
delete write_pcb;
|
||||
}
|
||||
|
@ -1298,6 +1363,7 @@ void GattClient::onServiceDiscoveryTermination(
|
|||
ServiceDiscovery::TerminationCallback_t callback
|
||||
)
|
||||
{
|
||||
tr_info("Service discovery ended");
|
||||
_termination_callback = callback;
|
||||
}
|
||||
|
||||
|
@ -1308,6 +1374,8 @@ ble_error_t GattClient::discoverCharacteristicDescriptors(
|
|||
const CharacteristicDescriptorDiscovery::TerminationCallback_t &terminationCallback
|
||||
)
|
||||
{
|
||||
tr_info("Discover char descriptors %d", characteristic.getDeclHandle());
|
||||
|
||||
// verify that there is no other procedures going on this connection
|
||||
if (_is_reseting || get_control_block(characteristic.getConnectionHandle())) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
|
@ -1370,6 +1438,7 @@ void GattClient::terminateCharacteristicDescriptorDiscovery(
|
|||
const DiscoveredCharacteristic &characteristic
|
||||
)
|
||||
{
|
||||
tr_info("terminate char descriptor discovery %d", characteristic.getDeclHandle());
|
||||
ProcedureControlBlock *pcb = control_blocks;
|
||||
|
||||
while (pcb) {
|
||||
|
@ -1397,6 +1466,7 @@ ble_error_t GattClient::negotiateAttMtu(
|
|||
|
||||
ble_error_t GattClient::reset()
|
||||
{
|
||||
tr_info("GattClient reset");
|
||||
/* Notify that the instance is about to shut down. */
|
||||
shutdownCallChain.call(&ble::BLE::Instance().gattClient());
|
||||
shutdownCallChain.clear();
|
||||
|
@ -1434,6 +1504,7 @@ void GattClient::on_att_mtu_change(
|
|||
uint16_t att_mtu_size
|
||||
)
|
||||
{
|
||||
tr_info("MTU changed to %d", att_mtu_size);
|
||||
if (eventHandler) {
|
||||
eventHandler->onAttMtuChange(connection_handle, att_mtu_size);
|
||||
}
|
||||
|
@ -1471,6 +1542,7 @@ void GattClient::on_server_message_received(
|
|||
const AttServerMessage &message
|
||||
)
|
||||
{
|
||||
tr_debug("Received server message %s", attribute_opcode_to_string(message.opcode));
|
||||
switch (message.opcode) {
|
||||
case AttributeOpcode::ERROR_RESPONSE:
|
||||
case AttributeOpcode::EXCHANGE_MTU_RESPONSE:
|
||||
|
@ -1493,6 +1565,7 @@ void GattClient::on_server_message_received(
|
|||
} break;
|
||||
|
||||
default:
|
||||
tr_warning("Unhandled message in gatt client received from server");
|
||||
// invalid message receive
|
||||
return;
|
||||
}
|
||||
|
@ -1527,6 +1600,7 @@ void GattClient::on_server_event(connection_handle_t connection, const AttServer
|
|||
callbacks_params.type = BLE_HVX_NOTIFICATION;
|
||||
callbacks_params.len = notification.attribute_value.size();
|
||||
callbacks_params.data = notification.attribute_value.data();
|
||||
tr_debug("Notification for char: %d value: %s", notification.attribute_handle, tr_array(notification.attribute_value.data(), notification.attribute_value.size()));
|
||||
} break;
|
||||
|
||||
case AttributeOpcode::HANDLE_VALUE_INDICATION: {
|
||||
|
@ -1536,9 +1610,11 @@ void GattClient::on_server_event(connection_handle_t connection, const AttServer
|
|||
callbacks_params.type = BLE_HVX_INDICATION;
|
||||
callbacks_params.len = indication.attribute_value.size();
|
||||
callbacks_params.data = indication.attribute_value.data();
|
||||
tr_debug("Indication for char: %d value: %s", indication.attribute_handle, tr_array(indication.attribute_value.data(), indication.attribute_value.size()));
|
||||
} break;
|
||||
|
||||
default:
|
||||
tr_warning("Unhandled event in gatt client received from server");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1633,6 +1709,9 @@ uint16_t GattClient::get_mtu(connection_handle_t connection) const
|
|||
*/
|
||||
void GattClient::setEventHandler(EventHandler *handler)
|
||||
{
|
||||
if (!handler) {
|
||||
tr_warning("Setting a null gatt event handler");
|
||||
}
|
||||
eventHandler = handler;
|
||||
}
|
||||
|
||||
|
@ -1705,6 +1784,11 @@ GattClient::HVXCallbackChain_t &GattClient::onHVX()
|
|||
*/
|
||||
void GattClient::processReadResponse(const GattReadCallbackParams *params)
|
||||
{
|
||||
if (params->status == BLE_ERROR_NONE) {
|
||||
tr_debug("Att read complete handle 0x%x (offset %d), value %s", params->handle, params->offset, tr_array(params->data, params->len));
|
||||
} else {
|
||||
tr_info("Connection %d - Att read failed with error %s", params->connHandle, ble_error_to_string(params->status));
|
||||
}
|
||||
onDataReadCallbackChain(params);
|
||||
}
|
||||
|
||||
|
@ -1713,6 +1797,11 @@ void GattClient::processReadResponse(const GattReadCallbackParams *params)
|
|||
*/
|
||||
void GattClient::processWriteResponse(const GattWriteCallbackParams *params)
|
||||
{
|
||||
if (params->status == BLE_ERROR_NONE) {
|
||||
tr_debug("Att write complete handle 0x%x", params->handle);
|
||||
} else {
|
||||
tr_info("Connection %d - Att write failed with error %s", params->connHandle, ble_error_to_string(params->status));
|
||||
}
|
||||
onDataWriteCallbackChain(params);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#if BLE_SECURITY_DATABASE_KVSTORE
|
||||
|
||||
#include "KVStoreSecurityDb.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLDB"
|
||||
|
||||
namespace ble {
|
||||
|
||||
|
@ -51,6 +54,7 @@ typedef SecurityDb::entry_handle_t entry_handle_t;
|
|||
|
||||
KVStoreSecurityDb::KVStoreSecurityDb()
|
||||
: SecurityDb() {
|
||||
tr_info("KFStore Security DB initialised to store " STR(BLE_SECURITY_DATABASE_MAX_ENTRIES) " entries");
|
||||
memset(_entries, 0, sizeof(_entries));
|
||||
}
|
||||
|
||||
|
@ -58,6 +62,14 @@ KVStoreSecurityDb::~KVStoreSecurityDb()
|
|||
{
|
||||
}
|
||||
|
||||
KVStoreSecurityDb::entry_t *KVStoreSecurityDb::as_entry(entry_handle_t db_handle) {
|
||||
entry_t* entry = reinterpret_cast<entry_t*>(db_handle);
|
||||
if (!entry) {
|
||||
tr_error("Invalid security DB handle used");
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool KVStoreSecurityDb::open_db()
|
||||
{
|
||||
uint8_t version = 0;
|
||||
|
@ -68,11 +80,13 @@ bool KVStoreSecurityDb::open_db()
|
|||
|
||||
/* kvstore problem (check if it's been successfully initialised before this call) */
|
||||
if (ret != MBED_ERROR_ITEM_NOT_FOUND && (ret != MBED_SUCCESS || size != sizeof(uint8_t))) {
|
||||
tr_error("Failed to read KV store, check if it's initialised");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* wipe the db if it's the wrong version or it doesn't exist */
|
||||
if (version != KVSTORESECURITYDB_VERSION) {
|
||||
tr_warning("Security missing or invalid, reinit");
|
||||
return erase_db();
|
||||
}
|
||||
|
||||
|
@ -81,6 +95,7 @@ bool KVStoreSecurityDb::open_db()
|
|||
|
||||
bool KVStoreSecurityDb::erase_db()
|
||||
{
|
||||
tr_info("Erasing security DB in KV store");
|
||||
union zero_t {
|
||||
int dummy; /* we need a dummy for initialisation */
|
||||
uint8_t buffer[sizeof(SecurityEntryKeys_t)];
|
||||
|
@ -111,7 +126,11 @@ bool KVStoreSecurityDb::erase_db()
|
|||
version = 0;
|
||||
db_read(&version, DB_VERSION);
|
||||
|
||||
return (version == KVSTORESECURITYDB_VERSION);
|
||||
bool success = (version == KVSTORESECURITYDB_VERSION);
|
||||
if (!success) {
|
||||
tr_error("failed to write security DB in KV store");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* KVStoreSecurityDb::get_distribution_flags(
|
||||
|
@ -139,6 +158,7 @@ void KVStoreSecurityDb::set_entry_local_ltk(
|
|||
SecurityEntryKeys_t* current_entry = read_in_entry_local_keys(db_handle);
|
||||
current_entry->ltk = ltk;
|
||||
|
||||
tr_info("Write DB entry %d: local ltk %s", get_index(db_handle), to_string(ltk));
|
||||
db_write_entry(current_entry, DB_ENTRY_LOCAL_KEYS, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -157,6 +177,7 @@ void KVStoreSecurityDb::set_entry_local_ediv_rand(
|
|||
current_entry->ediv = ediv;
|
||||
current_entry->rand = rand;
|
||||
|
||||
tr_info("Write DB entry %d: local ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
db_write_entry(current_entry, DB_ENTRY_LOCAL_KEYS, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -179,6 +200,7 @@ void KVStoreSecurityDb::set_entry_peer_ltk(
|
|||
SecurityEntryKeys_t* current_entry = read_in_entry_peer_keys(db_handle);
|
||||
current_entry->ltk = ltk;
|
||||
|
||||
tr_info("Write DB entry %d: peer ltk %s", get_index(db_handle), to_string(ltk));
|
||||
db_write_entry(current_entry, DB_ENTRY_PEER_KEYS, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -197,6 +219,7 @@ void KVStoreSecurityDb::set_entry_peer_ediv_rand(
|
|||
current_entry->ediv = ediv;
|
||||
current_entry->rand = rand;
|
||||
|
||||
tr_info("Write DB entry %d: peer ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
db_write_entry(current_entry, DB_ENTRY_PEER_KEYS, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -215,6 +238,7 @@ void KVStoreSecurityDb::set_entry_peer_irk(
|
|||
SecurityEntryIdentity_t* current_entry = read_in_entry_peer_identity(db_handle);
|
||||
current_entry->irk = irk;
|
||||
|
||||
tr_info("Write DB entry %d: peer irk %s", get_index(db_handle), to_string(irk));
|
||||
db_write_entry(current_entry, DB_ENTRY_PEER_IDENTITY, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -233,6 +257,7 @@ void KVStoreSecurityDb::set_entry_peer_bdaddr(
|
|||
current_entry->identity_address = peer_address;
|
||||
current_entry->identity_address_is_public = address_is_public;
|
||||
|
||||
tr_info("Write DB entry %d: %s peer address %s", get_index(db_handle), address_is_public? "public" : "private", to_string(peer_address));
|
||||
db_write_entry(current_entry, DB_ENTRY_PEER_IDENTITY, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -251,6 +276,7 @@ void KVStoreSecurityDb::set_entry_peer_csrk(
|
|||
SecurityEntrySigning_t* current_entry = read_in_entry_peer_signing(db_handle);
|
||||
current_entry->csrk = csrk;
|
||||
|
||||
tr_info("Write DB entry %d: peer csrk %s", get_index(db_handle), to_string(csrk));
|
||||
db_write_entry(current_entry, DB_ENTRY_PEER_SIGNING, get_index(entry));
|
||||
}
|
||||
|
||||
|
@ -270,6 +296,7 @@ void KVStoreSecurityDb::set_local_csrk(
|
|||
)
|
||||
{
|
||||
this->SecurityDb::set_local_csrk(csrk);
|
||||
tr_info("Write DB: local csrk %s", to_string(csrk));
|
||||
db_write(&_local_csrk, DB_LOCAL_CSRK);
|
||||
}
|
||||
|
||||
|
@ -280,6 +307,7 @@ void KVStoreSecurityDb::set_local_identity(
|
|||
)
|
||||
{
|
||||
this->SecurityDb::set_local_identity(irk, identity_address, public_address);
|
||||
tr_info("Write DB: %s peer address %s", public_address? "public" : "private", to_string(identity_address));
|
||||
db_write(&_local_identity, DB_LOCAL_IDENTITY);
|
||||
}
|
||||
|
||||
|
@ -296,6 +324,7 @@ void KVStoreSecurityDb::restore()
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Valid DB in KV store - restoring security DB");
|
||||
db_read(&_entries, DB_ENTRIES);
|
||||
db_read(&_local_identity, DB_LOCAL_IDENTITY);
|
||||
db_read(&_local_csrk, DB_LOCAL_CSRK);
|
||||
|
@ -309,6 +338,7 @@ void KVStoreSecurityDb::sync(entry_handle_t db_handle)
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Synchronising security DB with KV store");
|
||||
/* all entries are stored in a single key so we store them all*/
|
||||
db_write(&_entries, DB_ENTRIES);
|
||||
db_write(&_local_identity, DB_LOCAL_IDENTITY);
|
||||
|
@ -318,6 +348,7 @@ void KVStoreSecurityDb::sync(entry_handle_t db_handle)
|
|||
|
||||
void KVStoreSecurityDb::set_restore(bool reload)
|
||||
{
|
||||
tr_info("Security DB set to restore on reset: %s", to_string(reload));
|
||||
db_write(&reload, DB_RESTORE);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,10 +63,6 @@ private:
|
|||
static constexpr char DB_VERSION[DB_KEY_SIZE] = { 'v','e','r' };
|
||||
static constexpr char DB_RESTORE[DB_KEY_SIZE] = { 'r','e','s' };
|
||||
|
||||
static entry_t* as_entry(entry_handle_t db_handle) {
|
||||
return reinterpret_cast<entry_t*>(db_handle);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void db_read(T *value, const char* key) {
|
||||
char db_key[DB_FULL_KEY_SIZE];
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MemorySecurityDb.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLDB"
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
|
||||
namespace ble {
|
||||
|
||||
MemorySecurityDb::entry_t *MemorySecurityDb::as_entry(entry_handle_t db_handle)
|
||||
{
|
||||
entry_t* entry = reinterpret_cast<entry_t*>(db_handle);
|
||||
if (!entry) {
|
||||
tr_error("Invalid security DB handle used");
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
MemorySecurityDb::MemorySecurityDb() : SecurityDb()
|
||||
{
|
||||
tr_info("Using memory security DB (capacity " STR(BLE_SECURITY_DATABASE_MAX_ENTRIES) " entries) - no persistence across reset");
|
||||
}
|
||||
|
||||
|
||||
SecurityDistributionFlags_t *MemorySecurityDb::get_distribution_flags(
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle);
|
||||
}
|
||||
|
||||
/* local keys */
|
||||
|
||||
/* set */
|
||||
void MemorySecurityDb::set_entry_local_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: local ltk %s", get_index(db_handle), to_string(ltk));
|
||||
entry->flags.ltk_sent = true;
|
||||
entry->local_keys.ltk = ltk;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_local_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: local ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
entry->local_keys.ediv = ediv;
|
||||
entry->local_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: peer ltk %s", get_index(db_handle), to_string(ltk));
|
||||
entry->peer_keys.ltk = ltk;
|
||||
entry->flags.ltk_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: peer ediv %s rand %s", get_index(db_handle), to_string(ediv), to_string(rand));
|
||||
entry->peer_keys.ediv = ediv;
|
||||
entry->peer_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_irk(
|
||||
entry_handle_t db_handle,
|
||||
const irk_t &irk
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: peer irk %s", get_index(db_handle), to_string(irk));
|
||||
entry->peer_identity.irk = irk;
|
||||
entry->flags.irk_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_bdaddr(
|
||||
entry_handle_t db_handle,
|
||||
bool address_is_public,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: %s peer address %s", get_index(db_handle), address_is_public? "public" : "private", to_string(peer_address));
|
||||
entry->peer_identity.identity_address = peer_address;
|
||||
entry->peer_identity.identity_address_is_public = address_is_public;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_csrk(
|
||||
entry_handle_t db_handle,
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: peer csrk %s", get_index(db_handle), to_string(csrk));
|
||||
entry->flags.csrk_stored = true;
|
||||
entry->peer_signing.csrk = csrk;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::set_entry_peer_sign_counter(
|
||||
entry_handle_t db_handle,
|
||||
sign_count_t sign_counter
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
tr_info("Write DB entry %d: sign counter %lu", get_index(db_handle), sign_counter);
|
||||
entry->peer_signing.counter = sign_counter;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MemorySecurityDb::get_entry_count() {
|
||||
return BLE_SECURITY_DATABASE_MAX_ENTRIES;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t *MemorySecurityDb::get_entry_handle_by_index(uint8_t index) {
|
||||
if (index < BLE_SECURITY_DATABASE_MAX_ENTRIES) {
|
||||
return &_entries[index].flags;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySecurityDb::reset_entry(entry_handle_t db_entry) {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
*entry = entry_t();
|
||||
}
|
||||
|
||||
SecurityEntryIdentity_t *MemorySecurityDb::read_in_entry_peer_identity(entry_handle_t db_entry) {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_identity;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t *MemorySecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_keys;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t *MemorySecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->local_keys;
|
||||
}
|
||||
|
||||
SecurityEntrySigning_t *MemorySecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_signing;
|
||||
}
|
||||
|
||||
uint8_t MemorySecurityDb::get_index(const entry_handle_t db_handle) const
|
||||
{
|
||||
return reinterpret_cast<entry_t*>(db_handle) - _entries;
|
||||
}
|
||||
|
||||
} /* namespace ble */
|
|
@ -35,20 +35,16 @@ private:
|
|||
SecurityEntrySigning_t peer_signing;
|
||||
};
|
||||
|
||||
static entry_t* as_entry(entry_handle_t db_handle)
|
||||
{
|
||||
return reinterpret_cast<entry_t*>(db_handle);
|
||||
}
|
||||
static entry_t *as_entry(entry_handle_t db_handle);
|
||||
|
||||
public:
|
||||
MemorySecurityDb() : SecurityDb() { }
|
||||
MemorySecurityDb();
|
||||
|
||||
~MemorySecurityDb() override = default;
|
||||
|
||||
SecurityDistributionFlags_t* get_distribution_flags(
|
||||
SecurityDistributionFlags_t *get_distribution_flags(
|
||||
entry_handle_t db_handle
|
||||
) override {
|
||||
return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle);
|
||||
}
|
||||
) override;
|
||||
|
||||
/* local keys */
|
||||
|
||||
|
@ -56,25 +52,13 @@ public:
|
|||
void set_entry_local_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->flags.ltk_sent = true;
|
||||
entry->local_keys.ltk = ltk;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_local_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->local_keys.ediv = ediv;
|
||||
entry->local_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
/* peer's keys */
|
||||
|
||||
|
@ -83,107 +67,51 @@ public:
|
|||
void set_entry_peer_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_keys.ltk = ltk;
|
||||
entry->flags.ltk_stored = true;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_peer_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_keys.ediv = ediv;
|
||||
entry->peer_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_peer_irk(
|
||||
entry_handle_t db_handle,
|
||||
const irk_t &irk
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_identity.irk = irk;
|
||||
entry->flags.irk_stored = true;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_peer_bdaddr(
|
||||
entry_handle_t db_handle,
|
||||
bool address_is_public,
|
||||
const address_t &peer_address
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_identity.identity_address = peer_address;
|
||||
entry->peer_identity.identity_address_is_public = address_is_public;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_peer_csrk(
|
||||
entry_handle_t db_handle,
|
||||
const csrk_t &csrk
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->flags.csrk_stored = true;
|
||||
entry->peer_signing.csrk = csrk;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
void set_entry_peer_sign_counter(
|
||||
entry_handle_t db_handle,
|
||||
sign_count_t sign_counter
|
||||
) override {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_signing.counter = sign_counter;
|
||||
}
|
||||
}
|
||||
) override;
|
||||
|
||||
private:
|
||||
uint8_t get_entry_count() override {
|
||||
return BLE_SECURITY_DATABASE_MAX_ENTRIES;
|
||||
}
|
||||
uint8_t get_entry_count() override;
|
||||
|
||||
SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) override {
|
||||
if (index < BLE_SECURITY_DATABASE_MAX_ENTRIES) {
|
||||
return &_entries[index].flags;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
SecurityDistributionFlags_t *get_entry_handle_by_index(uint8_t index) override;
|
||||
|
||||
void reset_entry(entry_handle_t db_entry) override{
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
*entry = entry_t();
|
||||
}
|
||||
void reset_entry(entry_handle_t db_entry) override;
|
||||
|
||||
SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_entry) override {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_identity;
|
||||
};
|
||||
SecurityEntryIdentity_t *read_in_entry_peer_identity(entry_handle_t db_entry) override;
|
||||
|
||||
SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_entry) override {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_keys;
|
||||
};
|
||||
SecurityEntryKeys_t *read_in_entry_peer_keys(entry_handle_t db_entry) override;
|
||||
|
||||
SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_entry) override {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->local_keys;
|
||||
};
|
||||
SecurityEntryKeys_t *read_in_entry_local_keys(entry_handle_t db_entry) override;
|
||||
|
||||
SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_entry) override {
|
||||
auto *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||
return &entry->peer_signing;
|
||||
};
|
||||
SecurityEntrySigning_t *read_in_entry_peer_signing(entry_handle_t db_entry) override;
|
||||
|
||||
uint8_t get_index(const entry_handle_t db_handle) const;
|
||||
|
||||
private:
|
||||
entry_t _entries[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include "PrivateAddressController.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLSM"
|
||||
|
||||
namespace ble {
|
||||
|
||||
|
@ -50,12 +54,14 @@ PrivateAddressController::~PrivateAddressController()
|
|||
|
||||
void PrivateAddressController::set_local_irk(const irk_t &local_irk)
|
||||
{
|
||||
tr_info("Set local irk: %s", to_string(local_irk));
|
||||
_local_irk = local_irk;
|
||||
generate_resolvable_address();
|
||||
}
|
||||
|
||||
void PrivateAddressController::set_timeout(ble::resolvable_address_timeout_t rotation_timeout)
|
||||
{
|
||||
tr_info("Set resolvable address timeout: %d s", rotation_timeout.value());
|
||||
_rotation_timeout = rotation_timeout;
|
||||
_pal.set_ll_resolvable_private_address_timeout(rotation_timeout);
|
||||
if (_generation_started) {
|
||||
|
@ -85,12 +91,15 @@ void PrivateAddressController::start_private_address_generation()
|
|||
return;
|
||||
}
|
||||
|
||||
tr_info("Start private address generation");
|
||||
|
||||
// non resolvable private address generation has been delayed until now,
|
||||
// generate it.
|
||||
generate_non_resolvable_address();
|
||||
|
||||
_address_rotation_ticker.attach([this] {
|
||||
_event_queue.post([this]{
|
||||
tr_info("Private address timeout");
|
||||
generate_resolvable_address();
|
||||
generate_non_resolvable_address();
|
||||
});
|
||||
|
@ -101,6 +110,7 @@ void PrivateAddressController::start_private_address_generation()
|
|||
void PrivateAddressController::stop_private_address_generation()
|
||||
{
|
||||
if (_generation_started) {
|
||||
tr_info("Stop private address generation");
|
||||
_address_rotation_ticker.detach();
|
||||
_generation_started = false;
|
||||
}
|
||||
|
@ -110,14 +120,19 @@ void PrivateAddressController::generate_resolvable_address()
|
|||
{
|
||||
if (_local_irk != irk_t{}) {
|
||||
_pal.generate_resolvable_private_address(_local_irk);
|
||||
} else {
|
||||
tr_warning("Failed to generate resolvable address, no local irk");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::on_resolvable_private_address_generated(const address_t &rpa)
|
||||
{
|
||||
tr_info("Resolvable private address generated: %s", to_string(rpa));
|
||||
_resolvable_address = rpa;
|
||||
if (_event_handler) {
|
||||
_event_handler->on_resolvable_private_addresses_generated(_resolvable_address);
|
||||
} else {
|
||||
tr_warning("No app handler to receive RPA generated");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +142,8 @@ void PrivateAddressController::generate_non_resolvable_address()
|
|||
_event_queue.post([this] {
|
||||
if (_event_handler) {
|
||||
_event_handler->on_non_resolvable_private_addresses_generated(_non_resolvable_address);
|
||||
} else {
|
||||
tr_warning("No app handler to receive NRPA generated");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -168,7 +185,10 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list(
|
|||
const irk_t& peer_irk
|
||||
)
|
||||
{
|
||||
tr_info("Add device to resolving list: peer address=%s, type=%s, peer irk=%s",
|
||||
to_string(peer_identity_address), to_string(peer_address_type), to_string(peer_irk));
|
||||
if (_local_irk == irk_t{}) {
|
||||
tr_error("Invalid local IRK: %s", to_string(_local_irk));
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
@ -198,6 +218,7 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list(
|
|||
}
|
||||
|
||||
if (!entry_added) {
|
||||
tr_error("Failed to add address into host resolving list, not enough space");
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -221,6 +242,7 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list(
|
|||
peer_irk
|
||||
);
|
||||
} else {
|
||||
tr_error("Host based private address resolution enabled but not supported by the controller");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
@ -231,6 +253,8 @@ ble_error_t PrivateAddressController::remove_device_from_resolving_list(
|
|||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
tr_info("Remove device from resolving list: peer address=%s, type=%s",
|
||||
to_string(peer_identity_address), to_string(peer_address_type));
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
for (auto &entry : _resolving_list) {
|
||||
if (entry.populated &&
|
||||
|
@ -252,6 +276,7 @@ ble_error_t PrivateAddressController::remove_device_from_resolving_list(
|
|||
if (is_controller_privacy_supported()) {
|
||||
return queue_remove_device_from_resolving_list(peer_address_type, peer_identity_address);
|
||||
} else {
|
||||
tr_error("Host based private address resolution enabled but not supported by the controller");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
@ -259,6 +284,7 @@ ble_error_t PrivateAddressController::remove_device_from_resolving_list(
|
|||
|
||||
ble_error_t PrivateAddressController::clear_resolving_list()
|
||||
{
|
||||
tr_info("Clear resolving list");
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
// Remove entry from the resolving list
|
||||
for (auto &entry : _resolving_list) {
|
||||
|
@ -277,6 +303,7 @@ ble_error_t PrivateAddressController::clear_resolving_list()
|
|||
if (is_controller_privacy_supported()) {
|
||||
return queue_clear_resolving_list();
|
||||
} else {
|
||||
tr_error("Host based private address resolution enabled but not supported by the controller");
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
@ -310,12 +337,15 @@ bool PrivateAddressController::resolve_address_in_host_cache(
|
|||
entry->next = _resolved_list;
|
||||
_resolved_list = entry;
|
||||
}
|
||||
tr_debug("Resolved address from cache: rpa=%s, resolved address=%s, type=%s",
|
||||
to_string(peer_address), to_string(entry->identity->peer_address), to_string(entry->identity->peer_address_type));
|
||||
return true;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
tr_debug("Address not found in cache: %s", to_string(peer_address));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -340,6 +370,7 @@ ble_error_t PrivateAddressController::resolve_address_on_host(
|
|||
|
||||
void PrivateAddressController::on_resolving_list_action_complete()
|
||||
{
|
||||
tr_info("Resolving list action completed");
|
||||
process_privacy_control_blocks(true);
|
||||
}
|
||||
|
||||
|
@ -412,6 +443,7 @@ ble_error_t PrivateAddressController::queue_add_device_to_resolving_list(
|
|||
peer_irk
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
tr_error("Failed to create control block to add device to resolving list");
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
@ -458,6 +490,7 @@ ble_error_t PrivateAddressController::queue_remove_device_from_resolving_list(
|
|||
peer_identity_address
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
tr_error("Failed to create control block to remove device from resolving list");
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
@ -488,6 +521,7 @@ ble_error_t PrivateAddressController::queue_clear_resolving_list()
|
|||
|
||||
auto *cb = new(std::nothrow) PrivacyClearResListControlBlock();
|
||||
if (cb == nullptr) {
|
||||
tr_error("Failed to create control block to clear resolving list");
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
@ -549,6 +583,7 @@ private:
|
|||
}
|
||||
} while (!self._resolving_list[resolving_list_index].populated);
|
||||
|
||||
tr_debug("Start resolution with next identity entry: %s", to_string(peer_address));
|
||||
start_resolution(self);
|
||||
return false;
|
||||
}
|
||||
|
@ -567,6 +602,13 @@ private:
|
|||
resolving_list_entry_t* identity
|
||||
)
|
||||
{
|
||||
if (!resolved) {
|
||||
tr_debug("Address resolution complete: rpa=%s, resolved=%s", to_string(peer_resolvable_address), to_string(resolved));
|
||||
} else {
|
||||
tr_debug("Address resolution complete: rpa=%s, resolved=%s, identity address=%s, type=%s",
|
||||
to_string(peer_resolvable_address), to_string(resolved), to_string(identity->peer_address), to_string(identity->peer_address_type));
|
||||
}
|
||||
|
||||
// First we had the device to the resolution list
|
||||
self.add_resolution_entry_to_cache(peer_resolvable_address, identity);
|
||||
|
||||
|
@ -591,6 +633,7 @@ ble_error_t PrivateAddressController::queue_resolve_address_on_host(const addres
|
|||
auto *cb = new(std::nothrow) PrivacyResolveAddressOnHost(peer_address);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
tr_error("Not enough memory to queue host address resolution: %s", to_string(peer_address));
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -605,6 +648,7 @@ void PrivateAddressController::restart_resolution_process_on_host()
|
|||
{
|
||||
// if processing is active, restart the one running.
|
||||
if (_processing_privacy_control_block && _pending_privacy_control_blocks) {
|
||||
tr_info("Restart host address resolution process");
|
||||
static_cast<PrivacyResolveAddressOnHost*>(_pending_privacy_control_blocks)->invalidate();
|
||||
}
|
||||
}
|
||||
|
@ -614,6 +658,7 @@ void PrivateAddressController::on_private_address_resolved(bool success)
|
|||
if (_pending_privacy_control_blocks == nullptr ||
|
||||
_processing_privacy_control_block == false
|
||||
) {
|
||||
tr_warning("Received unexpected address resolution event");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -625,6 +670,7 @@ void PrivateAddressController::on_private_address_resolved(bool success)
|
|||
|
||||
void PrivateAddressController::clear_privacy_control_blocks()
|
||||
{
|
||||
tr_info("Clear privacy control blocks");
|
||||
while (_pending_privacy_control_blocks != nullptr) {
|
||||
PrivacyControlBlock *next = _pending_privacy_control_blocks->next();
|
||||
delete _pending_privacy_control_blocks;
|
||||
|
@ -634,6 +680,7 @@ void PrivateAddressController::clear_privacy_control_blocks()
|
|||
|
||||
void PrivateAddressController::queue_privacy_control_block(PrivacyControlBlock *block)
|
||||
{
|
||||
tr_info("Queue privacy request");
|
||||
if (_pending_privacy_control_blocks == nullptr) {
|
||||
_pending_privacy_control_blocks = block;
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,428 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SecurityDb.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLDB"
|
||||
|
||||
namespace ble {
|
||||
|
||||
SecurityDb::SecurityDb() : _local_sign_counter(0) { };
|
||||
|
||||
void SecurityDb::set_distribution_flags(
|
||||
entry_handle_t db_handle,
|
||||
const SecurityDistributionFlags_t& new_flags
|
||||
)
|
||||
{
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
*flags = new_flags;
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityDb::get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t* db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
)
|
||||
{
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(*db_handle);
|
||||
/* validate we have the correct key */
|
||||
if (keys && ediv == keys->ediv && rand == keys->rand) {
|
||||
cb(*db_handle, keys);
|
||||
} else {
|
||||
// Maybe this isn't the correct entry, try to find one that matches
|
||||
entry_handle_t correct_handle = find_entry_by_peer_ediv_rand(ediv, rand);
|
||||
if (!correct_handle) {
|
||||
tr_warn("Failed to find ltk matching given ediv&rand");
|
||||
cb(*db_handle, NULL);
|
||||
return;
|
||||
}
|
||||
tr_warn("Found ltk matching given ediv&rand but it belonged to a different identity, update entry with new identity");
|
||||
// Note: keys should never be null as a matching entry has been retrieved
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(correct_handle);
|
||||
MBED_ASSERT(keys);
|
||||
|
||||
/* set flags connected */
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(correct_handle);
|
||||
flags->connected = true;
|
||||
|
||||
/* update peer address */
|
||||
SecurityDistributionFlags_t* old_flags = get_distribution_flags(*db_handle);
|
||||
flags->peer_address = old_flags->peer_address;
|
||||
flags->peer_address_is_public = old_flags->peer_address_is_public;
|
||||
|
||||
close_entry(*db_handle, false);
|
||||
*db_handle = correct_handle;
|
||||
cb(*db_handle, keys);
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityDb::get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
)
|
||||
{
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
/* validate we have the correct key */
|
||||
if (flags && keys && flags->secure_connections_paired) {
|
||||
cb(db_handle, keys);
|
||||
} else {
|
||||
cb(db_handle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityDb::get_entry_peer_csrk(
|
||||
SecurityEntrySigningDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
)
|
||||
{
|
||||
SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle);
|
||||
cb(db_handle, signing);
|
||||
}
|
||||
|
||||
void SecurityDb::get_entry_peer_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
)
|
||||
{
|
||||
SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle);
|
||||
cb(db_handle, keys);
|
||||
}
|
||||
|
||||
void SecurityDb::get_entry_identity(
|
||||
SecurityEntryIdentityDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
)
|
||||
{
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags && flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||
if (peer_identity) {
|
||||
cb(db_handle, peer_identity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* avoid duplicate else */
|
||||
cb(db_handle, NULL);
|
||||
}
|
||||
|
||||
void SecurityDb::get_identity_list(
|
||||
IdentitylistDbCb_t cb,
|
||||
Span<SecurityEntryIdentity_t>& identity_list
|
||||
)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < get_entry_count() && count < (size_t) identity_list.size(); ++i) {
|
||||
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
|
||||
if (flags && flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||
if (peer_identity) {
|
||||
identity_list[count] = *peer_identity;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb(identity_list, count);
|
||||
}
|
||||
|
||||
const csrk_t *SecurityDb::get_local_csrk()
|
||||
{
|
||||
return &_local_csrk;
|
||||
}
|
||||
|
||||
sign_count_t SecurityDb::get_local_sign_counter()
|
||||
{
|
||||
return _local_sign_counter;
|
||||
}
|
||||
|
||||
void SecurityDb::set_local_csrk(const csrk_t &csrk)
|
||||
{
|
||||
_local_csrk = csrk;
|
||||
}
|
||||
|
||||
void SecurityDb::set_local_sign_counter(
|
||||
sign_count_t sign_counter
|
||||
)
|
||||
{
|
||||
_local_sign_counter = sign_counter;
|
||||
}
|
||||
|
||||
void SecurityDb::set_local_identity(
|
||||
const irk_t &irk,
|
||||
const address_t &identity_address,
|
||||
bool public_address
|
||||
)
|
||||
{
|
||||
_local_identity.irk = irk;
|
||||
_local_identity.identity_address = identity_address;
|
||||
_local_identity.identity_address_is_public = public_address;
|
||||
}
|
||||
|
||||
irk_t SecurityDb::get_local_irk()
|
||||
{
|
||||
return _local_identity.irk;
|
||||
}
|
||||
|
||||
|
||||
const address_t &SecurityDb::get_local_identity_address()
|
||||
{
|
||||
return _local_identity.identity_address;
|
||||
}
|
||||
|
||||
bool SecurityDb::is_local_identity_address_public()
|
||||
{
|
||||
return _local_identity.identity_address_is_public;
|
||||
}
|
||||
|
||||
SecurityDb::entry_handle_t SecurityDb::open_entry(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
)
|
||||
{
|
||||
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||
if (db_handle) {
|
||||
tr_debug("Found old DB entry (connected to peer previously)");
|
||||
((SecurityDistributionFlags_t*)db_handle)->connected = true;
|
||||
return db_handle;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = get_free_entry_flags();
|
||||
if (flags) {
|
||||
const bool peer_address_public =
|
||||
(peer_address_type == peer_address_type_t::PUBLIC) ||
|
||||
(peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
|
||||
/* we need some address to store, so we store even random ones
|
||||
* this address will be used as an id, possibly replaced later
|
||||
* by identity address */
|
||||
flags->peer_address = peer_address;
|
||||
flags->peer_address_is_public = peer_address_public;
|
||||
flags->connected = true;
|
||||
return flags;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SecurityDb::entry_handle_t SecurityDb::find_entry_by_peer_address(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
)
|
||||
{
|
||||
const bool peer_address_public =
|
||||
(peer_address_type == peer_address_type_t::PUBLIC) ||
|
||||
(peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
|
||||
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
/* only look among disconnected entries */
|
||||
if (flags && !flags->connected) {
|
||||
if (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY &&
|
||||
flags->irk_stored == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lookup for connection address used during bonding */
|
||||
if (flags->peer_address == peer_address &&
|
||||
flags->peer_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* look for the identity address if stored */
|
||||
if (flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
|
||||
if (identity &&
|
||||
identity->identity_address == peer_address &&
|
||||
identity->identity_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SecurityDb::entry_handle_t SecurityDb::find_entry_by_peer_ediv_rand(
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
)
|
||||
{
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (!flags || flags->connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
if (!keys) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keys->ediv == ediv && keys->rand == rand) {
|
||||
return db_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SecurityDb::close_entry(entry_handle_t db_handle, bool require_sync) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
flags->connected = false;
|
||||
}
|
||||
if (require_sync) {
|
||||
sync(db_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityDb::remove_entry(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
tr_info("Clearing entry for address %s", to_string(peer_address));
|
||||
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||
if (db_handle) {
|
||||
reset_entry(db_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void SecurityDb::clear_entries()
|
||||
{
|
||||
tr_info("Clearing all entries");
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
reset_entry(db_handle);
|
||||
}
|
||||
_local_identity = SecurityEntryIdentity_t();
|
||||
_local_csrk = csrk_t();
|
||||
}
|
||||
|
||||
void SecurityDb::get_whitelist(
|
||||
WhitelistDbCb_t cb,
|
||||
::ble::whitelist_t *whitelist
|
||||
) {
|
||||
/*TODO: fill whitelist*/
|
||||
cb(whitelist);
|
||||
}
|
||||
|
||||
void SecurityDb::generate_whitelist_from_bond_table(
|
||||
WhitelistDbCb_t cb,
|
||||
::ble::whitelist_t *whitelist
|
||||
) {
|
||||
for (size_t i = 0; i < get_entry_count() && whitelist->size < whitelist->capacity; i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (!flags || !flags->irk_stored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the connection address
|
||||
whitelist->addresses[whitelist->size].address = flags->peer_address.data();
|
||||
|
||||
if (flags->peer_address_is_public) {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::PUBLIC;
|
||||
} else {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::RANDOM;
|
||||
}
|
||||
|
||||
whitelist->size++;
|
||||
if (whitelist->size == whitelist->capacity) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the identity address
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
if (!identity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
whitelist->addresses[whitelist->size].address = identity->identity_address;
|
||||
|
||||
if (identity->identity_address_is_public) {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::PUBLIC_IDENTITY;
|
||||
} else {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::RANDOM_STATIC_IDENTITY;
|
||||
}
|
||||
|
||||
whitelist->size++;
|
||||
}
|
||||
|
||||
cb(whitelist);
|
||||
}
|
||||
|
||||
void SecurityDb::set_whitelist(const ::ble::whitelist_t &whitelist) { };
|
||||
|
||||
void SecurityDb::add_whitelist_entry(const address_t &address) { };
|
||||
|
||||
void SecurityDb::remove_whitelist_entry(const address_t &address) { };
|
||||
|
||||
void SecurityDb::clear_whitelist() { };
|
||||
|
||||
void SecurityDb::restore() { };
|
||||
|
||||
void SecurityDb::sync(entry_handle_t db_handle) { };
|
||||
|
||||
void SecurityDb::set_restore(bool reload) { };
|
||||
|
||||
SecurityDistributionFlags_t* SecurityDb::get_free_entry_flags() {
|
||||
/* get a free one if available */
|
||||
tr_debug("Retrieve a disconnected entry to use as a new entry in DB.");
|
||||
SecurityDistributionFlags_t* match = nullptr;
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (flags && !flags->connected) {
|
||||
/* we settle for any disconnected if we don't find an empty one */
|
||||
match = flags;
|
||||
if (!flags->csrk_stored
|
||||
&& !flags->ltk_stored
|
||||
&& !flags->ltk_sent
|
||||
&& !flags->irk_stored) {
|
||||
/* empty one found, stop looking*/
|
||||
tr_debug("Using a previously unused entry as a new entry in DB.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
reset_entry(match);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
} /* namespace ble */
|
|
@ -126,7 +126,7 @@ public:
|
|||
typedef mbed::Callback<void(::ble::whitelist_t*)>
|
||||
WhitelistDbCb_t;
|
||||
|
||||
SecurityDb() : _local_sign_counter(0) { };
|
||||
SecurityDb();
|
||||
virtual ~SecurityDb() = default;
|
||||
|
||||
/**
|
||||
|
@ -149,12 +149,7 @@ public:
|
|||
virtual void set_distribution_flags(
|
||||
entry_handle_t db_handle,
|
||||
const SecurityDistributionFlags_t& new_flags
|
||||
) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
*flags = new_flags;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* local keys */
|
||||
|
||||
|
@ -171,36 +166,7 @@ public:
|
|||
entry_handle_t* db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(*db_handle);
|
||||
/* validate we have the correct key */
|
||||
if (keys && ediv == keys->ediv && rand == keys->rand) {
|
||||
cb(*db_handle, keys);
|
||||
} else {
|
||||
// Maybe this isn't the correct entry, try to find one that matches
|
||||
entry_handle_t correct_handle = find_entry_by_peer_ediv_rand(ediv, rand);
|
||||
if (!correct_handle) {
|
||||
cb(*db_handle, NULL);
|
||||
return;
|
||||
}
|
||||
// Note: keys should never be null as a matching entry has been retrieved
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(correct_handle);
|
||||
MBED_ASSERT(keys);
|
||||
|
||||
/* set flags connected */
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(correct_handle);
|
||||
flags->connected = true;
|
||||
|
||||
/* update peer address */
|
||||
SecurityDistributionFlags_t* old_flags = get_distribution_flags(*db_handle);
|
||||
flags->peer_address = old_flags->peer_address;
|
||||
flags->peer_address_is_public = old_flags->peer_address_is_public;
|
||||
|
||||
close_entry(*db_handle, false);
|
||||
*db_handle = correct_handle;
|
||||
cb(*db_handle, keys);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Retrieve stored LTK generated during secure connections pairing.
|
||||
|
@ -211,16 +177,7 @@ public:
|
|||
virtual void get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
/* validate we have the correct key */
|
||||
if (flags && keys && flags->secure_connections_paired) {
|
||||
cb(db_handle, keys);
|
||||
} else {
|
||||
cb(db_handle, NULL);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Save new local LTK for a connection.
|
||||
|
@ -259,10 +216,7 @@ public:
|
|||
virtual void get_entry_peer_csrk(
|
||||
SecurityEntrySigningDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle);
|
||||
cb(db_handle, signing);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Return asynchronously the peer encryption key through a callback
|
||||
|
@ -274,10 +228,7 @@ public:
|
|||
virtual void get_entry_peer_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle);
|
||||
cb(db_handle, keys);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Save new LTK received from the peer.
|
||||
|
@ -337,18 +288,7 @@ public:
|
|||
virtual void get_entry_identity(
|
||||
SecurityEntryIdentityDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags && flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||
if (peer_identity) {
|
||||
cb(db_handle, peer_identity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* avoid duplicate else */
|
||||
cb(db_handle, NULL);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Asynchronously return the identity list stored in NVM through a callback.
|
||||
|
@ -362,25 +302,7 @@ public:
|
|||
virtual void get_identity_list(
|
||||
IdentitylistDbCb_t cb,
|
||||
Span<SecurityEntryIdentity_t>& identity_list
|
||||
) {
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < get_entry_count() && count < (size_t) identity_list.size(); ++i) {
|
||||
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
|
||||
if (flags && flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||
if (peer_identity) {
|
||||
identity_list[count] = *peer_identity;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb(identity_list, count);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Update peer signing key.
|
||||
|
@ -411,18 +333,14 @@ public:
|
|||
*
|
||||
* @return pointer to local CSRK
|
||||
*/
|
||||
virtual const csrk_t* get_local_csrk() {
|
||||
return &_local_csrk;
|
||||
}
|
||||
virtual const csrk_t* get_local_csrk();
|
||||
|
||||
/**
|
||||
* Return local signing counter.
|
||||
*
|
||||
* @return signing counter
|
||||
*/
|
||||
virtual sign_count_t get_local_sign_counter() {
|
||||
return _local_sign_counter;
|
||||
}
|
||||
virtual sign_count_t get_local_sign_counter();
|
||||
|
||||
/**
|
||||
* Update local signing key.
|
||||
|
@ -431,9 +349,7 @@ public:
|
|||
*/
|
||||
virtual void set_local_csrk(
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
_local_csrk = csrk;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Update local signing counter.
|
||||
|
@ -442,9 +358,7 @@ public:
|
|||
*/
|
||||
virtual void set_local_sign_counter(
|
||||
sign_count_t sign_counter
|
||||
) {
|
||||
_local_sign_counter = sign_counter;
|
||||
}
|
||||
);
|
||||
|
||||
/* local identity */
|
||||
/**
|
||||
|
@ -456,34 +370,24 @@ public:
|
|||
const irk_t &irk,
|
||||
const address_t &identity_address,
|
||||
bool public_address
|
||||
) {
|
||||
_local_identity.irk = irk;
|
||||
_local_identity.identity_address = identity_address;
|
||||
_local_identity.identity_address_is_public = public_address;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Return local irk.
|
||||
*
|
||||
* @return irk
|
||||
*/
|
||||
virtual irk_t get_local_irk() {
|
||||
return _local_identity.irk;
|
||||
}
|
||||
virtual irk_t get_local_irk();
|
||||
|
||||
/**
|
||||
* Return local identity address.
|
||||
*/
|
||||
virtual const address_t& get_local_identity_address() {
|
||||
return _local_identity.identity_address;
|
||||
}
|
||||
virtual const address_t& get_local_identity_address();
|
||||
|
||||
/**
|
||||
* Return if the local identity address is public or not
|
||||
*/
|
||||
virtual bool is_local_identity_address_public() {
|
||||
return _local_identity.identity_address_is_public;
|
||||
}
|
||||
virtual bool is_local_identity_address_public();
|
||||
|
||||
/* list management */
|
||||
|
||||
|
@ -502,29 +406,7 @@ public:
|
|||
virtual entry_handle_t open_entry(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||
if (db_handle) {
|
||||
((SecurityDistributionFlags_t*)db_handle)->connected = true;
|
||||
return db_handle;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = get_free_entry_flags();
|
||||
if (flags) {
|
||||
const bool peer_address_public =
|
||||
(peer_address_type == peer_address_type_t::PUBLIC) ||
|
||||
(peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
|
||||
/* we need some address to store, so we store even random ones
|
||||
* this address will be used as an id, possibly replaced later
|
||||
* by identity address */
|
||||
flags->peer_address = peer_address;
|
||||
flags->peer_address_is_public = peer_address_public;
|
||||
flags->connected = true;
|
||||
return flags;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Find a database entry based on peer address.
|
||||
|
@ -537,43 +419,7 @@ public:
|
|||
virtual entry_handle_t find_entry_by_peer_address(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
const bool peer_address_public =
|
||||
(peer_address_type == peer_address_type_t::PUBLIC) ||
|
||||
(peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
|
||||
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
/* only look among disconnected entries */
|
||||
if (flags && !flags->connected) {
|
||||
if (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY &&
|
||||
flags->irk_stored == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lookup for connection address used during bonding */
|
||||
if (flags->peer_address == peer_address &&
|
||||
flags->peer_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* look for the identity address if stored */
|
||||
if (flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
|
||||
if (identity &&
|
||||
identity->identity_address == peer_address &&
|
||||
identity->identity_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Find a database entry based on ediv and rand.
|
||||
|
@ -586,27 +432,7 @@ public:
|
|||
virtual entry_handle_t find_entry_by_peer_ediv_rand(
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (!flags || flags->connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
if (!keys) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keys->ediv == ediv && keys->rand == rand) {
|
||||
return db_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -614,15 +440,7 @@ public:
|
|||
*
|
||||
* @param[in] db_handle this handle will be freed up from the security db.
|
||||
*/
|
||||
virtual void close_entry(entry_handle_t db_handle, bool require_sync = true) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
flags->connected = false;
|
||||
}
|
||||
if (require_sync) {
|
||||
sync(db_handle);
|
||||
}
|
||||
}
|
||||
virtual void close_entry(entry_handle_t db_handle, bool require_sync = true);
|
||||
|
||||
/**
|
||||
* Remove entry for this peer from NVM.
|
||||
|
@ -636,24 +454,12 @@ public:
|
|||
virtual void remove_entry(
|
||||
peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||
if (db_handle) {
|
||||
reset_entry(db_handle);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Remove all entries from the security DB.
|
||||
*/
|
||||
virtual void clear_entries() {
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
reset_entry(db_handle);
|
||||
}
|
||||
_local_identity = SecurityEntryIdentity_t();
|
||||
_local_csrk = csrk_t();
|
||||
}
|
||||
virtual void clear_entries();
|
||||
|
||||
/**
|
||||
* Asynchronously return the whitelist stored in NVM through a callback.
|
||||
|
@ -666,10 +472,7 @@ public:
|
|||
virtual void get_whitelist(
|
||||
WhitelistDbCb_t cb,
|
||||
::ble::whitelist_t *whitelist
|
||||
) {
|
||||
/*TODO: fill whitelist*/
|
||||
cb(whitelist);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Asynchronously return a whitelist through a callback, generated from the
|
||||
|
@ -681,93 +484,52 @@ public:
|
|||
virtual void generate_whitelist_from_bond_table(
|
||||
WhitelistDbCb_t cb,
|
||||
::ble::whitelist_t *whitelist
|
||||
) {
|
||||
for (size_t i = 0; i < get_entry_count() && whitelist->size < whitelist->capacity; i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (!flags || !flags->irk_stored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the connection address
|
||||
whitelist->addresses[whitelist->size].address = flags->peer_address.data();
|
||||
|
||||
if (flags->peer_address_is_public) {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::PUBLIC;
|
||||
} else {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::RANDOM;
|
||||
}
|
||||
|
||||
whitelist->size++;
|
||||
if (whitelist->size == whitelist->capacity) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the identity address
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
if (!identity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
whitelist->addresses[whitelist->size].address = identity->identity_address;
|
||||
|
||||
if (identity->identity_address_is_public) {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::PUBLIC_IDENTITY;
|
||||
} else {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::RANDOM_STATIC_IDENTITY;
|
||||
}
|
||||
|
||||
whitelist->size++;
|
||||
}
|
||||
|
||||
cb(whitelist);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Update the whitelist stored in NVM by replacing it with new one.
|
||||
*
|
||||
* @param[in] whitelist
|
||||
*/
|
||||
virtual void set_whitelist(const ::ble::whitelist_t &whitelist) { };
|
||||
virtual void set_whitelist(const ::ble::whitelist_t &whitelist);
|
||||
|
||||
/**
|
||||
* Add a new entry to the whitelist in the NVM.
|
||||
*
|
||||
* @param[in] address new whitelist entry
|
||||
*/
|
||||
virtual void add_whitelist_entry(const address_t &address) { };
|
||||
virtual void add_whitelist_entry(const address_t &address);
|
||||
|
||||
/**
|
||||
* Remove whitelist entry from NVM.
|
||||
*
|
||||
* @param[in] address entry to be removed
|
||||
*/
|
||||
virtual void remove_whitelist_entry(const address_t &address) { };
|
||||
virtual void remove_whitelist_entry(const address_t &address);
|
||||
|
||||
/**
|
||||
*Remove all whitelist entries stored in the NVM.
|
||||
*/
|
||||
virtual void clear_whitelist() { };
|
||||
virtual void clear_whitelist();
|
||||
|
||||
/* saving and loading from nvm */
|
||||
|
||||
/**
|
||||
* Read values from storage.
|
||||
*/
|
||||
virtual void restore() { };
|
||||
virtual void restore();
|
||||
|
||||
/**
|
||||
* Flush all values which might be stored in memory into NVM.
|
||||
*/
|
||||
virtual void sync(entry_handle_t db_handle) { };
|
||||
virtual void sync(entry_handle_t db_handle);
|
||||
|
||||
/**
|
||||
* Toggle whether values should be preserved across resets.
|
||||
*
|
||||
* @param[in] reload if true values will be preserved across resets.
|
||||
*/
|
||||
virtual void set_restore(bool reload) { };
|
||||
virtual void set_restore(bool reload);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -775,35 +537,10 @@ private:
|
|||
* or use a disconnected entry by reseting all the stored information.
|
||||
* @return empty entry for the new connection
|
||||
*/
|
||||
virtual SecurityDistributionFlags_t* get_free_entry_flags() {
|
||||
/* get a free one if available */
|
||||
SecurityDistributionFlags_t* match = nullptr;
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (flags && !flags->connected) {
|
||||
/* we settle for any disconnected if we don't find an empty one */
|
||||
match = flags;
|
||||
if (!flags->csrk_stored
|
||||
&& !flags->ltk_stored
|
||||
&& !flags->ltk_sent
|
||||
&& !flags->irk_stored) {
|
||||
/* empty one found, stop looking*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
reset_entry(match);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
virtual SecurityDistributionFlags_t* get_free_entry_flags();
|
||||
|
||||
/**
|
||||
* How many entries can be stored in the databes.
|
||||
* How many entries can be stored in the database.
|
||||
* @return max number of entries
|
||||
*/
|
||||
virtual uint8_t get_entry_count() = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,6 +42,11 @@
|
|||
#include "rtos/Semaphore.h"
|
||||
#include "rtos/Mutex.h"
|
||||
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#include "common/ble_trace_helpers.h"
|
||||
|
||||
#define TRACE_GROUP "BLHC"
|
||||
|
||||
#define HCI_RESET_RAND_CNT 4
|
||||
|
||||
#define VENDOR_SPECIFIC_EVENT 0xFF
|
||||
|
|
|
@ -70,9 +70,6 @@
|
|||
// #undef TRACE_LEVEL_DEBUG
|
||||
// #define TRACE_LEVEL_DEBUG 0
|
||||
|
||||
/* tr_debug : add data content in console print */
|
||||
#define PRINT_HCI_DATA 0
|
||||
|
||||
/******************************************************************************
|
||||
* BLE config parameters
|
||||
******************************************************************************/
|
||||
|
@ -177,11 +174,6 @@ public:
|
|||
/* if event is a command complete event */
|
||||
if (*pMsg == HCI_CMD_CMPL_EVT) {
|
||||
tr_debug("Command Complete Event Command");
|
||||
#if (PRINT_HCI_DATA)
|
||||
for (uint8_t i = 0; i < 20; i++) {
|
||||
tr_debug(" %02X", *((uint8_t *)pMsg + i));
|
||||
}
|
||||
#endif
|
||||
/* parse parameters */
|
||||
tr_debug(" HCI_EVT_HDR_LEN=%d", HCI_EVT_HDR_LEN);
|
||||
pMsg += HCI_EVT_HDR_LEN;
|
||||
|
@ -579,11 +571,6 @@ private:
|
|||
tr_debug(" Type %#x", bleCmdBuf->cmdserial.type);
|
||||
tr_debug(" Cmd %#x", bleCmdBuf->cmdserial.cmd.cmdcode);
|
||||
tr_debug(" Len %#x", bleCmdBuf->cmdserial.cmd.plen);
|
||||
#if (PRINT_HCI_DATA)
|
||||
for (uint8_t i = 0; i < bleCmdBuf->cmdserial.cmd.plen; i++) {
|
||||
tr_debug(" %02X", *(((uint8_t *)&bleCmdBuf->cmdserial.cmd.payload) + i));
|
||||
}
|
||||
#endif
|
||||
TL_BLE_SendCmd(NULL, 0); // unused parameters for now
|
||||
break;
|
||||
case 2://ACL DATA
|
||||
|
@ -597,11 +584,6 @@ private:
|
|||
memcpy(aclDataBuffer + + sizeof(TL_PacketHeader_t) + sizeof(type), pData, len);
|
||||
TL_BLE_SendAclData(NULL, 0); // unused parameters for now
|
||||
tr_info("TX>> BLE ACL");
|
||||
#if (PRINT_HCI_DATA)
|
||||
for (uint8_t i = 0; i < len + 1 + 8; i++) {
|
||||
tr_debug(" %02x", *(((uint8_t *) aclDataBuffer) + i));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
|
|
Loading…
Reference in New Issue