Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,612 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef IMPL_GAP_GAP_H
|
||||
#define IMPL_GAP_GAP_H
|
||||
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "drivers/LowPowerTimeout.h"
|
||||
#include "drivers/LowPowerTicker.h"
|
||||
#include "platform/mbed_error.h"
|
||||
|
||||
#include "ble/common/ble/BLERoles.h"
|
||||
#include "ble/common/ble/BLETypes.h"
|
||||
#include "ble/common/ble/gap/AdvertisingDataBuilder.h"
|
||||
#include "ble/common/ble/gap/AdvertisingDataSimpleBuilder.h"
|
||||
#include "ble/common/ble/gap/ConnectionParameters.h"
|
||||
#include "ble/common/ble/gap/ScanParameters.h"
|
||||
#include "ble/common/ble/gap/AdvertisingParameters.h"
|
||||
#include "ble/common/ble/gap/Events.h"
|
||||
|
||||
#include "ble/internal/PalGap.h"
|
||||
#include "ble/common/ble/GapEvents.h"
|
||||
#include "ble/common/ble/GapTypes.h"
|
||||
#include "ble/internal/PalEventQueue.h"
|
||||
#include "ble/internal/PalConnectionMonitor.h"
|
||||
#include "PalEventQueue.h"
|
||||
|
||||
#include "ble/Gap.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
class PalGenericAccessService;
|
||||
class PalSecurityManager;
|
||||
class PalGap;
|
||||
class BLEInstanceBase;
|
||||
|
||||
class Gap :
|
||||
public ble::interface::Gap,
|
||||
public PalConnectionMonitor,
|
||||
public PalGapEventHandler
|
||||
{
|
||||
friend PalConnectionMonitor;
|
||||
friend PalGapEventHandler;
|
||||
friend PalGap;
|
||||
friend BLEInstanceBase;
|
||||
public:
|
||||
/**
|
||||
* Default peripheral privacy configuration.
|
||||
*/
|
||||
static const peripheral_privacy_configuration_t
|
||||
default_peripheral_privacy_configuration;
|
||||
|
||||
/**
|
||||
* Default peripheral privacy configuration.
|
||||
*/
|
||||
static const central_privacy_configuration_t
|
||||
default_central_privacy_configuration;
|
||||
|
||||
public:
|
||||
void setEventHandler(EventHandler *handler);
|
||||
|
||||
bool isFeatureSupported(controller_supported_features_t feature);
|
||||
|
||||
/* advertising */
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
|
||||
uint8_t getMaxAdvertisingSetNumber();
|
||||
|
||||
uint16_t getMaxAdvertisingDataLength();
|
||||
|
||||
uint16_t getMaxConnectableAdvertisingDataLength();
|
||||
|
||||
uint16_t getMaxActiveSetAdvertisingDataLength();
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
ble_error_t createAdvertisingSet(
|
||||
advertising_handle_t *handle,
|
||||
const AdvertisingParameters ¶meters
|
||||
);
|
||||
|
||||
ble_error_t destroyAdvertisingSet(advertising_handle_t handle);
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
ble_error_t setAdvertisingParameters(
|
||||
advertising_handle_t handle,
|
||||
const AdvertisingParameters ¶ms
|
||||
);
|
||||
|
||||
ble_error_t setAdvertisingPayload(
|
||||
advertising_handle_t handle,
|
||||
mbed::Span<const uint8_t> payload
|
||||
);
|
||||
|
||||
ble_error_t setAdvertisingScanResponse(
|
||||
advertising_handle_t handle,
|
||||
mbed::Span<const uint8_t> response
|
||||
);
|
||||
|
||||
ble_error_t startAdvertising(
|
||||
advertising_handle_t handle,
|
||||
adv_duration_t maxDuration = adv_duration_t::forever(),
|
||||
uint8_t maxEvents = 0
|
||||
);
|
||||
|
||||
ble_error_t stopAdvertising(advertising_handle_t handle);
|
||||
|
||||
bool isAdvertisingActive(advertising_handle_t handle);
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
|
||||
ble_error_t setPeriodicAdvertisingParameters(
|
||||
advertising_handle_t handle,
|
||||
periodic_interval_t periodicAdvertisingIntervalMin,
|
||||
periodic_interval_t periodicAdvertisingIntervalMax,
|
||||
bool advertiseTxPower = true
|
||||
);
|
||||
|
||||
ble_error_t setPeriodicAdvertisingPayload(
|
||||
advertising_handle_t handle,
|
||||
mbed::Span<const uint8_t> payload
|
||||
);
|
||||
|
||||
ble_error_t startPeriodicAdvertising(advertising_handle_t handle);
|
||||
|
||||
ble_error_t stopPeriodicAdvertising(advertising_handle_t handle);
|
||||
|
||||
bool isPeriodicAdvertisingActive(advertising_handle_t handle);
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
#endif // BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
|
||||
/* scanning */
|
||||
#if BLE_ROLE_OBSERVER
|
||||
|
||||
ble_error_t setScanParameters(const ScanParameters ¶ms);
|
||||
|
||||
ble_error_t startScan(
|
||||
scan_duration_t duration = scan_duration_t::forever(),
|
||||
duplicates_filter_t filtering = duplicates_filter_t::DISABLE,
|
||||
scan_period_t period = scan_period_t(0)
|
||||
);
|
||||
|
||||
ble_error_t stopScan();
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
|
||||
ble_error_t createSync(
|
||||
peer_address_type_t peerAddressType,
|
||||
const address_t &peerAddress,
|
||||
uint8_t sid,
|
||||
slave_latency_t maxPacketSkip,
|
||||
sync_timeout_t timeout
|
||||
);
|
||||
|
||||
ble_error_t createSync(
|
||||
slave_latency_t maxPacketSkip,
|
||||
sync_timeout_t timeout
|
||||
);
|
||||
|
||||
ble_error_t cancelCreateSync();
|
||||
|
||||
ble_error_t terminateSync(periodic_sync_handle_t handle);
|
||||
|
||||
ble_error_t addDeviceToPeriodicAdvertiserList(
|
||||
peer_address_type_t peerAddressType,
|
||||
const address_t &peerAddress,
|
||||
advertising_sid_t sid
|
||||
);
|
||||
|
||||
ble_error_t removeDeviceFromPeriodicAdvertiserList(
|
||||
peer_address_type_t peerAddressType,
|
||||
const address_t &peerAddress,
|
||||
advertising_sid_t sid
|
||||
);
|
||||
|
||||
ble_error_t clearPeriodicAdvertiserList();
|
||||
|
||||
uint8_t getMaxPeriodicAdvertiserListSize();
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#endif // BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
|
||||
#if BLE_ROLE_CENTRAL
|
||||
|
||||
ble_error_t connect(
|
||||
peer_address_type_t peerAddressType,
|
||||
const address_t &peerAddress,
|
||||
const ConnectionParameters &connectionParams
|
||||
);
|
||||
|
||||
ble_error_t cancelConnect(
|
||||
peer_address_type_t peerAddressType,
|
||||
const address_t &peerAddress
|
||||
);
|
||||
|
||||
ble_error_t cancelConnect();
|
||||
#endif // BLE_ROLE_CENTRAL
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
|
||||
ble_error_t updateConnectionParameters(
|
||||
connection_handle_t connectionHandle,
|
||||
conn_interval_t minConnectionInterval,
|
||||
conn_interval_t maxConnectionInterval,
|
||||
slave_latency_t slaveLatency,
|
||||
supervision_timeout_t supervision_timeout,
|
||||
conn_event_length_t minConnectionEventLength = conn_event_length_t(0),
|
||||
conn_event_length_t maxConnectionEventLength = conn_event_length_t(0)
|
||||
);
|
||||
|
||||
ble_error_t manageConnectionParametersUpdateRequest(
|
||||
bool userManageConnectionUpdateRequest
|
||||
);
|
||||
|
||||
ble_error_t acceptConnectionParametersUpdate(
|
||||
connection_handle_t connectionHandle,
|
||||
conn_interval_t minConnectionInterval,
|
||||
conn_interval_t maxConnectionInterval,
|
||||
slave_latency_t slaveLatency,
|
||||
supervision_timeout_t supervision_timeout,
|
||||
conn_event_length_t minConnectionEventLength = conn_event_length_t(0),
|
||||
conn_event_length_t maxConnectionEventLength = conn_event_length_t(0)
|
||||
);
|
||||
|
||||
ble_error_t rejectConnectionParametersUpdate(
|
||||
connection_handle_t connectionHandle
|
||||
);
|
||||
|
||||
ble_error_t disconnect(
|
||||
connection_handle_t connectionHandle,
|
||||
local_disconnection_reason_t reason
|
||||
);
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
ble_error_t readPhy(connection_handle_t connection);
|
||||
|
||||
ble_error_t setPreferredPhys(
|
||||
const phy_set_t *txPhys,
|
||||
const phy_set_t *rxPhys
|
||||
);
|
||||
|
||||
ble_error_t setPhy(
|
||||
connection_handle_t connection,
|
||||
const phy_set_t *txPhys,
|
||||
const phy_set_t *rxPhys,
|
||||
coded_symbol_per_bit_t codedSymbol
|
||||
);
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
ble_error_t enablePrivacy(bool enable);
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
|
||||
ble_error_t setPeripheralPrivacyConfiguration(
|
||||
const peripheral_privacy_configuration_t *configuration
|
||||
);
|
||||
|
||||
ble_error_t getPeripheralPrivacyConfiguration(
|
||||
peripheral_privacy_configuration_t *configuration
|
||||
);
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
|
||||
ble_error_t setCentralPrivacyConfiguration(
|
||||
const central_privacy_configuration_t *configuration
|
||||
);
|
||||
|
||||
ble_error_t getCentralPrivacyConfiguration(
|
||||
central_privacy_configuration_t *configuration
|
||||
);
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#if BLE_FEATURE_WHITELIST
|
||||
|
||||
uint8_t getMaxWhitelistSize(void) const;
|
||||
|
||||
ble_error_t getWhitelist(whitelist_t &whitelist) const;
|
||||
|
||||
ble_error_t setWhitelist(const whitelist_t &whitelist);
|
||||
|
||||
#endif // BLE_FEATURE_WHITELIST
|
||||
|
||||
ble_error_t getAddress(
|
||||
own_address_type_t &typeP,
|
||||
address_t &address
|
||||
);
|
||||
|
||||
static ble_error_t getRandomAddressType(
|
||||
const ble::address_t address,
|
||||
ble::random_address_type_t *addressType
|
||||
);
|
||||
|
||||
ble_error_t reset(void);
|
||||
|
||||
void onShutdown(const GapShutdownCallback_t &callback);
|
||||
|
||||
template<typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const Gap *));
|
||||
|
||||
GapShutdownCallbackChain_t &onShutdown();
|
||||
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
/*
|
||||
* API reserved for the controller driver to set the random static address.
|
||||
* Setting a new random static address while the controller is operating is
|
||||
* forbidden by the Bluetooth specification.
|
||||
*/
|
||||
ble_error_t setRandomStaticAddress(const ble::address_t& address);
|
||||
#endif // !defined(DOXYGEN_ONLY)
|
||||
|
||||
/* ===================================================================== */
|
||||
/* private implementation follows */
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
Gap(const Gap &);
|
||||
Gap& operator=(const Gap &);
|
||||
|
||||
Gap(
|
||||
PalEventQueue &event_queue,
|
||||
PalGap &pal_gap,
|
||||
PalGenericAccessService &generic_access_service,
|
||||
PalSecurityManager &pal_sm
|
||||
);
|
||||
|
||||
~Gap();
|
||||
|
||||
ble_error_t setAdvertisingData(
|
||||
advertising_handle_t handle,
|
||||
Span<const uint8_t> payload,
|
||||
bool minimiseFragmentation,
|
||||
bool scan_response
|
||||
);
|
||||
|
||||
void on_advertising_timeout();
|
||||
|
||||
void process_advertising_timeout();
|
||||
|
||||
void on_gap_event_received(const GapEvent &e);
|
||||
|
||||
void on_advertising_report(const GapAdvertisingReportEvent &e);
|
||||
|
||||
void on_connection_complete(const GapConnectionCompleteEvent &e);
|
||||
|
||||
void on_disconnection_complete(const GapDisconnectionCompleteEvent &e);
|
||||
|
||||
void on_connection_parameter_request(
|
||||
const GapRemoteConnectionParameterRequestEvent &e
|
||||
);
|
||||
|
||||
void on_connection_update(const GapConnectionUpdateEvent &e);
|
||||
|
||||
void on_unexpected_error(const GapUnexpectedErrorEvent &e);
|
||||
|
||||
enum AddressUseType_t {
|
||||
CENTRAL_CONNECTION,
|
||||
CENTRAL_SCAN,
|
||||
PERIPHERAL_CONNECTABLE,
|
||||
PERIPHERAL_NON_CONNECTABLE
|
||||
};
|
||||
|
||||
own_address_type_t get_own_address_type(AddressUseType_t address_use_type);
|
||||
|
||||
bool initialize_whitelist() const;
|
||||
|
||||
ble_error_t update_address_resolution_setting();
|
||||
|
||||
void set_random_address_rotation(bool enable);
|
||||
|
||||
void update_random_address();
|
||||
|
||||
bool getUnresolvableRandomAddress(ble::address_t &address);
|
||||
|
||||
void on_address_rotation_timeout();
|
||||
|
||||
ble_error_t setExtendedAdvertisingParameters(
|
||||
advertising_handle_t handle,
|
||||
const AdvertisingParameters ¶meters
|
||||
);
|
||||
|
||||
bool is_extended_advertising_available();
|
||||
|
||||
void prepare_legacy_advertising_set();
|
||||
|
||||
/* implements PalGap::EventHandler */
|
||||
private:
|
||||
void on_read_phy(
|
||||
hci_error_code_t hci_status,
|
||||
connection_handle_t connection_handle,
|
||||
phy_t tx_phy,
|
||||
phy_t rx_phy
|
||||
);
|
||||
|
||||
void on_data_length_change(
|
||||
connection_handle_t connection_handle,
|
||||
uint16_t tx_size,
|
||||
uint16_t rx_size
|
||||
);
|
||||
|
||||
void on_phy_update_complete(
|
||||
hci_error_code_t hci_status,
|
||||
connection_handle_t connection_handle,
|
||||
phy_t tx_phy,
|
||||
phy_t rx_phy
|
||||
);
|
||||
|
||||
void on_enhanced_connection_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
connection_role_t own_role,
|
||||
connection_peer_address_type_t peer_address_type,
|
||||
const ble::address_t &peer_address,
|
||||
const ble::address_t &local_resolvable_private_address,
|
||||
const ble::address_t &peer_resolvable_private_address,
|
||||
uint16_t connection_interval,
|
||||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout,
|
||||
clock_accuracy_t master_clock_accuracy
|
||||
);
|
||||
|
||||
void on_extended_advertising_report(
|
||||
advertising_event_t event_type,
|
||||
const connection_peer_address_type_t *address_type,
|
||||
const ble::address_t &address,
|
||||
phy_t primary_phy,
|
||||
const phy_t *secondary_phy,
|
||||
advertising_sid_t advertising_sid,
|
||||
advertising_power_t tx_power,
|
||||
rssi_t rssi,
|
||||
uint16_t periodic_advertising_interval,
|
||||
direct_address_type_t direct_address_type,
|
||||
const ble::address_t &direct_address,
|
||||
uint8_t data_length,
|
||||
const uint8_t *data
|
||||
);
|
||||
|
||||
void on_periodic_advertising_sync_established(
|
||||
hci_error_code_t error,
|
||||
sync_handle_t sync_handle,
|
||||
advertising_sid_t advertising_sid,
|
||||
connection_peer_address_type_t advertiser_address_type,
|
||||
const ble::address_t &advertiser_address,
|
||||
phy_t advertiser_phy,
|
||||
uint16_t periodic_advertising_interval,
|
||||
clock_accuracy_t clock_accuracy
|
||||
);
|
||||
|
||||
void on_periodic_advertising_report(
|
||||
sync_handle_t sync_handle,
|
||||
advertising_power_t tx_power,
|
||||
rssi_t rssi,
|
||||
advertising_data_status_t data_status,
|
||||
uint8_t data_length,
|
||||
const uint8_t *data
|
||||
);
|
||||
|
||||
void on_periodic_advertising_sync_loss(sync_handle_t sync_handle);
|
||||
|
||||
void on_advertising_set_terminated(
|
||||
hci_error_code_t status,
|
||||
advertising_handle_t advertising_handle,
|
||||
connection_handle_t connection_handle,
|
||||
uint8_t number_of_completed_extended_advertising_events
|
||||
);
|
||||
|
||||
void on_scan_request_received(
|
||||
advertising_handle_t advertising_handle,
|
||||
connection_peer_address_type_t scanner_address_type,
|
||||
const ble::address_t &address
|
||||
);
|
||||
|
||||
void on_connection_update_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
uint16_t connection_interval,
|
||||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout
|
||||
);
|
||||
|
||||
void on_remote_connection_parameter(
|
||||
connection_handle_t connection_handle,
|
||||
uint16_t connection_interval_min,
|
||||
uint16_t connection_interval_max,
|
||||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout
|
||||
);
|
||||
|
||||
void on_scan_timeout();
|
||||
void process_legacy_scan_timeout();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for shutdown
|
||||
* events.
|
||||
*/
|
||||
GapShutdownCallbackChain_t shutdownCallChain;
|
||||
|
||||
/**
|
||||
* Event handler provided by the application.
|
||||
*/
|
||||
ble::Gap::EventHandler *_event_handler;
|
||||
|
||||
PalEventQueue &_event_queue;
|
||||
PalGap &_pal_gap;
|
||||
PalGenericAccessService &_gap_service;
|
||||
PalSecurityManager &_pal_sm;
|
||||
ble::own_address_type_t _address_type;
|
||||
ble::address_t _address;
|
||||
initiator_policy_t _initiator_policy_mode;
|
||||
scanning_filter_policy_t _scanning_filter_policy;
|
||||
advertising_filter_policy_t _advertising_filter_policy;
|
||||
mutable whitelist_t _whitelist;
|
||||
|
||||
bool _privacy_enabled;
|
||||
peripheral_privacy_configuration_t _peripheral_privacy_configuration;
|
||||
central_privacy_configuration_t _central_privacy_configuration;
|
||||
ble::address_t _random_static_identity_address;
|
||||
bool _random_address_rotating;
|
||||
|
||||
bool _scan_enabled;
|
||||
mbed::LowPowerTimeout _advertising_timeout;
|
||||
mbed::LowPowerTimeout _scan_timeout;
|
||||
mbed::LowPowerTicker _address_rotation_ticker;
|
||||
|
||||
template<size_t bit_size>
|
||||
struct BitArray {
|
||||
BitArray() : data()
|
||||
{
|
||||
}
|
||||
|
||||
bool get(size_t index) const
|
||||
{
|
||||
position p(index);
|
||||
return (data[p.byte_index] >> p.bit_index) & 0x01;
|
||||
}
|
||||
|
||||
void set(size_t index)
|
||||
{
|
||||
position p(index);
|
||||
data[p.byte_index] |= (0x01 << p.bit_index);
|
||||
}
|
||||
|
||||
void clear(size_t index)
|
||||
{
|
||||
position p(index);
|
||||
data[p.byte_index] &= ~(0x01 << p.bit_index);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (size_t i = 0; i < (bit_size / 8 + 1); ++i) {
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct position {
|
||||
position(size_t bit_number) :
|
||||
byte_index(bit_number / 8),
|
||||
bit_index(bit_number % 8)
|
||||
{
|
||||
}
|
||||
|
||||
size_t byte_index;
|
||||
uint8_t bit_index;
|
||||
};
|
||||
|
||||
uint8_t data[bit_size / 8 + 1];
|
||||
};
|
||||
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _existing_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _active_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _active_periodic_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _connectable_payload_size_exceeded;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _set_is_connectable;
|
||||
|
||||
bool _user_manage_connection_parameter_requests : 1;
|
||||
|
||||
/* these need be removed when the deprecated cancelConnect() is removed */
|
||||
peer_address_type_t _last_used_peer_address_type = peer_address_type_t::ANONYMOUS;
|
||||
ble::address_t _last_used_peer_address;
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif //IMPL_GAP_GAP_H
|
||||
@@ -0,0 +1,242 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef IMPL_GATT_CLIENT_H__
|
||||
#define IMPL_GATT_CLIENT_H__
|
||||
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "ble/common/ble/blecommon.h"
|
||||
#include "ble/common/ble/GattAttribute.h"
|
||||
#include "ble/common/ble/ServiceDiscovery.h"
|
||||
#include "ble/common/ble/CharacteristicDescriptorDiscovery.h"
|
||||
#include "ble/common/ble/GattCallbackParamTypes.h"
|
||||
#include "ble/internal/PalGattClient.h"
|
||||
#include "ble/internal/PalSigningMonitor.h"
|
||||
#include "ble/GattClient.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
class GattClient :
|
||||
public ble::interface::GattClient,
|
||||
public PalSigningMonitor,
|
||||
public PalGattClientEventHandler
|
||||
{
|
||||
friend PalSigningMonitor;
|
||||
friend BLEInstanceBase;
|
||||
public:
|
||||
void setEventHandler(EventHandler *handler);
|
||||
|
||||
ble_error_t launchServiceDiscovery(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t sc = NULL,
|
||||
ServiceDiscovery::CharacteristicCallback_t cc = NULL,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
|
||||
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)
|
||||
);
|
||||
|
||||
ble_error_t discoverServices(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t callback,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)
|
||||
);
|
||||
|
||||
ble_error_t discoverServices(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t callback,
|
||||
GattAttribute::Handle_t startHandle,
|
||||
GattAttribute::Handle_t endHandle
|
||||
);
|
||||
|
||||
bool isServiceDiscoveryActive(void) const;
|
||||
|
||||
void terminateServiceDiscovery(void);
|
||||
|
||||
ble_error_t read(
|
||||
ble::connection_handle_t connHandle,
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
uint16_t offset
|
||||
) const;
|
||||
|
||||
ble_error_t write(
|
||||
GattClient::WriteOp_t cmd,
|
||||
ble::connection_handle_t connHandle,
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
size_t length,
|
||||
const uint8_t *value
|
||||
) const;
|
||||
|
||||
/* Event callback handlers. */
|
||||
|
||||
void onDataRead(ReadCallback_t callback);
|
||||
|
||||
ReadCallbackChain_t& onDataRead();
|
||||
|
||||
void onDataWritten(WriteCallback_t callback);
|
||||
|
||||
WriteCallbackChain_t& onDataWritten();
|
||||
|
||||
void onServiceDiscoveryTermination(
|
||||
ServiceDiscovery::TerminationCallback_t callback
|
||||
);
|
||||
|
||||
ble_error_t discoverCharacteristicDescriptors(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
||||
);
|
||||
|
||||
bool isCharacteristicDescriptorDiscoveryActive(
|
||||
const DiscoveredCharacteristic& characteristic
|
||||
) const;
|
||||
|
||||
void terminateCharacteristicDescriptorDiscovery(
|
||||
const DiscoveredCharacteristic& characteristic
|
||||
);
|
||||
|
||||
ble_error_t negotiateAttMtu(ble::connection_handle_t connection);
|
||||
|
||||
/**
|
||||
* Register an handler for Handle Value Notification/Indication events.
|
||||
*
|
||||
* @param callback Event handler to register.
|
||||
*
|
||||
* @note It is possible to unregister a callback by using
|
||||
* onHVX().detach(callbackToRemove).
|
||||
*/
|
||||
void onHVX(HVXCallback_t callback);
|
||||
|
||||
void onShutdown(const GattClientShutdownCallback_t& callback);
|
||||
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattClient *));
|
||||
|
||||
GattClientShutdownCallbackChain_t& onShutdown();
|
||||
|
||||
HVXCallbackChain_t& onHVX();
|
||||
|
||||
ble_error_t reset(void);
|
||||
|
||||
/* Entry points for the underlying stack to report events back to the user. */
|
||||
|
||||
void processReadResponse(const GattReadCallbackParams *params);
|
||||
|
||||
void processWriteResponse(const GattWriteCallbackParams *params);
|
||||
|
||||
void processHVXEvent(const GattHVXCallbackParams *params);
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
GattClient(const GattClient &);
|
||||
GattClient& operator=(const GattClient &);
|
||||
|
||||
/* ===================================================================== */
|
||||
/* private implementation follows */
|
||||
|
||||
private:
|
||||
/**
|
||||
* @see ble::PalSigningMonitor::set_signing_event_handler
|
||||
*/
|
||||
void set_signing_event_handler(PalSigningMonitorEventHandler *signing_event_handler);
|
||||
|
||||
/**
|
||||
* @see PalGattClient::EventHandler::on_att_mtu_change
|
||||
*/
|
||||
void on_att_mtu_change(
|
||||
ble::connection_handle_t connection_handle,
|
||||
uint16_t att_mtu_size
|
||||
);
|
||||
|
||||
/**
|
||||
* @see PalGattClient::EventHandler::on_write_command_sent
|
||||
*/
|
||||
void on_write_command_sent(
|
||||
ble::connection_handle_t connection_handle,
|
||||
ble::attribute_handle_t attribute_handle,
|
||||
uint8_t status
|
||||
);
|
||||
|
||||
private:
|
||||
struct ProcedureControlBlock;
|
||||
struct DiscoveryControlBlock;
|
||||
struct ReadControlBlock;
|
||||
struct WriteControlBlock;
|
||||
struct DescriptorDiscoveryControlBlock;
|
||||
|
||||
ProcedureControlBlock* get_control_block(connection_handle_t connection);
|
||||
const ProcedureControlBlock* get_control_block(connection_handle_t connection) const;
|
||||
void insert_control_block(ProcedureControlBlock* cb) const;
|
||||
void remove_control_block(ProcedureControlBlock* cb) const;
|
||||
|
||||
void on_termination(connection_handle_t connection_handle);
|
||||
void on_server_message_received(connection_handle_t, const AttServerMessage&);
|
||||
void on_server_response(connection_handle_t, const AttServerMessage&);
|
||||
void on_server_event(connection_handle_t, const AttServerMessage&);
|
||||
void on_transaction_timeout(connection_handle_t);
|
||||
|
||||
uint16_t get_mtu(connection_handle_t connection) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Event handler provided by the application.
|
||||
*/
|
||||
EventHandler *eventHandler;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered event handlers for data read
|
||||
* events.
|
||||
*/
|
||||
ReadCallbackChain_t onDataReadCallbackChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered event handlers for data write
|
||||
* events.
|
||||
*/
|
||||
WriteCallbackChain_t onDataWriteCallbackChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered event handlers for update
|
||||
* events.
|
||||
*/
|
||||
HVXCallbackChain_t onHVXCallbackChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered event handlers for shutdown
|
||||
* events.
|
||||
*/
|
||||
GattClientShutdownCallbackChain_t shutdownCallChain;
|
||||
|
||||
PalGattClient& _pal_client;
|
||||
ServiceDiscovery::TerminationCallback_t _termination_callback;
|
||||
PalSigningMonitorEventHandler* _signing_event_handler;
|
||||
mutable ProcedureControlBlock* control_blocks;
|
||||
bool _is_reseting;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Create a PalGattClient from a PalGattClient
|
||||
*/
|
||||
GattClient(PalGattClient& pal_client);
|
||||
|
||||
~GattClient() { }
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif /* ifndef IMPL_GATT_CLIENT_H__ */
|
||||
@@ -0,0 +1,381 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef MBED_CORDIO_GATT_SERVER_H__
|
||||
#define MBED_CORDIO_GATT_SERVER_H__
|
||||
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
|
||||
#include "ble/common/ble/GattService.h"
|
||||
#include "ble/common/ble/GattAttribute.h"
|
||||
#include "ble/common/ble/GattServerEvents.h"
|
||||
#include "ble/common/ble/GattCallbackParamTypes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include "ble/common/ble/blecommon.h"
|
||||
#include "ble/Gap.h"
|
||||
#include "wsf_types.h"
|
||||
#include "att_api.h"
|
||||
#include "SecurityManager.h"
|
||||
|
||||
#include "ble/common/ble/GattCallbackParamTypes.h"
|
||||
#include "ble/internal/PalSigningMonitor.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
// fwd declaration of PalAttClient and BLE
|
||||
class PalAttClient;
|
||||
class BLE;
|
||||
|
||||
class GattServer :
|
||||
public ble::interface::GattServer,
|
||||
public PalSigningMonitor
|
||||
{
|
||||
friend ble::BLE;
|
||||
friend ble::PalAttClient;
|
||||
friend PalSigningMonitor;
|
||||
friend BLEInstanceBase;
|
||||
friend PalGenericAccessService;
|
||||
|
||||
// inherited typedefs have the wrong types so we have to redefine them
|
||||
public:
|
||||
|
||||
typedef FunctionPointerWithContext<const GattServer *>
|
||||
GattServerShutdownCallback_t;
|
||||
|
||||
typedef CallChainOfFunctionPointersWithContext<const GattServer*>
|
||||
GattServerShutdownCallbackChain_t;
|
||||
public:
|
||||
|
||||
void setEventHandler(EventHandler *handler);
|
||||
|
||||
ble_error_t reset(void);
|
||||
|
||||
ble_error_t addService(GattService &service);
|
||||
|
||||
ble_error_t read(
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
uint8_t buffer[],
|
||||
uint16_t *lengthP
|
||||
);
|
||||
|
||||
ble_error_t read(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
uint8_t *buffer,
|
||||
uint16_t *lengthP
|
||||
);
|
||||
|
||||
ble_error_t write(
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
const uint8_t *value,
|
||||
uint16_t size,
|
||||
bool localOnly = false
|
||||
);
|
||||
|
||||
ble_error_t write(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
GattAttribute::Handle_t attributeHandle,
|
||||
const uint8_t *value,
|
||||
uint16_t size,
|
||||
bool localOnly = false
|
||||
);
|
||||
|
||||
ble_error_t areUpdatesEnabled(
|
||||
const GattCharacteristic &characteristic,
|
||||
bool *enabledP
|
||||
);
|
||||
|
||||
ble_error_t areUpdatesEnabled(
|
||||
ble::connection_handle_t connectionHandle,
|
||||
const GattCharacteristic &characteristic,
|
||||
bool *enabledP
|
||||
);
|
||||
|
||||
Gap::PreferredConnectionParams_t getPreferredConnectionParams();
|
||||
|
||||
void setPreferredConnectionParams(const Gap::PreferredConnectionParams_t& params);
|
||||
|
||||
bool isOnDataReadAvailable() const;
|
||||
|
||||
void onDataSent(const DataSentCallback_t &callback);
|
||||
|
||||
template <typename T>
|
||||
void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count));
|
||||
|
||||
DataSentCallbackChain_t &onDataSent();
|
||||
|
||||
void onDataWritten(const DataWrittenCallback_t &callback) {
|
||||
dataWrittenCallChain.add(callback);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void onDataWritten(
|
||||
T *objPtr,
|
||||
void (T::*memberPtr)(const GattWriteCallbackParams *context)
|
||||
) {
|
||||
dataWrittenCallChain.add(objPtr, memberPtr);
|
||||
};
|
||||
|
||||
DataWrittenCallbackChain_t &onDataWritten();
|
||||
|
||||
ble_error_t onDataRead(const DataReadCallback_t &callback);
|
||||
|
||||
template <typename T>
|
||||
ble_error_t onDataRead(
|
||||
T *objPtr,
|
||||
void (T::*memberPtr)(const GattReadCallbackParams *context)
|
||||
);
|
||||
|
||||
DataReadCallbackChain_t &onDataRead();
|
||||
|
||||
void onShutdown(const GattServerShutdownCallback_t &callback);
|
||||
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const GattServer *));
|
||||
|
||||
GattServerShutdownCallbackChain_t& onShutdown();
|
||||
|
||||
void onUpdatesEnabled(EventCallback_t callback);
|
||||
|
||||
void onUpdatesDisabled(EventCallback_t callback);
|
||||
|
||||
void onConfirmationReceived(EventCallback_t callback);
|
||||
|
||||
/* Entry points for the underlying stack to report events back to the user. */
|
||||
protected:
|
||||
|
||||
void handleDataWrittenEvent(const GattWriteCallbackParams *params);
|
||||
|
||||
void handleDataReadEvent(const GattReadCallbackParams *params);
|
||||
|
||||
void handleEvent(
|
||||
GattServerEvents::gattEvent_e type,
|
||||
GattAttribute::Handle_t attributeHandle
|
||||
);
|
||||
|
||||
void handleDataSentEvent(unsigned count);
|
||||
|
||||
/* ===================================================================== */
|
||||
/* private implementation follows */
|
||||
|
||||
#if 0 // Disabled until reworked and reintroduced to GattServer API
|
||||
public:
|
||||
/**
|
||||
* @see ble::GattServer::setDeviceName
|
||||
*/
|
||||
ble_error_t setDeviceName(const uint8_t *deviceName);
|
||||
|
||||
/**
|
||||
* @see ble::GattServer::getDeviceName
|
||||
*/
|
||||
void getDeviceName(const uint8_t*& name, uint16_t& length);
|
||||
|
||||
/**
|
||||
* @see ble::GattServer::setAppearance
|
||||
*/
|
||||
void setAppearance(GapAdvertisingData::Appearance appearance);
|
||||
|
||||
/**
|
||||
* @see ble::GattServer::getAppearance
|
||||
*/
|
||||
GapAdvertisingData::Appearance getAppearance();
|
||||
|
||||
#endif // Disabled until reworked and reintroduced to GattServer API
|
||||
|
||||
private:
|
||||
GattServer();
|
||||
|
||||
GattServer(const GattServer &);
|
||||
const GattServer& operator=(const GattServer &);
|
||||
|
||||
/**
|
||||
* Return the singleton of the Cordio implementation of ble::GattServer.
|
||||
*/
|
||||
static GattServer &getInstance();
|
||||
|
||||
/**
|
||||
* Initialize the GattServer and add mandatory services (generic access and
|
||||
* generic attribute service).
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
void set_signing_event_handler(
|
||||
PalSigningMonitorEventHandler *signing_event_handler
|
||||
);
|
||||
|
||||
EventHandler* getEventHandler();
|
||||
|
||||
void add_default_services();
|
||||
|
||||
static uint16_t compute_attributes_count(GattService& service);
|
||||
|
||||
void insert_service_attribute(
|
||||
GattService& service,
|
||||
attsAttr_t *&attribute_it
|
||||
);
|
||||
|
||||
ble_error_t insert_characteristic(
|
||||
GattCharacteristic *characteristic,
|
||||
attsAttr_t *&attribute_it
|
||||
);
|
||||
|
||||
bool is_characteristic_valid(GattCharacteristic *characteristic);
|
||||
|
||||
void insert_characteristic_declaration_attribute(
|
||||
GattCharacteristic *characteristic,
|
||||
attsAttr_t *&attribute_it
|
||||
);
|
||||
|
||||
ble_error_t insert_characteristic_value_attribute(
|
||||
GattCharacteristic *characteristic,
|
||||
attsAttr_t *&attribute_it
|
||||
);
|
||||
|
||||
ble_error_t insert_descriptor(
|
||||
GattCharacteristic *characteristic,
|
||||
GattAttribute* descriptor,
|
||||
attsAttr_t *&attribute_it,
|
||||
bool& cccd_created
|
||||
);
|
||||
|
||||
ble_error_t insert_cccd(
|
||||
GattCharacteristic *characteristic,
|
||||
attsAttr_t *&attribute_it
|
||||
);
|
||||
|
||||
static void cccd_cb(attsCccEvt_t *pEvt);
|
||||
static void att_cb(const attEvt_t *pEvt);
|
||||
static uint8_t atts_read_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr);
|
||||
static uint8_t atts_write_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr);
|
||||
static uint8_t atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle);
|
||||
void add_generic_access_service();
|
||||
void add_generic_attribute_service();
|
||||
void* alloc_block(size_t block_size);
|
||||
GattCharacteristic* get_auth_char(uint16_t value_handle);
|
||||
bool get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const;
|
||||
bool get_cccd_index_by_value_handle(GattAttribute::Handle_t char_handle, uint8_t& idx) const;
|
||||
bool is_update_authorized(connection_handle_t connection, GattAttribute::Handle_t value_handle);
|
||||
|
||||
struct alloc_block_t {
|
||||
alloc_block_t* next;
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
struct internal_service_t {
|
||||
attsGroup_t attGroup;
|
||||
internal_service_t *next;
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* Event handler provided by the application.
|
||||
*/
|
||||
EventHandler *eventHandler;
|
||||
|
||||
/**
|
||||
* The total number of services added to the ATT table.
|
||||
*/
|
||||
uint8_t serviceCount;
|
||||
|
||||
/**
|
||||
* The total number of characteristics added to the ATT table.
|
||||
*/
|
||||
uint8_t characteristicCount;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data sent
|
||||
* events.
|
||||
*/
|
||||
DataSentCallbackChain_t dataSentCallChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data written
|
||||
* events.
|
||||
*/
|
||||
DataWrittenCallbackChain_t dataWrittenCallChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for data read
|
||||
* events.
|
||||
*/
|
||||
DataReadCallbackChain_t dataReadCallChain;
|
||||
|
||||
/**
|
||||
* Callchain containing all registered callback handlers for shutdown
|
||||
* events.
|
||||
*/
|
||||
GattServerShutdownCallbackChain_t shutdownCallChain;
|
||||
|
||||
/**
|
||||
* The registered callback handler for updates enabled events.
|
||||
*/
|
||||
EventCallback_t updatesEnabledCallback;
|
||||
|
||||
/**
|
||||
* The registered callback handler for updates disabled events.
|
||||
*/
|
||||
EventCallback_t updatesDisabledCallback;
|
||||
|
||||
/**
|
||||
* The registered callback handler for confirmation received events.
|
||||
*/
|
||||
EventCallback_t confirmationReceivedCallback;
|
||||
|
||||
PalSigningMonitorEventHandler *_signing_event_handler;
|
||||
|
||||
attsCccSet_t cccds[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT];
|
||||
uint16_t cccd_values[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT];
|
||||
uint16_t cccd_handles[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CCCD_COUNT];
|
||||
uint8_t cccd_cnt;
|
||||
|
||||
GattCharacteristic *_auth_char[MBED_CONF_BLE_API_IMPLEMENTATION_MAX_CHARACTERISTIC_AUTHORISATION_COUNT];
|
||||
uint8_t _auth_char_count;
|
||||
|
||||
struct {
|
||||
attsGroup_t service;
|
||||
attsAttr_t attributes[7];
|
||||
uint8_t device_name_declaration_value[5];
|
||||
uint16_t device_name_length;
|
||||
uint8_t appearance_declaration_value[5];
|
||||
uint16_t appearance;
|
||||
uint8_t ppcp_declaration_value[5];
|
||||
uint8_t ppcp[8];
|
||||
|
||||
uint8_t*& device_name_value() {
|
||||
return attributes[2].pValue;
|
||||
}
|
||||
} generic_access_service;
|
||||
|
||||
struct {
|
||||
attsGroup_t service;
|
||||
attsAttr_t attributes[4];
|
||||
uint8_t service_changed_declaration[5];
|
||||
} generic_attribute_service;
|
||||
|
||||
internal_service_t* registered_service;
|
||||
alloc_block_t* allocated_blocks;
|
||||
|
||||
uint16_t currentHandle;
|
||||
|
||||
bool default_services_added;
|
||||
};
|
||||
|
||||
} // ble
|
||||
|
||||
#endif /* ifndef MBED_CORDIO_GATT_SERVER_H__ */
|
||||
@@ -0,0 +1,639 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef IMPL_SECURITY_MANAGER_H_
|
||||
#define IMPL_SECURITY_MANAGER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "CallChainOfFunctionPointersWithContext.h"
|
||||
#include "platform/Callback.h"
|
||||
|
||||
#include "ble/common/ble/BLETypes.h"
|
||||
#include "ble/common/ble/blecommon.h"
|
||||
#include "ble/Gap.h"
|
||||
|
||||
#include "ble/common/ble/GapTypes.h"
|
||||
#include "ble/common/ble/BLETypes.h"
|
||||
#include "ble/internal/SecurityDb.h"
|
||||
#include "ble/internal/PalConnectionMonitor.h"
|
||||
#include "ble/internal/PalSigningMonitor.h"
|
||||
#include "ble/internal/PalSecurityManager.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
class BLEInstanceBase;
|
||||
|
||||
class SecurityManager :
|
||||
public ble::interface::SecurityManager,
|
||||
public ble::PalSecurityManagerEventHandler,
|
||||
public ble::PalConnectionMonitorEventHandler,
|
||||
public ble::PalSigningMonitorEventHandler
|
||||
{
|
||||
friend class ble::PalConnectionMonitorEventHandler;
|
||||
friend BLEInstanceBase;
|
||||
friend PalGenericAccessService;
|
||||
friend PalSecurityManager;
|
||||
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// SM lifecycle management
|
||||
//
|
||||
|
||||
ble_error_t init(
|
||||
bool enableBonding = true,
|
||||
bool requireMITM = true,
|
||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||
const Passkey_t passkey = NULL,
|
||||
bool signing = true,
|
||||
const char *dbFilepath = NULL
|
||||
);
|
||||
|
||||
ble_error_t setDatabaseFilepath(const char *dbFilepath = NULL);
|
||||
|
||||
ble_error_t reset(void);
|
||||
|
||||
ble_error_t preserveBondingStateOnReset(bool enable);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// List management
|
||||
//
|
||||
|
||||
ble_error_t purgeAllBondingState(void);
|
||||
|
||||
ble_error_t generateWhitelistFromBondTable(::ble::whitelist_t *whitelist) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pairing
|
||||
//
|
||||
|
||||
ble_error_t requestPairing(ble::connection_handle_t connectionHandle);
|
||||
|
||||
ble_error_t acceptPairingRequest(ble::connection_handle_t connectionHandle);
|
||||
|
||||
ble_error_t cancelPairingRequest(ble::connection_handle_t connectionHandle);
|
||||
|
||||
ble_error_t setPairingRequestAuthorisation(bool required = true);
|
||||
|
||||
ble_error_t getPeerIdentity(ble::connection_handle_t connectionHandle);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Feature support
|
||||
//
|
||||
|
||||
ble_error_t allowLegacyPairing(bool allow = true);
|
||||
|
||||
ble_error_t getSecureConnectionsSupport(bool *enabled);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Security settings
|
||||
//
|
||||
|
||||
ble_error_t setIoCapability(SecurityIOCapabilities_t iocaps);
|
||||
|
||||
ble_error_t setDisplayPasskey(const Passkey_t passkey);
|
||||
|
||||
ble_error_t setLinkSecurity(ble::connection_handle_t connectionHandle, SecurityMode_t securityMode);
|
||||
|
||||
ble_error_t setKeypressNotification(bool enabled = true);
|
||||
|
||||
#if BLE_FEATURE_SIGNING
|
||||
|
||||
ble_error_t enableSigning(ble::connection_handle_t connectionHandle, bool enabled = true);
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
|
||||
ble_error_t setHintFutureRoleReversal(bool enable = true);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Encryption
|
||||
//
|
||||
|
||||
ble_error_t getLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t *encryption);
|
||||
|
||||
ble_error_t setLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t encryption);
|
||||
|
||||
ble_error_t setEncryptionKeyRequirements(uint8_t minimumByteSize, uint8_t maximumByteSize);
|
||||
|
||||
ble_error_t getEncryptionKeySize(
|
||||
connection_handle_t connectionHandle,
|
||||
uint8_t *size
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Authentication
|
||||
//
|
||||
|
||||
ble_error_t requestAuthentication(ble::connection_handle_t connectionHandle);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// MITM
|
||||
//
|
||||
|
||||
ble_error_t generateOOB(const ble::address_t *address);
|
||||
|
||||
ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true);
|
||||
|
||||
ble_error_t confirmationEntered(ble::connection_handle_t connectionHandle, bool confirmation);
|
||||
|
||||
ble_error_t passkeyEntered(ble::connection_handle_t connectionHandle, Passkey_t passkey);
|
||||
|
||||
ble_error_t sendKeypressNotification(ble::connection_handle_t connectionHandle, ble::Keypress_t keypress);
|
||||
|
||||
ble_error_t legacyPairingOobReceived(const ble::address_t *address, const ble::oob_tk_t *tk);
|
||||
|
||||
ble_error_t oobReceived(const ble::address_t *address, const ble::oob_lesc_value_t *random, const ble::oob_confirm_t *confirm);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
//
|
||||
|
||||
ble_error_t getSigningKey(ble::connection_handle_t connectionHandle, bool authenticated);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Privacy
|
||||
//
|
||||
|
||||
ble_error_t setPrivateAddressTimeout(
|
||||
uint16_t timeout_in_seconds
|
||||
);
|
||||
|
||||
/* Event callback handlers. */
|
||||
public:
|
||||
|
||||
void onShutdown(const SecurityManagerShutdownCallback_t& callback);
|
||||
|
||||
template <typename T>
|
||||
void onShutdown(T *objPtr, void (T::*memberPtr)(const SecurityManager *));
|
||||
|
||||
SecurityManagerShutdownCallbackChain_t& onShutdown();
|
||||
|
||||
void setSecurityManagerEventHandler(EventHandler* handler);
|
||||
|
||||
/* ===================================================================== */
|
||||
/* private implementation follows */
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the time after which an event will be generated unless we received a packet with
|
||||
* a valid MIC.
|
||||
*
|
||||
* @param[in] connectionHandle Handle to identify the connection.
|
||||
* @param[in] timeout_in_ms Timeout to set.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t setAuthenticationTimeout(
|
||||
connection_handle_t connection,
|
||||
uint32_t timeout_in_ms
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the time after which an event will be generated unless we received a packet with
|
||||
* a valid MIC.
|
||||
*
|
||||
* @param[in] connectionHandle Handle to identify the connection.
|
||||
* @param[in] timeout_in_ms Returns the timeout.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t getAuthenticationTimeout(
|
||||
connection_handle_t connection,
|
||||
uint32_t *timeout_in_ms
|
||||
);
|
||||
|
||||
/* implements PalSecurityManager::EventHandler */
|
||||
private:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pairing
|
||||
//
|
||||
|
||||
/** @copydoc PalSecurityManager::on_pairing_request
|
||||
*/
|
||||
void on_pairing_request(
|
||||
connection_handle_t connection,
|
||||
bool use_oob,
|
||||
AuthenticationMask authentication,
|
||||
KeyDistribution initiator_dist,
|
||||
KeyDistribution responder_dist
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_pairing_error
|
||||
*/
|
||||
void on_pairing_error(
|
||||
connection_handle_t connection,
|
||||
pairing_failure_t error
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_pairing_timed_out
|
||||
*/
|
||||
void on_pairing_timed_out(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_pairing_completed
|
||||
*/
|
||||
void on_pairing_completed(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Security
|
||||
//
|
||||
|
||||
/** @copydoc PalSecurityManager::on_valid_mic_timeout
|
||||
*/
|
||||
void on_valid_mic_timeout(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_signed_write_received
|
||||
*/
|
||||
void on_signed_write_received(
|
||||
connection_handle_t connection,
|
||||
uint32_t sign_coutner
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_signed_write_verification_failure
|
||||
*/
|
||||
void on_signed_write_verification_failure(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_signed_write
|
||||
*/
|
||||
void on_signed_write();
|
||||
|
||||
/** @copydoc PalSecurityManager::on_slave_security_request
|
||||
*/
|
||||
void on_slave_security_request(
|
||||
connection_handle_t connection,
|
||||
AuthenticationMask authentication
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Encryption
|
||||
//
|
||||
|
||||
/** @copydoc PalSecurityManager::on_link_encryption_result
|
||||
*/
|
||||
void on_link_encryption_result(
|
||||
connection_handle_t connection,
|
||||
link_encryption_t result
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_link_encryption_request_timed_out
|
||||
*/
|
||||
void on_link_encryption_request_timed_out(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// MITM
|
||||
//
|
||||
|
||||
/** @copydoc PalSecurityManager::on_passkey_display
|
||||
*/
|
||||
void on_passkey_display(
|
||||
connection_handle_t connection,
|
||||
passkey_num_t passkey
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keypress_notification
|
||||
*/
|
||||
void on_keypress_notification(
|
||||
connection_handle_t connection,
|
||||
ble::Keypress_t keypress
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_passkey_request
|
||||
*/
|
||||
void on_passkey_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_confirmation_request
|
||||
*/
|
||||
void on_confirmation_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_secure_connections_oob_request
|
||||
*/
|
||||
void on_secure_connections_oob_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_legacy_pairing_oob_request
|
||||
*/
|
||||
void on_legacy_pairing_oob_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_secure_connections_oob_generated
|
||||
*/
|
||||
void on_secure_connections_oob_generated(
|
||||
const oob_lesc_value_t &random,
|
||||
const oob_confirm_t &confirm
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
//
|
||||
|
||||
/** @copydoc PalSecurityManager::on_secure_connections_ltk_generated
|
||||
*/
|
||||
void on_secure_connections_ltk_generated(
|
||||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_ltk
|
||||
*/
|
||||
void on_keys_distributed_ltk(
|
||||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_ediv_rand
|
||||
*/
|
||||
void on_keys_distributed_ediv_rand(
|
||||
connection_handle_t connection,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_local_ltk
|
||||
*/
|
||||
void on_keys_distributed_local_ltk(
|
||||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_local_ediv_rand
|
||||
*/
|
||||
void on_keys_distributed_local_ediv_rand(
|
||||
connection_handle_t connection,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_irk
|
||||
*/
|
||||
void on_keys_distributed_irk(
|
||||
connection_handle_t connection,
|
||||
const irk_t &irk
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_bdaddr
|
||||
*/
|
||||
void on_keys_distributed_bdaddr(
|
||||
connection_handle_t connection,
|
||||
advertising_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_keys_distributed_csrk
|
||||
*/
|
||||
void on_keys_distributed_csrk(
|
||||
connection_handle_t connection,
|
||||
const csrk_t &csrk
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_ltk_requeston_ltk_request
|
||||
*/
|
||||
void on_ltk_request(
|
||||
connection_handle_t connection,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
);
|
||||
|
||||
/** @copydoc PalSecurityManager::on_ltk_requeston_ltk_request
|
||||
*/
|
||||
void on_ltk_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
/* end implements PalSecurityManager::EventHandler */
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
SecurityManager(const SecurityManager &);
|
||||
SecurityManager& operator=(const SecurityManager &);
|
||||
|
||||
SecurityManager(
|
||||
PalSecurityManager &palImpl,
|
||||
PalConnectionMonitor &connMonitorImpl,
|
||||
PalSigningMonitor &signingMonitorImpl
|
||||
) : _pal(palImpl),
|
||||
_connection_monitor(connMonitorImpl),
|
||||
_signing_monitor(signingMonitorImpl),
|
||||
_db(NULL),
|
||||
_default_authentication(0),
|
||||
_default_key_distribution(KeyDistribution::KEY_DISTRIBUTION_ALL),
|
||||
_pairing_authorisation_required(false),
|
||||
_legacy_pairing_allowed(true),
|
||||
_master_sends_keys(false),
|
||||
eventHandler(NULL)
|
||||
{
|
||||
eventHandler = &defaultEventHandler;
|
||||
_pal.set_event_handler(this);
|
||||
|
||||
/* We create a fake value for oob to allow creation of the next oob which needs
|
||||
* the last process to finish first before restarting (this is to simplify checking).
|
||||
* This fake value will not be used as the oob address is currently invalid */
|
||||
_oob_local_random[0] = 1;
|
||||
}
|
||||
|
||||
~SecurityManager()
|
||||
{
|
||||
delete _db;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions
|
||||
//
|
||||
|
||||
private:
|
||||
|
||||
ble_error_t init_database(const char *db_path = NULL);
|
||||
|
||||
ble_error_t init_resolving_list();
|
||||
|
||||
ble_error_t init_signing();
|
||||
|
||||
ble_error_t init_identity();
|
||||
|
||||
ble_error_t get_random_data(
|
||||
uint8_t *buffer,
|
||||
size_t size
|
||||
);
|
||||
|
||||
ble_error_t slave_security_request(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
ble_error_t enable_encryption(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
void enable_encryption_cb(
|
||||
ble::SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
);
|
||||
|
||||
void set_ltk_cb(
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
);
|
||||
|
||||
void return_csrk_cb(
|
||||
SecurityDb::entry_handle_t connection,
|
||||
const SecurityEntrySigning_t *signing
|
||||
);
|
||||
|
||||
void set_peer_csrk_cb(
|
||||
SecurityDb::entry_handle_t connection,
|
||||
const SecurityEntrySigning_t *signing
|
||||
);
|
||||
|
||||
void update_oob_presence(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
void set_mitm_performed(
|
||||
connection_handle_t connection,
|
||||
bool enable = true
|
||||
);
|
||||
|
||||
void on_connected(
|
||||
connection_handle_t connection,
|
||||
connection_role_t role,
|
||||
peer_address_type_t peer_address_type,
|
||||
address_t peer_address,
|
||||
own_address_type_t local_address_type,
|
||||
address_t local_address
|
||||
);
|
||||
|
||||
void on_disconnected(
|
||||
connection_handle_t connection,
|
||||
disconnection_reason_t reason
|
||||
);
|
||||
|
||||
void on_security_entry_retrieved(
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryIdentity_t* identity
|
||||
);
|
||||
|
||||
void on_identity_list_retrieved(
|
||||
Span<SecurityEntryIdentity_t>& identity_list,
|
||||
size_t count
|
||||
);
|
||||
|
||||
private:
|
||||
struct ControlBlock_t {
|
||||
ControlBlock_t();
|
||||
|
||||
KeyDistribution get_initiator_key_distribution() {
|
||||
return KeyDistribution(initiator_key_distribution);
|
||||
};
|
||||
KeyDistribution get_responder_key_distribution() {
|
||||
return KeyDistribution(responder_key_distribution);
|
||||
};
|
||||
void set_initiator_key_distribution(KeyDistribution mask) {
|
||||
initiator_key_distribution = mask.value();
|
||||
};
|
||||
void set_responder_key_distribution(KeyDistribution mask) {
|
||||
responder_key_distribution = mask.value();
|
||||
};
|
||||
|
||||
connection_handle_t connection;
|
||||
SecurityDb::entry_handle_t db_entry;
|
||||
|
||||
address_t local_address; /**< address used for connection, possibly different from identity */
|
||||
|
||||
private:
|
||||
uint8_t initiator_key_distribution:4;
|
||||
uint8_t responder_key_distribution:4;
|
||||
public:
|
||||
uint8_t connected:1;
|
||||
uint8_t authenticated:1; /**< have we turned encryption on during this connection */
|
||||
uint8_t is_master:1;
|
||||
|
||||
uint8_t encryption_requested:1;
|
||||
uint8_t encryption_failed:1;
|
||||
uint8_t encrypted:1;
|
||||
uint8_t signing_requested:1;
|
||||
uint8_t signing_override_default:1;
|
||||
|
||||
uint8_t mitm_requested:1;
|
||||
uint8_t mitm_performed:1; /**< keys exchange will have MITM protection */
|
||||
|
||||
uint8_t attempt_oob:1;
|
||||
uint8_t oob_mitm_protection:1;
|
||||
uint8_t oob_present:1;
|
||||
uint8_t legacy_pairing_oob_request_pending:1;
|
||||
|
||||
uint8_t csrk_failures:2;
|
||||
};
|
||||
|
||||
/* list management */
|
||||
|
||||
ControlBlock_t* acquire_control_block(connection_handle_t connection);
|
||||
|
||||
ControlBlock_t* get_control_block(connection_handle_t connection);
|
||||
|
||||
ControlBlock_t* get_control_block(const address_t &peer_address);
|
||||
|
||||
ControlBlock_t* get_control_block(SecurityDb::entry_handle_t db_entry);
|
||||
|
||||
void release_control_block(ControlBlock_t* entry);
|
||||
|
||||
private:
|
||||
SecurityManagerShutdownCallbackChain_t shutdownCallChain;
|
||||
EventHandler* eventHandler;
|
||||
EventHandler defaultEventHandler;
|
||||
|
||||
PalSecurityManager &_pal;
|
||||
PalConnectionMonitor &_connection_monitor;
|
||||
PalSigningMonitor &_signing_monitor;
|
||||
|
||||
SecurityDb *_db;
|
||||
|
||||
/* OOB data */
|
||||
address_t _oob_local_address;
|
||||
address_t _oob_peer_address;
|
||||
oob_lesc_value_t _oob_peer_random;
|
||||
oob_confirm_t _oob_peer_confirm;
|
||||
oob_lesc_value_t _oob_local_random;
|
||||
address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */
|
||||
oob_tk_t _oob_temporary_key; /**< used for legacy pairing */
|
||||
|
||||
AuthenticationMask _default_authentication;
|
||||
KeyDistribution _default_key_distribution;
|
||||
|
||||
bool _pairing_authorisation_required;
|
||||
bool _legacy_pairing_allowed;
|
||||
bool _master_sends_keys;
|
||||
|
||||
static const size_t MAX_CONTROL_BLOCKS = 5;
|
||||
ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS];
|
||||
};
|
||||
|
||||
} // ble
|
||||
|
||||
#endif /*IMPL_SECURITY_MANAGER_H_*/
|
||||
Reference in New Issue
Block a user