Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,605 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "mbed.h"
#include "us_ticker_api.h"
#include "ble/BLE.h"
#include "CriticalSectionLock.h"
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_os.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "hci_drv.h"
#include "mbed_assert.h"
#include "bstream.h"
#include "ble/internal/PalAttClient.h"
#include "ble/internal/PalSecurityManager.h"
#include "ble/internal/PalGap.h"
#include "ble/internal/PalSigningMonitor.h"
#include "ble/internal/BLEInstanceBase.h"
#include "CordioHCIDriver.h"
using namespace std::chrono;
/*! WSF handler ID */
wsfHandlerId_t stack_handler_id;
/* WSF heap allocation */
uint8_t *SystemHeapStart;
uint32_t SystemHeapSize;
/**
* Weak definition of ble_cordio_get_hci_driver.
* A runtime error is generated if the user does not define any
* ble_cordio_get_hci_driver.
*/
MBED_WEAK ble::CordioHCIDriver &ble_cordio_get_hci_driver()
{
MBED_ASSERT("No HCI driver");
printf("Please provide an implementation for the HCI driver");
ble::CordioHCIDriver *bad_instance = nullptr;
return *bad_instance;
}
/**
* Low level HCI interface between Cordio stack and the port.
*/
extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData)
{
return ble_cordio_get_hci_driver().write(type, len, pData);
}
extern "C" void hci_mbed_os_start_reset_sequence(void)
{
ble_cordio_get_hci_driver().start_reset_sequence();
}
extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t *msg)
{
ble_cordio_get_hci_driver().handle_reset_sequence(msg);
}
/*
* This function will signal to the user code by calling signalEventsToProcess.
* It is registered and called into the Wsf Stack.
*/
extern "C" MBED_WEAK void wsf_mbed_ble_signal_event(void)
{
BLE::Instance().signalEventsToProcess();
}
/**
* BLE-API requires an implementation of the following function in order to
* obtain its transport handle.
*/
ble::BLEInstanceBase *createBLEInstance()
{
return (&(ble::BLEInstanceBase::deviceInstance()));
}
namespace ble {
BLEInstanceBase::BLEInstanceBase(CordioHCIDriver &hci_driver) :
initialization_status(NOT_INITIALIZED),
_event_queue(),
_last_update_us(0)
{
_hci_driver = &hci_driver;
stack_setup();
}
BLEInstanceBase::~BLEInstanceBase()
{}
/**
* The singleton which represents the BLE transport for the BLE.
*/
BLEInstanceBase &BLEInstanceBase::deviceInstance()
{
static BLEInstanceBase instance(
ble_cordio_get_hci_driver()
);
return instance;
}
ble_error_t BLEInstanceBase::init(
FunctionPointerWithContext<::BLE::InitializationCompleteCallbackContext *> initCallback)
{
switch (initialization_status) {
case NOT_INITIALIZED:
_timer.reset();
_timer.start();
_event_queue.initialize(this);
_init_callback = initCallback;
start_stack_reset();
return BLE_ERROR_NONE;
case INITIALIZING:
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
case INITIALIZED:
return BLE_ERROR_NONE;
default:
return BLE_ERROR_UNSPECIFIED;
}
}
bool BLEInstanceBase::hasInitialized() const
{
return initialization_status == INITIALIZED;
}
ble_error_t BLEInstanceBase::shutdown()
{
if (initialization_status != INITIALIZED) {
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
}
initialization_status = NOT_INITIALIZED;
_hci_driver->terminate();
#if BLE_FEATURE_GATT_SERVER
getGattServer().reset();
#endif
#if BLE_FEATURE_GATT_CLIENT
getGattClient().reset();
#endif // BLE_FEATURE_GATT_CLIENT
getGap().reset();
_event_queue.clear();
return BLE_ERROR_NONE;
}
const char *BLEInstanceBase::getVersion()
{
static const char version[] = "generic-cordio";
return version;
}
ble::Gap &BLEInstanceBase::getGap()
{
static ble::PalGenericAccessService cordio_gap_service;
static ble::Gap gap(
_event_queue,
ble::PalGap::get_gap(),
cordio_gap_service,
ble::PalSecurityManager::get_security_manager()
);
return gap;
}
const ble::Gap &BLEInstanceBase::getGap() const
{
BLEInstanceBase &self = const_cast<BLEInstanceBase &>(*this);
return const_cast<const ble::Gap &>(self.getGap());
};
#if BLE_FEATURE_GATT_SERVER
GattServer &BLEInstanceBase::getGattServer()
{
return GattServer::getInstance();
}
const GattServer &BLEInstanceBase::getGattServer() const
{
return GattServer::getInstance();
}
#endif // BLE_FEATURE_GATT_SERVER
#if BLE_FEATURE_GATT_CLIENT
ble::GattClient &BLEInstanceBase::getGattClient()
{
static ble::GattClient gatt_client(getPalGattClient());
return gatt_client;
}
PalGattClient &BLEInstanceBase::getPalGattClient()
{
static PalGattClient pal_gatt_client(PalAttClient::get_client());
return pal_gatt_client;
}
#endif // BLE_FEATURE_GATT_CLIENT
#if BLE_FEATURE_SECURITY
SecurityManager &BLEInstanceBase::getSecurityManager()
{
static PalSigningMonitor signing_event_monitor;
static ble::SecurityManager m_instance(
ble::PalSecurityManager::get_security_manager(),
getGap(),
signing_event_monitor
);
return m_instance;
}
const SecurityManager &BLEInstanceBase::getSecurityManager() const
{
const BLEInstanceBase &self = const_cast<BLEInstanceBase &>(*this);
return const_cast<const SecurityManager &>(self.getSecurityManager());
}
#endif // BLE_FEATURE_SECURITY
void BLEInstanceBase::waitForEvent()
{
static Timeout nextTimeout;
timestamp_t nextTimestamp;
bool_t pTimerRunning;
callDispatcher();
if (wsfOsReadyToSleep()) {
// setup an mbed timer for the next cordio timeout
nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK);
if (pTimerRunning) {
nextTimeout.attach(timeoutCallback, milliseconds(nextTimestamp));
}
}
}
void BLEInstanceBase::processEvents()
{
callDispatcher();
}
void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
{
if (msg == nullptr) {
return;
}
#if BLE_FEATURE_SECURITY
if (ble::PalSecurityManager::get_security_manager().sm_handler(msg)) {
return;
}
#endif // BLE_FEATURE_SECURITY
switch (msg->event) {
case DM_RESET_CMPL_IND: {
::BLE::InitializationCompleteCallbackContext context = {
::BLE::Instance(::BLE::DEFAULT_INSTANCE),
BLE_ERROR_NONE
};
#if BLE_FEATURE_EXTENDED_ADVERTISING
// initialize extended module if supported
if (HciGetLeSupFeat() & HCI_LE_SUP_FEAT_LE_EXT_ADV) {
#if BLE_ROLE_BROADCASTER
DmExtAdvInit();
#endif // BLE_ROLE_BROADCASTER
#if BLE_ROLE_OBSERVER
DmExtScanInit();
#endif // BLE_ROLE_OBSERVER
#if BLE_ROLE_CENTRAL
DmExtConnMasterInit();
#endif // BLE_ROLE_CENTRAL
#if BLE_ROLE_PERIPHERAL
DmExtConnSlaveInit();
#endif // BLE_ROLE_PERIPHERAL
}
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
#if BLE_FEATURE_GATT_SERVER
deviceInstance().getGattServer().initialize();
#endif
deviceInstance().initialization_status = INITIALIZED;
_init_callback.call(&context);
}
break;
#if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS
case DM_UNHANDLED_CMD_CMPL_EVT_IND: {
// 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) {
// unhandled events are not parsed so we need to parse the payload ourselves
uint8_t status;
uint16_t packet_number;
status = unhandled->param[0];
BYTES_TO_UINT16(packet_number, unhandled->param + 1);
_hci_driver->handle_test_end(status == 0, packet_number);
return;
}
}
break;
#endif // MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS
default:
ble::PalGap::gap_handler(msg);
break;
}
}
void BLEInstanceBase::device_manager_cb(dmEvt_t *dm_event)
{
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
ble::PalGapEventHandler *handler;
handler = ble::PalGap::get_gap().get_event_handler();
if (handler) {
handler->on_data_length_change(
dm_event->hdr.param,
dm_event->dataLenChange.maxTxOctets,
dm_event->dataLenChange.maxRxOctets
);
}
return;
}
BLEInstanceBase::deviceInstance().stack_handler(0, &dm_event->hdr);
}
/*
* AttServerInitDeInitCback callback is used to Initialize/Deinitialize
* the CCC Table of the ATT Server when a remote peer requests to Open
* or Close the connection.
*/
void BLEInstanceBase::connection_handler(dmEvt_t *dm_event)
{
dmConnId_t connId = (dmConnId_t) dm_event->hdr.param;
switch (dm_event->hdr.event) {
case DM_CONN_OPEN_IND:
/* set up CCC table with uninitialized (all zero) values */
AttsCccInitTable(connId, nullptr);
break;
case DM_CONN_CLOSE_IND:
/* clear CCC table on connection close */
AttsCccClearTable(connId);
break;
default:
break;
}
}
void BLEInstanceBase::timeoutCallback()
{
wsf_mbed_ble_signal_event();
}
void BLEInstanceBase::stack_setup()
{
MBED_ASSERT(_hci_driver != nullptr);
wsfHandlerId_t handlerId;
buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();
// use the buffer for the WSF heap
SystemHeapStart = buf_pool_desc.buffer_memory;
SystemHeapSize = buf_pool_desc.buffer_size;
// Initialize buffers with the ones provided by the HCI driver
uint16_t bytes_used = WsfBufInit(buf_pool_desc.pool_count, (wsfBufPoolDesc_t *) buf_pool_desc.pool_description);
// Raise assert if not enough memory was allocated
MBED_ASSERT(bytes_used != 0);
SystemHeapStart += bytes_used;
SystemHeapSize -= bytes_used;
// This warning will be raised if we've allocated too much memory
if (bytes_used < buf_pool_desc.buffer_size) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_BLE, MBED_ERROR_CODE_INVALID_SIZE),
"Too much memory allocated for Cordio memory pool, reduce buf_pool_desc.buffer_size by value below.",
buf_pool_desc.buffer_size - bytes_used);
}
WsfTimerInit();
// Note: SecInit required for RandInit.
SecInit();
SecRandInit();
#if BLE_FEATURE_SECURITY
SecAesInit();
SecCmacInit();
SecEccInit();
#endif
handlerId = WsfOsSetNextHandler(HciHandler);
HciHandlerInit(handlerId);
handlerId = WsfOsSetNextHandler(DmHandler);
#if BLE_ROLE_BROADCASTER
DmAdvInit();
#endif
#if BLE_ROLE_OBSERVER
DmScanInit();
#endif
#if BLE_FEATURE_CONNECTABLE
DmConnInit();
#endif
#if BLE_ROLE_CENTRAL
DmConnMasterInit();
#endif
#if BLE_ROLE_PERIPHERAL
DmConnSlaveInit();
#endif
#if BLE_FEATURE_SECURITY
DmSecInit();
#endif
#if BLE_FEATURE_PHY_MANAGEMENT
DmPhyInit();
#endif
#if BLE_FEATURE_SECURE_CONNECTIONS
DmSecLescInit();
#endif
#if BLE_FEATURE_PRIVACY
DmPrivInit();
#endif
DmHandlerInit(handlerId);
#if BLE_ROLE_PERIPHERAL
handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
L2cSlaveHandlerInit(handlerId);
#endif
#if BLE_FEATURE_CONNECTABLE
L2cInit();
#endif
#if BLE_ROLE_PERIPHERAL
L2cSlaveInit();
#endif
#if BLE_ROLE_CENTRAL
L2cMasterInit();
#endif
#if BLE_FEATURE_ATT
handlerId = WsfOsSetNextHandler(AttHandler);
AttHandlerInit(handlerId);
#if BLE_FEATURE_GATT_SERVER
AttsInit();
AttsIndInit();
#if BLE_FEATURE_SECURITY
AttsAuthorRegister(GattServer::atts_auth_cb);
#endif
#if BLE_FEATURE_SIGNING
AttsSignInit();
#endif
#endif // BLE_FEATURE_GATT_SERVER
#if BLE_FEATURE_GATT_CLIENT
AttcInit();
#if BLE_FEATURE_SIGNING
AttcSignInit();
#endif
#endif // BLE_FEATURE_GATT_CLIENT
#endif // BLE_FEATURE_ATT
#if BLE_FEATURE_SECURITY
handlerId = WsfOsSetNextHandler(SmpHandler);
SmpHandlerInit(handlerId);
#if BLE_ROLE_PERIPHERAL
SmprInit();
#if BLE_FEATURE_SECURE_CONNECTIONS
SmprScInit();
#endif
#endif
#if BLE_ROLE_CENTRAL
SmpiInit();
#if BLE_FEATURE_SECURE_CONNECTIONS
SmpiScInit();
#endif
#endif // BLE_ROLE_CENTRAL
#endif // BLE_FEATURE_SECURITY
stack_handler_id = WsfOsSetNextHandler(&BLEInstanceBase::stack_handler);
HciSetMaxRxAclLen(MBED_CONF_CORDIO_RX_ACL_BUFFER_SIZE);
DmRegister(BLEInstanceBase::device_manager_cb);
#if BLE_FEATURE_CONNECTABLE
DmConnRegister(DM_CLIENT_ID_APP, BLEInstanceBase::device_manager_cb);
#endif
#if BLE_FEATURE_GATT_SERVER
AttConnRegister(BLEInstanceBase::connection_handler);
#endif
#if BLE_FEATURE_ATT
#if BLE_FEATURE_GATT_CLIENT
AttRegister((attCback_t) ble::PalAttClient::att_client_handler);
#else
AttRegister((attCback_t) ble::GattServer::att_cb);
#endif // BLE_FEATURE_GATT_CLIENT
#endif
}
void BLEInstanceBase::start_stack_reset()
{
_hci_driver->initialize();
DmDevReset();
}
void BLEInstanceBase::callDispatcher()
{
// process the external event queue
_event_queue.process();
_last_update_us += (uint64_t) _timer.elapsed_time().count();
_timer.reset();
uint64_t last_update_ms = (_last_update_us / 1000);
wsfTimerTicks_t wsf_ticks = (last_update_ms / WSF_MS_PER_TICK);
if (wsf_ticks > 0) {
WsfTimerUpdate(wsf_ticks);
_last_update_us -= (last_update_ms * 1000);
}
wsfOsDispatcher();
static LowPowerTimeout nextTimeout;
CriticalSectionLock critical_section;
if (wsfOsReadyToSleep()) {
// setup an mbed timer for the next Cordio timeout
bool_t pTimerRunning;
timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK);
if (pTimerRunning) {
nextTimeout.attach(timeoutCallback, milliseconds(nextTimestamp));
} else {
critical_section.disable();
_hci_driver->on_host_stack_inactivity();
}
}
}
CordioHCIDriver *BLEInstanceBase::_hci_driver = nullptr;
FunctionPointerWithContext<::BLE::InitializationCompleteCallbackContext *> BLEInstanceBase::_init_callback;
} // namespace ble

