mbed-os/features/FEATURE_BLE/source/Gap.cpp

626 lines
18 KiB
C++

/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* 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/Gap.h"
namespace {
ble_error_t convert_address_type(
Gap::PeerAddressType_t input_type,
const BLEProtocol::AddressBytes_t address,
BLEProtocol::AddressType_t& output_type
) {
typedef Gap::RandomAddressType_t RandomAddressType_t;
typedef Gap::PeerAddressType_t PeerAddressType_t;
typedef BLEProtocol::AddressType LegacyAddressType_t;
// best effort; peerAddrTypeIn should not be used when privacy is on.
switch(input_type.value()) {
case PeerAddressType_t::PUBLIC:
case PeerAddressType_t::PUBLIC_IDENTITY:
output_type = LegacyAddressType_t::PUBLIC;
break;
case PeerAddressType_t::RANDOM: {
RandomAddressType_t random_address_type(RandomAddressType_t::STATIC);
ble_error_t err = Gap::getRandomAddressType(address, &random_address_type);
if (err) {
return err;
}
switch (random_address_type.value()) {
case RandomAddressType_t::STATIC:
output_type = LegacyAddressType_t::RANDOM_STATIC;
break;
case RandomAddressType_t::NON_RESOLVABLE_PRIVATE:
output_type = LegacyAddressType_t::RANDOM_PRIVATE_NON_RESOLVABLE;
break;
case RandomAddressType_t::RESOLVABLE_PRIVATE:
output_type = LegacyAddressType_t::RANDOM_PRIVATE_RESOLVABLE;
break;
}
break;
}
case PeerAddressType_t::RANDOM_STATIC_IDENTITY:
output_type = LegacyAddressType_t::RANDOM_STATIC;
break;
}
return BLE_ERROR_NONE;
}
Gap::PeerAddressType_t convert_legacy_address_type(
BLEProtocol::AddressType_t legacy_address
) {
if (legacy_address == BLEProtocol::AddressType::PUBLIC) {
return Gap::PeerAddressType_t::PUBLIC;
} else {
return Gap::PeerAddressType_t::RANDOM;
}
}
}
uint8_t Gap::getMaxAdvertisingSetNumber()
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return 1;
}
uint8_t Gap::getMaxAdvertisingDataLength()
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return 0x1F;
}
ble_error_t Gap::createAdvertisingSet(
ble::advertising_handle_t *handle,
const ble::AdvertisingParameters &parameters
)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::destroyAdvertisingSet(ble::advertising_handle_t handle)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setAdvertisingParameters(
ble::advertising_handle_t handle,
const ble::AdvertisingParameters &params
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setAdvertisingPayload(
ble::advertising_handle_t handle,
mbed::Span<uint8_t> payload,
bool minimiseFragmentation
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setAdvertisingScanResponse(
ble::advertising_handle_t handle,
mbed::Span<uint8_t> response,
bool minimiseFragmentation
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::startAdvertising(
ble::advertising_handle_t handle,
ble::adv_duration_t maxDuration,
uint8_t maxEvents
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::stopAdvertising(ble::advertising_handle_t handle)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
bool Gap::isAdvertisingActive(ble::advertising_handle_t handle) {
return false;
}
ble_error_t Gap::setPeriodicAdvertisingParameters(
ble::advertising_handle_t handle,
ble::periodic_interval_t periodicAdvertisingIntervalMin,
ble::periodic_interval_t periodicAdvertisingIntervalMax,
bool advertiseTxPower
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setPeriodicAdvertisingPayload(
ble::advertising_handle_t handle,
mbed::Span<uint8_t> payload
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::startPeriodicAdvertising(ble::advertising_handle_t handle)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::stopPeriodicAdvertising(ble::advertising_handle_t handle)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
bool Gap::isPeriodicAdvertisingActive(ble::advertising_handle_t handle)
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return false;
}
ble_error_t Gap::setScanParameters(const ble::ScanParameters& params)
{
useVersionTwoAPI();
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
};
ble_error_t Gap::startScan(
ble::duplicates_filter_t filtering,
ble::scan_duration_t duration,
ble::scan_period_t period
) {
useVersionTwoAPI();
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
};
ble_error_t Gap::createSync(
ble::peer_address_type_t peerAddressType,
const ble::address_t &peerAddress,
uint8_t sid,
ble::slave_latency_t maxPacketSkip,
ble::sync_timeout_t timeout
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::createSync(
ble::slave_latency_t maxPacketSkip,
ble::sync_timeout_t timeout
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::cancelCreateSync()
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::terminateSync(ble::periodic_sync_handle_t handle) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::addDeviceToPeriodicAdvertiserList(
ble::peer_address_type_t peerAddressType,
const ble::address_t &peerAddress,
ble::advertising_sid_t sid
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::removeDeviceFromPeriodicAdvertiserList(
ble::peer_address_type_t peerAddressType,
const ble::address_t &peerAddress,
ble::advertising_sid_t sid
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::clearPeriodicAdvertiserList()
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
uint8_t Gap::getMaxPeriodicAdvertiserListSize()
{
/* Requesting action from porter(s): override this API if this capability is supported. */
return 0;
}
ble_error_t Gap::connect(
ble::target_peer_address_type_t peerAddressType,
const ble::address_t &peerAddress,
const ble::ConnectionParameters &connectionParams
) {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::cancelConnect() {
/* Requesting action from porter(s): override this API if this capability is supported. */
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::updateConnectionParameters(
ble::connection_handle_t connectionHandle,
ble::conn_interval_t minConnectionInterval,
ble::conn_interval_t maxConnectionInterval,
ble::slave_latency_t slaveLatency,
ble::supervision_timeout_t supervision_timeout,
ble::conn_event_length_t minConnectionEventLength,
ble::conn_event_length_t maxConnectionEventLength
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::manageConnectionParametersUpdateRequest(
bool userManageConnectionUpdateRequest
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::acceptConnectionParametersUpdate(
ble::connection_handle_t connectionHandle,
ble::conn_interval_t minConnectionInterval,
ble::conn_interval_t maxConnectionInterval,
ble::slave_latency_t slaveLatency,
ble::supervision_timeout_t supervision_timeout,
ble::conn_event_length_t minConnectionEventLength,
ble::conn_event_length_t maxConnectionEventLength
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::rejectConnectionParametersUpdate(
ble::connection_handle_t connectionHandle
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::disconnect(
ble::connection_handle_t connectionHandle,
ble::local_disconnection_reason_t reason
) {
// Forward to the old implementation for now.
return disconnect(connectionHandle, (Gap::DisconnectionReason_t) reason.value());
}
ble_error_t Gap::readPhy(ble::connection_handle_t connection)
{
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setPreferredPhys(
const ble::phy_set_t *txPhys,
const ble::phy_set_t *rxPhys
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setPhy(
ble::connection_handle_t connection,
const ble::phy_set_t *txPhys,
const ble::phy_set_t *rxPhys,
ble::coded_symbol_per_bit_t codedSymbol
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
uint8_t Gap::getMaxWhitelistSize(void) const
{
return 0;
}
ble_error_t Gap::getWhitelist(Whitelist_t &whitelist) const
{
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t Gap::setWhitelist(const Whitelist_t &whitelist)
{
return BLE_ERROR_NOT_IMPLEMENTED;
}
const Gap::PeripheralPrivacyConfiguration_t Gap::default_peripheral_privacy_configuration = {
/* use_non_resolvable_random_address */ false,
/* resolution_strategy */ PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE
};
const Gap::CentralPrivacyConfiguration_t Gap::default_central_privacy_configuration = {
/* use_non_resolvable_random_address */ false,
/* resolution_strategy */ CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
};
void Gap::processConnectionEvent(
Handle_t handle,
Role_t role,
PeerAddressType_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams,
const uint8_t *peerResolvableAddr,
const uint8_t *localResolvableAddr
) {
/* Update Gap state */
state.advertising = 0;
state.connected = 1;
++connectionCount;
ConnectionCallbackParams_t callbackParams(
handle,
role,
peerAddrType,
peerAddr,
ownAddrType,
ownAddr,
connectionParams,
peerResolvableAddr,
localResolvableAddr
);
connectionCallChain.call(&callbackParams);
}
void Gap::processAdvertisementReport(
const BLEProtocol::AddressBytes_t peerAddr,
int8_t rssi,
bool isScanResponse,
GapAdvertisingParams::AdvertisingType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData,
PeerAddressType_t addressType
) {
AdvertisementCallbackParams_t params;
memcpy(params.peerAddr, peerAddr, ADDR_LEN);
params.rssi = rssi;
params.isScanResponse = isScanResponse;
params.type = type;
params.advertisingDataLen = advertisingDataLen;
params.advertisingData = advertisingData;
params.peerAddrType = addressType;
convert_address_type(
addressType,
peerAddr,
params.addressType
);
onAdvertisementReport.call(&params);
}
#if defined(__GNUC__) && !defined(__CC_ARM)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__CC_ARM)
#pragma push
#pragma diag_suppress 1361
#endif
Gap::AdvertisementCallbackParams_t::AdvertisementCallbackParams_t() :
peerAddr(),
rssi(),
isScanResponse(),
type(),
advertisingDataLen(0),
advertisingData(NULL),
addressType(),
peerAddrType(PeerAddressType_t::PUBLIC)
{
}
ble_error_t Gap::getRandomAddressType(
const BLEProtocol::AddressBytes_t address,
RandomAddressType_t* type
) {
// see section Device address in Bluetooth Link Layer specification
// (Vol 6 - Part B)
switch (address[5] >> 6) {
case 0x03:
*type = RandomAddressType_t::STATIC;
return BLE_ERROR_NONE;
case 0x00:
*type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE;
return BLE_ERROR_NONE;
case 0x01:
*type = RandomAddressType_t::RESOLVABLE_PRIVATE;
return BLE_ERROR_NONE;
default:
return BLE_ERROR_INVALID_PARAM;
}
}
Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t(
Handle_t handleIn,
Role_t roleIn,
BLEProtocol::AddressType_t peerAddrTypeIn,
const uint8_t *peerAddrIn,
BLEProtocol::AddressType_t ownAddrTypeIn,
const uint8_t *ownAddrIn,
const ConnectionParams_t *connectionParamsIn,
const uint8_t *peerResolvableAddrIn,
const uint8_t *localResolvableAddrIn
) : handle(handleIn),
role(roleIn),
peerAddrType(peerAddrTypeIn),
peerAddr(),
ownAddrType(ownAddrTypeIn),
ownAddr(),
connectionParams(connectionParamsIn),
peerResolvableAddr(),
localResolvableAddr(),
peerAddressType(convert_legacy_address_type(peerAddrTypeIn))
{
constructor_helper(
peerAddrIn,
ownAddrIn,
peerResolvableAddrIn,
localResolvableAddrIn
);
}
Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t(
Handle_t handleIn,
Role_t roleIn,
PeerAddressType_t peerAddrTypeIn,
const uint8_t *peerAddrIn,
BLEProtocol::AddressType_t ownAddrTypeIn,
const uint8_t *ownAddrIn,
const ConnectionParams_t *connectionParamsIn,
const uint8_t *peerResolvableAddrIn,
const uint8_t *localResolvableAddrIn
) : handle(handleIn),
role(roleIn),
peerAddrType(),
peerAddr(),
ownAddrType(ownAddrTypeIn),
ownAddr(),
connectionParams(connectionParamsIn),
peerResolvableAddr(),
localResolvableAddr(),
peerAddressType(peerAddrTypeIn)
{
constructor_helper(
peerAddrIn,
ownAddrIn,
peerResolvableAddrIn,
localResolvableAddrIn
);
convert_address_type(peerAddrTypeIn, peerAddrIn, peerAddrType);
}
void Gap::ConnectionCallbackParams_t::constructor_helper(
const uint8_t *peerAddrIn,
const uint8_t *ownAddrIn,
const uint8_t *peerResolvableAddrIn,
const uint8_t *localResolvableAddrIn
) {
memcpy(peerAddr, peerAddrIn, ADDR_LEN);
if (ownAddrIn) {
memcpy(ownAddr, ownAddrIn, ADDR_LEN);
} else {
memset(ownAddr, 0, ADDR_LEN);
}
if (peerResolvableAddrIn) {
memcpy(peerResolvableAddr, peerResolvableAddrIn, ADDR_LEN);
} else {
memset(ownAddr, 0, ADDR_LEN);
}
if (localResolvableAddrIn) {
memcpy(localResolvableAddr, localResolvableAddrIn, ADDR_LEN);
} else {
memset(ownAddr, 0, ADDR_LEN);
}
}
ble_error_t Gap::connect(
const BLEProtocol::AddressBytes_t peerAddr,
DeprecatedAddressType_t peerAddrType,
const ConnectionParams_t *connectionParams,
const GapScanningParams *scanParams
) {
return connect(
peerAddr,
(BLEProtocol::AddressType_t) peerAddrType,
connectionParams,
scanParams
);
}
void Gap::processConnectionEvent(
Handle_t handle,
Role_t role,
BLEProtocol::AddressType_t peerAddrType,
const BLEProtocol::AddressBytes_t peerAddr,
BLEProtocol::AddressType_t ownAddrType,
const BLEProtocol::AddressBytes_t ownAddr,
const ConnectionParams_t *connectionParams,
const uint8_t *peerResolvableAddr,
const uint8_t *localResolvableAddr
) {
/* Update Gap state */
state.advertising = 0;
state.connected = 1;
++connectionCount;
ConnectionCallbackParams_t callbackParams(
handle,
role,
peerAddrType,
peerAddr,
ownAddrType,
ownAddr,
connectionParams,
peerResolvableAddr,
localResolvableAddr
);
connectionCallChain.call(&callbackParams);
}
void Gap::processAdvertisementReport(
const BLEProtocol::AddressBytes_t peerAddr,
int8_t rssi,
bool isScanResponse,
GapAdvertisingParams::AdvertisingType_t type,
uint8_t advertisingDataLen,
const uint8_t *advertisingData,
BLEProtocol::AddressType_t addressType
) {
AdvertisementCallbackParams_t params;
memcpy(params.peerAddr, peerAddr, ADDR_LEN);
params.rssi = rssi;
params.isScanResponse = isScanResponse;
params.type = type;
params.advertisingDataLen = advertisingDataLen;
params.advertisingData = advertisingData;
params.addressType = addressType;
params.peerAddrType = convert_legacy_address_type(addressType);
onAdvertisementReport.call(&params);
}
#if defined(__GNUC__) && !defined(__CC_ARM)
#pragma GCC diagnostic pop
#elif defined(__CC_ARM)
#pragma pop
#endif