View File

@@ -0,0 +1,451 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "ble/internal/PalAttClient.h"
#include "ble/GattServer.h"
#include "ble/internal/PalSimpleAttServerMessage.h"
#include "ble/internal/PalGap.h"
#include "ble/internal/PalGattClient.h"
#include "ble/internal/BLEInstanceBase.h"
#include "att_api.h"
#include "att_defs.h"
namespace ble {
PalAttClient::PalAttClient() : _local_sign_counter(0) {}
PalAttClient::~PalAttClient() {}
/**
* @see ble::PalAttClient::exchange_mtu_request
*/
ble_error_t PalAttClient::exchange_mtu_request(connection_handle_t connection)
{
AttcMtuReq(connection, pAttCfg->mtu);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalGattClient::get_mtu_size
*/
ble_error_t PalAttClient::get_mtu_size(
connection_handle_t connection_handle,
uint16_t &mtu_size
)
{
mtu_size = AttGetMtu(connection_handle);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::find_information_request
*/
ble_error_t PalAttClient::find_information_request(
connection_handle_t connection_handle,
attribute_handle_range_t discovery_range
)
{
AttcFindInfoReq(
connection_handle,
discovery_range.begin,
discovery_range.end,
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::find_by_type_value_request
*/
ble_error_t PalAttClient::find_by_type_value_request(
connection_handle_t connection_handle,
attribute_handle_range_t discovery_range,
uint16_t type,
const Span<const uint8_t> &value
)
{
AttcFindByTypeValueReq(
connection_handle,
discovery_range.begin,
discovery_range.end,
type,
value.size(),
const_cast<uint8_t *>(value.data()),
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::read_by_type_request
*/
ble_error_t PalAttClient::read_by_type_request(
connection_handle_t connection_handle,
attribute_handle_range_t read_range,
const UUID &type
)
{
AttcReadByTypeReq(
connection_handle,
read_range.begin,
read_range.end,
type.getLen(),
const_cast<uint8_t *>(type.getBaseUUID()),
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::read_request
*/
ble_error_t PalAttClient::read_request(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle
)
{
AttcReadReq(connection_handle, attribute_handle);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::read_blob_request
*/
ble_error_t PalAttClient::read_blob_request(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
uint16_t offset
)
{
AttcReadLongReq(
connection_handle,
attribute_handle,
offset,
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::read_multiple_request
*/
ble_error_t PalAttClient::read_multiple_request(
connection_handle_t connection_handle,
const Span<const attribute_handle_t> &attribute_handles
)
{
AttcReadMultipleReq(
connection_handle,
attribute_handles.size(),
const_cast<uint16_t *>(attribute_handles.data())
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::read_by_group_type_request
*/
ble_error_t PalAttClient::read_by_group_type_request(
connection_handle_t connection_handle,
attribute_handle_range_t read_range,
const UUID &group_type
)
{
AttcReadByGroupTypeReq(
connection_handle,
read_range.begin,
read_range.end,
group_type.getLen(),
const_cast<uint8_t *>(group_type.getBaseUUID()),
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::write_request
*/
ble_error_t PalAttClient::write_request(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
const Span<const uint8_t> &value
)
{
AttcWriteReq(
connection_handle,
attribute_handle,
value.size(),
const_cast<uint8_t *>(value.data())
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::write_command
*/
ble_error_t PalAttClient::write_command(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
const Span<const uint8_t> &value
)
{
AttcWriteCmd(
connection_handle,
attribute_handle,
value.size(),
const_cast<uint8_t *>(value.data())
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::signed_write_command
*/
ble_error_t PalAttClient::signed_write_command(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
const Span<const uint8_t> &value
)
{
AttcSignedWriteCmd(
connection_handle,
attribute_handle,
_local_sign_counter,
value.size(),
const_cast<uint8_t *>(value.data())
);
_local_sign_counter++;
return BLE_ERROR_NONE;
}
/**
* Initialises the counter used to sign messages. Counter will be incremented every
* time a message is signed.
*
* @param sign_counter initialise the signing counter to this value
*/
void PalAttClient::set_sign_counter(
sign_count_t sign_counter
)
{
_local_sign_counter = sign_counter;
}
/**
* @see ble::PalAttClient::prepare_write_request
*/
ble_error_t PalAttClient::prepare_write_request(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
uint16_t offset,
const Span<const uint8_t> &value
)
{
AttcPrepareWriteReq(
connection_handle,
attribute_handle,
offset,
value.size(),
const_cast<uint8_t *>(value.data()),
false,
false
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::execute_write_request
*/
ble_error_t PalAttClient::execute_write_request(
connection_handle_t connection_handle,
bool execute
)
{
AttcExecuteWriteReq(
connection_handle,
execute
);
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::initialize
*/
ble_error_t PalAttClient::initialize()
{
return BLE_ERROR_NONE;
}
/**
* @see ble::PalAttClient::terminate
*/
ble_error_t PalAttClient::terminate()
{
return BLE_ERROR_NONE;
}
// singleton of the ARM Cordio client
PalAttClient &PalAttClient::get_client()
{
static PalAttClient _client;
return _client;
}
void PalAttClient::when_server_message_received(
mbed::Callback<void(connection_handle_t, const AttServerMessage &)> cb
)
{
_server_message_cb = cb;
}
void PalAttClient::when_transaction_timeout(
mbed::Callback<void(connection_handle_t)> cb
)
{
_transaction_timeout_cb = cb;
}
// convert an array of byte to an uint16_t
uint16_t PalAttClient::to_uint16_t(const uint8_t *array)
{
uint16_t result;
memcpy(&result, array, sizeof(result));
return result;
}
template<typename T>
bool PalAttClient::event_handler(const attEvt_t *event)
{
if (T::can_convert(event)) {
generated_handler(event, T::convert);
return true;
}
return false;
}
bool PalAttClient::timeout_event_handler(const attEvt_t *event)
{
if (event->hdr.status != ATT_ERR_TIMEOUT) {
return false;
}
get_client().on_transaction_timeout(event->hdr.param);
return true;
}
template<typename ResultType>
void PalAttClient::generated_handler(
const attEvt_t *event, ResultType (*convert)(const attEvt_t *)
)
{
get_client().on_server_event(
event->hdr.param,
convert(event)
);
}
void PalAttClient::on_server_event(
connection_handle_t connection_handle,
const AttServerMessage &server_message
)
{
if (_server_message_cb) {
_server_message_cb(connection_handle, server_message);
}
}
/**
* Upon transaction timeout an implementation shall call this function.
*
* @param connection_handle The handle of the connection of the transaction
* which has times out.
*
* @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3
*/
void PalAttClient::on_transaction_timeout(
connection_handle_t connection_handle
)
{
if (_transaction_timeout_cb) {
_transaction_timeout_cb(connection_handle);
}
}
void PalAttClient::att_client_handler(const attEvt_t *event)
{
#if BLE_FEATURE_GATT_CLIENT
if (event->hdr.status == ATT_SUCCESS && event->hdr.event == ATT_MTU_UPDATE_IND) {
ble::BLEInstanceBase &ble = ble::BLEInstanceBase::deviceInstance();
PalGattClientEventHandler *handler = ble.getPalGattClient().get_event_handler();
if (handler) {
handler->on_att_mtu_change(event->hdr.param, event->mtu);
}
} else if (event->hdr.event == ATTC_WRITE_CMD_RSP) {
ble::BLEInstanceBase &ble = ble::BLEInstanceBase::deviceInstance();
PalGattClientEventHandler *handler = ble.getPalGattClient().get_event_handler();
if (handler) {
handler->on_write_command_sent(
event->hdr.param,
event->handle,
event->hdr.status
);
}
} else {
// all handlers are stored in a static array
static const event_handler_t handlers[] = {
&timeout_event_handler,
&event_handler<ErrorResponseConverter>,
&event_handler<FindInformationResponseConverter>,
&event_handler<FindByTypeValueResponseConverter>,
&event_handler<ReadByTypeResponseConverter>,
&event_handler<ReadResponseConverter>,
&event_handler<ReadBlobResponseConverter>,
&event_handler<ReadMultipleResponseConverter>,
&event_handler<ReadBygroupTypeResponseConverter>,
&event_handler<WriteResponseConverter>,
&event_handler<PrepareWriteResponseConverter>,
&event_handler<ExecuteWriteResponseConverter>,
&event_handler<HandleValueIndicationConverter>,
&event_handler<HandleValueNotificationConverter>
};
// event->hdr.param: connection handle
// event->header.event: opcode from the request
// event->header.status: success or error code ...
// event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses.
// event->handle: handle for server initiated responses
// traverse all handlers and execute them with the event in input.
// exit if an handler has handled the event.
for (size_t i = 0; i < (sizeof(handlers) / sizeof(handlers[0])); ++i) {
if (handlers[i](event)) {
return;
}
}
}
#endif // BLE_FEATURE_GATT_CLIENT
#if BLE_FEATURE_GATT_SERVER
// pass events not handled to the server side
ble::GattServer::getInstance().att_cb(event);
#endif // BLE_FEATURE_GATT_SERVER
}
} // ble

View File

@@ -0,0 +1,29 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "ble/internal/PalEventQueue.h"
#include "ble/internal/BLEInstanceBase.h"
namespace ble {
void PalEventQueue::signal_event()
{
_ble_base->signalEventsToProcess();
}
} // namespace ble

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,251 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "ble/internal/PalGattClient.h"
#include "ble/internal/PalAttClient.h"
namespace ble {
PalGattClient::PalGattClient(PalAttClient& client) : _event_handler(nullptr), _client(client)
{
_client.when_server_message_received(
mbed::callback(this, &PalGattClient::on_server_event)
);
_client.when_transaction_timeout(
mbed::callback(
this, &PalGattClient::on_transaction_timeout
)
);
}
ble_error_t PalGattClient::exchange_mtu(connection_handle_t connection)
{
return _client.exchange_mtu_request(connection);
}
ble_error_t PalGattClient::get_mtu_size(
connection_handle_t connection_handle,
uint16_t& mtu_size
)
{
return _client.get_mtu_size(connection_handle, mtu_size);
}
ble_error_t PalGattClient::discover_primary_service(
connection_handle_t connection,
attribute_handle_t discovery_range_begining
)
{
return _client.read_by_group_type_request(
connection,
attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE),
SERVICE_TYPE_UUID
);
}
ble_error_t PalGattClient::discover_primary_service_by_service_uuid(
connection_handle_t connection_handle,
attribute_handle_t discovery_range_begining,
const UUID& uuid
)
{
return _client.find_by_type_value_request(
connection_handle,
attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE),
SERVICE_TYPE_UUID,
Span<const uint8_t>(
uuid.getBaseUUID(),
(uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) ? 2 : UUID::LENGTH_OF_LONG_UUID
)
);
}
ble_error_t PalGattClient::find_included_service(
connection_handle_t connection_handle,
attribute_handle_range_t service_range
)
{
return _client.read_by_type_request(
connection_handle,
service_range,
INCLUDE_TYPE_UUID
);
}
ble_error_t PalGattClient::discover_characteristics_of_a_service(
connection_handle_t connection_handle,
attribute_handle_range_t discovery_range
)
{
return _client.read_by_type_request(
connection_handle,
discovery_range,
CHARACTERISTIC_TYPE_UUID
);
}
ble_error_t PalGattClient::discover_characteristics_descriptors(
connection_handle_t connection_handle,
attribute_handle_range_t descriptors_discovery_range
)
{
return _client.find_information_request(
connection_handle,
descriptors_discovery_range
);
}
ble_error_t PalGattClient::read_attribute_value(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle
)
{
return _client.read_request(
connection_handle,
attribute_handle
);
}
ble_error_t PalGattClient::read_using_characteristic_uuid(
connection_handle_t connection_handle,
attribute_handle_range_t read_range,
const UUID& uuid
)
{
return _client.read_by_type_request(
connection_handle,
read_range,
uuid
);
}
ble_error_t PalGattClient::read_attribute_blob(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
uint16_t offset
)
{
return _client.read_blob_request(
connection_handle,
attribute_handle,
offset
);
}
ble_error_t PalGattClient::read_multiple_characteristic_values(
connection_handle_t connection_handle,
const Span<const attribute_handle_t>& characteristic_value_handles
)
{
return _client.read_multiple_request(
connection_handle,
characteristic_value_handles
);
}
ble_error_t PalGattClient::write_without_response(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const Span<const uint8_t>& value
)
{
return _client.write_command(
connection_handle,
characteristic_value_handle,
value
);
}
ble_error_t PalGattClient::signed_write_without_response(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const Span<const uint8_t>& value
)
{
return _client.signed_write_command(
connection_handle,
characteristic_value_handle,
value
);
}
ble_error_t PalGattClient::write_attribute(
connection_handle_t connection_handle,
attribute_handle_t attribute_handle,
const Span<const uint8_t>& value
)
{
return _client.write_request(
connection_handle,
attribute_handle,
value
);
}
ble_error_t PalGattClient::queue_prepare_write(
connection_handle_t connection_handle,
attribute_handle_t characteristic_value_handle,
const Span<const uint8_t>& value,
uint16_t offset
)
{
return _client.prepare_write_request(
connection_handle,
characteristic_value_handle,
offset,
value
);
}
ble_error_t PalGattClient::execute_write_queue(
connection_handle_t connection_handle,
bool execute
)
{
return _client.execute_write_request(connection_handle, execute);
}
ble_error_t PalGattClient::initialize()
{
return _client.initialize();
}
ble_error_t PalGattClient::terminate()
{
return _client.initialize();
}
} // ble

View File

@@ -0,0 +1,125 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "ble/internal/PalGenericAccessService.h"
namespace ble {
#if 0 // Disabled until reworked and reintroduced to GattServer API
virtual ble_error_t PalGenericAccessService::get_device_name_length(uint8_t& length)
{
#if BLE_FEATURE_GATT_SERVER
const uint8_t* name = nullptr;
uint16_t actual_length = 0;
gatt_server().getDeviceName(name, actual_length);
length = actual_length;
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif
}
virtual ble_error_t PalGenericAccessService::get_device_name(Span<uint8_t>& array) {
#if BLE_FEATURE_GATT_SERVER
const uint8_t* name = nullptr;
uint16_t length = 0;
gatt_server().getDeviceName(name, length);
if (length > array.size()) {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
memcpy(array.data(), name, length);
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
virtual ble_error_t PalGenericAccessService::set_device_name(const uint8_t* device_name) {
#if BLE_FEATURE_GATT_SERVER
return gatt_server().setDeviceName(device_name);
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
virtual ble_error_t PalGenericAccessService::get_appearance(
GapAdvertisingData::Appearance& appearance
) {
#if BLE_FEATURE_GATT_SERVER
appearance = gatt_server().getAppearance();
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
virtual ble_error_t PalGenericAccessService::set_appearance(
GapAdvertisingData::Appearance appearance
) {
#if BLE_FEATURE_GATT_SERVER
gatt_server().setAppearance(appearance);
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
#endif // Disabled until reworked and reintroduced to GattServer API
ble_error_t PalGenericAccessService::get_peripheral_preferred_connection_parameters(
ble::Gap::PreferredConnectionParams_t& parameters
)
{
#if BLE_FEATURE_GATT_SERVER
parameters = gatt_server().getPreferredConnectionParams();
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
ble_error_t PalGenericAccessService::set_peripheral_preferred_connection_parameters(
const ble::Gap::PreferredConnectionParams_t& parameters
)
{
#if BLE_FEATURE_GATT_SERVER
gatt_server().setPreferredConnectionParams(parameters);
return BLE_ERROR_NONE;
#else
return BLE_ERROR_NOT_IMPLEMENTED;
#endif // BLE_FEATURE_GATT_SERVER
}
#if BLE_FEATURE_GATT_SERVER
ble::GattServer& PalGenericAccessService::gatt_server()
{
return ble::GattServer::getInstance();
}
} // ble
#endif // BLE_FEATURE_GATT_SERVER

View File

@@ -0,0 +1,35 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 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 "ble/internal/PalSigningMonitor.h"
#include "ble/internal/BLEInstanceBase.h"
#include "ble/GattClient.h"
namespace ble {
void PalSigningMonitor::set_signing_event_handler(SecurityManager *handler)
{
#if BLE_FEATURE_GATT_CLIENT
BLEInstanceBase::deviceInstance().getGattClient().set_signing_event_handler(handler);
#endif // BLE_FEATURE_GATT_CLIENT
#if BLE_FEATURE_GATT_SERVER
BLEInstanceBase::deviceInstance().getGattServer().set_signing_event_handler(handler);
#endif // BLE_FEATURE_GATT_SERVER
}
}