From 4deb64aed1459d5893b97b3f1f70e82e7ad2cdca Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Jul 2018 11:54:33 +0100 Subject: [PATCH 01/14] Merge pull request #1 from pan-/PHY_API Phy api --- features/FEATURE_BLE/ble/BLETypes.h | 104 ++++++++++++++++++ features/FEATURE_BLE/ble/Gap.h | 163 +++++++++++++++++++++++++++- 2 files changed, 266 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 7e57b17e2d..f30a4da2d0 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -572,6 +572,110 @@ struct peer_address_type_t :SafeEnum { SafeEnum(PUBLIC) { } }; +/** + * Type that describes a bluetooth PHY(sical) transport. + */ +struct phy_t : SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + /** + * 1Mbit/s LE. + * + * @note This physical transport was available since Bluetooth 4.0 + */ + LE_1M = 1, + + /** + * 2Mbit/s LE. + * + * Modulation is similar to LE_1M but differs in rate. Therefore range + * performances are in the same ballpark as LE_1M while the increased rate + * minimize time spent to transfer or receive a packet which leads to a + * better power consumption and/or faster transfer. + * + * @note This transport has been introduced with the Bluetooth 5. + * @note When operating at 2Mbit/s range is not exactly identical to the + * range at 1Mbit/s due to a loss in sensitivity. + */ + LE_2M = 2, + + /** + * LE Coded PHY. + * + * This transport reuse the 1Mbit/s channel with different coding schemes. + * Either two (S=2) or eight (S=8) symbols can be used to represent a + * bit while the 1Mbit/s transport use 1 symbol to code 1 bit of data. + * + * Here is the data rate of the two coding schemes: + * - S=2: 500kbit/s + * - S=8: 125kbit/s + * + * The goal of the coded PHY is to increase the range of BLE devices. + * Of course given it takes more time to transfer data, transmission + * and reception last longer which leads to an increase in power + * consumption. + * + * @note This transport has been introduced with the Bluetooth 5. + */ + LE_CODED + }; + + /** + * Construct a new instance of phy_t. + */ + phy_t(type value) : + SafeEnum(value) { } +}; + +/** + * Type that describe a set of PHY(sical) transports. + */ +struct phys_t { + /** + * If equal to 1 then the set includes phy_t::LE_1M. + */ + uint8_t le_1m:1; + + /** + * If equal to 1 then the set includes phy_t::LE_2M. + */ + uint8_t le_2m:1; + + /** + * If equal to 1 then the set includes phy_t::LE_CODED. + */ + uint8_t le_coded:1; +}; + +/** + * Type describing the number of symbols per bit in le coded PHY. + */ +struct coded_symbol_per_bit_t :SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + /** + * The Number of symbol used to code a bit is undefined. + */ + UNDEFINED, + + /** + * Two symbols to code a bit. + */ + S2, + + /** + * Eight symbols to code a bit. + */ + S8 + }; + + /** + * Construct a new instance of coded_symbol_per_bit_t. + */ + coded_symbol_per_bit_t(type value) : + SafeEnum(value) { } +}; + } // namespace ble /** diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index e3b3518d63..d1397f8d74 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -533,6 +533,21 @@ public: */ typedef ble::peer_address_type_t PeerAddressType_t; + /** + * Enumeration of BLE PHY + */ + typedef ble::phy_t Phy_t; + + /** + * Set of BLE PHYs + */ + typedef ble::phys_t Phys_t; + + /** + * Enumeration of type of symbols that can be used with LE coded PHY. + */ + typedef ble::coded_symbol_per_bit_t CodedSymbolPerBit_t; + /** * Parameters of a BLE connection. */ @@ -1071,6 +1086,68 @@ public: typedef CallChainOfFunctionPointersWithContext GapShutdownCallbackChain_t; + + /** + * Definition of the general handler of Gap related events. + */ + struct EventHandler { + /** + * Function invoked when the current transmitter and receiver PHY have + * been read for a given connection. + * + * @param status Status of the operation: BLE_ERROR_NONE in case of + * success or an appropriate error code. + * + * @param connectionHandle: The handle of the connection for which the + * PHYs have been read. + * + * @param txPhy PHY used by the transmitter. + * + * @param rxPhy PHY used by the receiver. + */ + virtual void onPhyRead( + ble_error_t status, + Handle_t connectionHandle, + ble::phy_t txPhy, + ble::phy_t rxPhy + ) = 0; + + /** + * Function invoked when the update process of the PHY has been completed. + * + * The process can be initiated by a call to the function setPhy, the + * local bluetooth subsystem or the peer. + * + * @param status Status of the operation: BLE_ERROR_NONE in case of + * success or an appropriate error code. + * + * @param connectionHandle: The handle of the connection on which the + * operation was made. + * + * @param txPhy PHY used by the transmitter. + * + * @param rxPhy PHY used by the receiver. + * + * @note Success doesn't mean the PHY has been updated it means both + * ends have negociated the best phy according to their configuration and + * capabilities. The PHY currently used are present in the txPhy and + * rxPhy parameters. + */ + virtual void onPhyUpdateComplete( + ble_error_t status, + Handle_t connectionHandle, + ble::phy_t txPhy, + ble::phy_t rxPhy + ) = 0; + + protected: + /** + * Prevent polymorphic deletion and avoid uncessery virtual destructor + * as the Gap class will never delete the instance it contains. + */ + ~EventHandler() { } + }; + /* * The following functions are meant to be overridden in the platform-specific subclass. */ @@ -1331,6 +1408,72 @@ public: const GapScanningParams *scanParams ); + /** + * Read the PHY used by the transmitter and the receiver on a connection. + * + * Once the PHY has been read, it is reported back via the function onPhyRead + * of the event handler registered by the application. + * + * @param connection Handle of the connection for which the PHY being used is + * queried. + * + * @return BLE_ERROR_NONE if the read PHY procedure has been started or an + * appropriate error code. + */ + virtual ble_error_t readPhy(Handle_t connection) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Set the prefered PHYs to use in a connection. + * + * @param txPhy: Set of PHYs prefered for tx operations. If NULL then no + * prefered PHYs are set and the default value of the subsytem is used. + * + * @param rxPhy: Set of PHYs prefered for rx operations. If NULL then no + * prefered PHYs are set and the default value of the subsytem is used. + * + * @return BLE_ERROR_NONE if the preferences have been set or an appropriate + * error code. + */ + virtual ble_error_t setPreferedPhys( + const Phys_t* txPhys, + const Phys_t* rxPhys + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Update the PHY used by a connection. + * + * Once the update process has been completed, it is reported back to the + * application via the function onPhyUpdateComplete of the event handler + * registered by the application. + * + * @param connection Handle of the connection to update. + * + * @param txPhys Set of PHYs prefered for tx operations. If NULL then the + * choice is up to the Bluetooth subsystem. + * + * @param rxPhys Set of PHYs prefered for rx operations. If NULL then the + * choice is up to the Bluetooth subsystem. + * + * @param codedSymbol Number of symbols used to code a bit when le coded is + * used. If the value is UNDEFINED then the choice is up to the Bluetooth + * subsystem. + * + * @return BLE_ERROR_NONE if the update PHY procedure has been successfully + * started or an error code. + */ + virtual ble_error_t setPhy( + Handle_t connection, + const Phys_t* txPhys, + const Phys_t* rxPhys, + CodedSymbolPerBit_t codedSymbol + ) { + return BLE_ERROR_NONE; + } + /** * Initiate a disconnection procedure. * @@ -2446,6 +2589,17 @@ public: /* Event handlers. */ public: + + /** + * Assign the event handler implementation that will be used by the gap + * module to signal events back to the application. + * + * @param handler Application implementation of an Eventhandler. + */ + void setEventHandler(EventHandler* handler) { + _eventHandler = handler; + } + /** * Register a callback handling timeout events. * @@ -2674,6 +2828,7 @@ public: disconnectionCallChain.clear(); radioNotificationCallback = NULL; onAdvertisementReport = NULL; + _eventHandler = NULL; return BLE_ERROR_NONE; } @@ -2694,7 +2849,8 @@ protected: radioNotificationCallback(), onAdvertisementReport(), connectionCallChain(), - disconnectionCallChain() { + disconnectionCallChain(), + _eventHandler(NULL) { _advPayload.clear(); _scanResponse.clear(); } @@ -2938,6 +3094,11 @@ protected: */ DisconnectionEventCallbackChain_t disconnectionCallChain; + /** + * Event handler provided by the application. + */ + EventHandler* _eventHandler; + private: /** * Callchain containing all registered callback handlers for shutdown From 47ea39982fa2e84c568d1a2b4b68bb1c8c686458 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Jul 2018 11:57:26 +0100 Subject: [PATCH 02/14] Merge pull request #2 from pan-/PHY_API Phy api --- features/FEATURE_BLE/ble/Gap.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index d1397f8d74..cc146e2c7f 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -276,6 +276,20 @@ class GapAdvertisingData; * gap.startScan(handle_advertising_packet); * @endcode * + * @par Changing the PHYsical transport of a connection + * + * Once a connection has been established, it is possible to change the physical + * transport used between the local and the distant device. Changing the transport + * can either increase the bandwidth or increase the communication range. + * An increased bandwidth equals a better power consumption but also a loss in + * sensibility and therefore a degraded range. + * Symmetrically an increased range means a lowered bandwith and a degraded power + * consumption. + * + * Applications can change the PHY used by calling the function setPhy. Once the + * update has been made the result is forwarded to the application by calling the + * function onPhyUpdateComplete of the event handler registered. + * * @par disconnection * * The application code initiates a disconnection when it calls the @@ -1105,7 +1119,7 @@ public: * * @param rxPhy PHY used by the receiver. */ - virtual void onPhyRead( + virtual void onReadPhy( ble_error_t status, Handle_t connectionHandle, ble::phy_t txPhy, @@ -1471,7 +1485,7 @@ public: const Phys_t* rxPhys, CodedSymbolPerBit_t codedSymbol ) { - return BLE_ERROR_NONE; + return BLE_ERROR_NOT_IMPLEMENTED; } /** From 954f004d1663a9c450b6a65c2ccfa7356a75c94b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 29 Jun 2018 16:11:51 +0100 Subject: [PATCH 03/14] Nordic BLE: Implement PHY APIs for NRF52. --- .../TARGET_NRF52/source/btle/btle.cpp | 18 +- .../TARGET_NRF52/source/nRF5xGap.cpp | 171 ++++++++++++++++++ .../TARGET_NRF52/source/nRF5xGap.h | 27 ++- 3 files changed, 205 insertions(+), 11 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.cpp index be6abd25ee..cf7836a8ee 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.cpp @@ -335,16 +335,18 @@ void btle_handler(const ble_evt_t *p_ble_evt) #ifndef S140 // Handle PHY upgrade request case BLE_GAP_EVT_PHY_UPDATE_REQUEST: - { - ble_gap_phys_t const phys = - { - /* rx_phys */ BLE_GAP_PHY_AUTO, - /* tx_phys */ BLE_GAP_PHY_AUTO, - }; - ASSERT_STATUS_RET_VOID( sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys) ); + gap.on_phy_update_request( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.phy_update_request + ); break; - } #endif + case BLE_GAP_EVT_PHY_UPDATE: + gap.on_phy_update( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.phy_update + ); + break; // Handle Data length negotiation request case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 3a772b2667..689a6ae96d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -115,6 +115,33 @@ peer_address_type_t convert_identity_address(advertising_peer_address_type_t add } } +// FIXME: update when SD 5 (not alpha!) or more is used for 52840. +#ifndef BLE_GAP_PHY_AUTO +#define BLE_GAP_PHY_AUTO 0 +#endif + +uint8_t to_nordic_phy_set(const ble::phys_t* phys) { + if (!phys) { + return BLE_GAP_PHY_AUTO; + } + + uint8_t nordic_phys = 0; + + if (phys->le_1m) { + nordic_phys |= BLE_GAP_PHY_1MBPS; + } + + if (phys->le_2m) { + nordic_phys |= BLE_GAP_PHY_2MBPS; + } + + if (phys->le_coded) { + nordic_phys |= BLE_GAP_PHY_CODED; + } + + return nordic_phys; +} + } // namespace void radioNotificationStaticCallback(bool param) { @@ -134,6 +161,8 @@ nRF5xGap::nRF5xGap() : Gap(), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), _non_private_address_type(LegacyAddressType::RANDOM_STATIC), + _prefered_tx_phys(BLE_GAP_PHY_AUTO), + _prefered_rx_phys(BLE_GAP_PHY_AUTO), _connections_role() { m_connectionHandle = BLE_CONN_HANDLE_INVALID; @@ -654,6 +683,87 @@ ble_error_t nRF5xGap::connect( } } +ble_error_t nRF5xGap::readPhy(Handle_t connection) { + /* + * This function is not implemented as it is not possible with current + * nordic API to know which phy was used to establish the connection. + * + * TODO: Update when Nordic provides the API to do the job. + */ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5xGap::setPreferedPhys( + const Phys_t* txPhys, + const Phys_t* rxPhys +) { + uint8_t prefered_tx_phys = to_nordic_phy_set(txPhys); + uint8_t prefered_rx_phys = to_nordic_phy_set(rxPhys); + +#ifdef S140 + ble_opt_t opt = { 0 }; + opt.gap_opt.preferred_phys.tx_phys = prefered_tx_phys; + opt.gap_opt.preferred_phys.rx_phys = prefered_rx_phys; + + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PREFERRED_PHYS_SET, &opt); + + switch (err) { + case NRF_SUCCESS: + break; + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_PARAM: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + return BLE_ERROR_UNSPECIFIED; + } + +#endif + + _prefered_tx_phys = prefered_tx_phys; + _prefered_rx_phys = prefered_rx_phys; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPhy( + Handle_t connection, + const Phys_t* txPhys, + const Phys_t* rxPhys, + CodedSymbolPerBit_t codedSymbol +) { +#ifdef S140 + return BLE_ERROR_NOT_IMPLEMENTED; +#else + // TODO handle coded symbol once supported by the softdevice. + ble_gap_phys_t gap_phys = { + to_nordic_phy_set(txPhys), + to_nordic_phy_set(rxPhys) + }; + + uint32_t err = sd_ble_gap_phy_update(connection, &gap_phys); + + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_INVALID_CONN_HANDLE: + case NRF_ERROR_INVALID_PARAM: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + default: + return BLE_ERROR_UNSPECIFIED; + } +#endif +} + ble_error_t nRF5xGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) { uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION; @@ -1507,6 +1617,67 @@ void nRF5xGap::release_all_connections_role() { _connections_role[i].is_allocated = false; } } +void nRF5xGap::on_phy_update( + Handle_t connection, + const ble_gap_evt_phy_update_t& evt +) { + if (!_eventHandler) { + return; + } + + ble_error_t status; + switch (evt.status) { + case BLE_HCI_STATUS_CODE_SUCCESS: + status = BLE_ERROR_NONE; + break; + + case BLE_HCI_UNSUPPORTED_REMOTE_FEATURE: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + + case BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION: + case BLE_HCI_DIFFERENT_TRANSACTION_COLLISION: + status = BLE_ERROR_INVALID_STATE; + break; + + case BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS: + status = BLE_ERROR_INVALID_PARAM; + break; + + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + _eventHandler->onPhyUpdateComplete( + status, + connection, + Phy_t::LE_1M, + Phy_t::LE_1M + ); +} + +#ifndef S140 +void nRF5xGap::on_phy_update_request( + Handle_t connection, + const ble_gap_evt_phy_update_request_t& evt +) { + ble_gap_phys_t phys = { + _prefered_tx_phys & evt.peer_preferred_phys.tx_phys, + _prefered_rx_phys & evt.peer_preferred_phys.rx_phys + }; + + if (!phys.tx_phys) { + phys.tx_phys = BLE_GAP_PHY_AUTO; + } + + if (!phys.rx_phys) { + phys.rx_phys = BLE_GAP_PHY_AUTO; + } + + sd_ble_gap_phy_update(connection, &phys); +} +#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index 4e52a60f28..b482c4a5b6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -30,10 +30,10 @@ #endif #ifndef YOTTA_CFG_IRK_TABLE_MAX_SIZE #if (NRF_SD_BLE_API_VERSION >= 3) - #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT + #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT #else #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT - #endif + #endif #elif YOTTA_CFG_IRK_TABLE_MAX_SIZE > BLE_GAP_WHITELIST_IRK_MAX_COUNT #undef YOTTA_CFG_IRK_TABLE_MAX_SIZE #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT @@ -77,7 +77,7 @@ public: // The Mbed infrastructure expects 100ms+ - so for now return that // return getMinAdvertisingInterval(); // FIXME infrastructure - return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; + return GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON; #else return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN); #endif @@ -89,6 +89,19 @@ public: virtual ble_error_t connect(const Address_t, ble::peer_address_type_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams, bool identity); + + virtual ble_error_t readPhy(Handle_t connection); + virtual ble_error_t setPreferedPhys( + const Phys_t* txPhys, + const Phys_t* rxPhys + ); + virtual ble_error_t setPhy( + Handle_t connection, + const Phys_t* txPhys, + const Phys_t* rxPhys, + CodedSymbolPerBit_t codedSymbol + ); + virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); @@ -287,6 +300,12 @@ private: void release_connection_role(ble::connection_handle_t); void release_all_connections_role(); + void on_phy_update(Handle_t connection, const ble_gap_evt_phy_update_t& evt); + // FIXME: remove guard when S140 updated + #ifndef S140 + void on_phy_update_request(Handle_t connection, const ble_gap_evt_phy_update_request_t& evt); + #endif + uint16_t m_connectionHandle; ConnectionEventMonitor::EventHandler* _connection_event_handler; @@ -295,6 +314,8 @@ private: CentralPrivacyConfiguration_t _central_privacy_configuration; AddressType_t _non_private_address_type; Address_t _non_private_address; + uint8_t _prefered_tx_phys; + uint8_t _prefered_rx_phys; struct connection_role_t { connection_role_t() : From d5c675e3001a1ecf804911fc04bfd1a3ad5ea6cf Mon Sep 17 00:00:00 2001 From: Paul Szczepanek Date: Thu, 23 Aug 2018 11:26:27 +0100 Subject: [PATCH 04/14] Merge pull request #6 from paul-szczepanek-arm/feature-support support for controller features --- features/FEATURE_BLE/ble/pal/PalGap.h | 37 +++++++++++++++++++ .../FEATURE_BLE/source/generic/GenericGap.cpp | 2 + .../targets/TARGET_CORDIO/CordioPalGap.h | 7 +++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index aec629a587..0df5756e5d 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -32,6 +32,33 @@ namespace pal { * by that layer. */ struct Gap { + /** @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 6, Part B - 4.6 */ + struct ControllerSupportedFeatures_t : SafeEnum { + enum type { + LE_ENCRYPTION = 0, + CONNECTION_PARAMETERS_REQUEST_PROCEDURE, + EXTENDED_REJECT_INDICATION, + SLAVE_INITIATED_FEATURES_EXCHANGE, + LE_PING, + LE_DATA_PACKET_LENGTH_EXTENSION, + LL_PRIVACY, + EXTENDED_SCANNER_FILTER_POLICIES, + LE_2M_PHY, + STABLE_MODULATION_INDEX_TRANSMITTER, + STABLE_MODULATION_INDEX_RECEIVER, + LE_CODED_PHY, + LE_EXTENDED_ADVERTISING, + LE_PERIODIC_ADVERTISING, + CHANNEL_SELECTION_ALGORITHM_2, + LE_POWER_CLASS + }; + + /** + * Construct a new instance of ControllerSupportedFeatures_t. + */ + ControllerSupportedFeatures_t(type value) : SafeEnum(value) { } + }; + /** * Initialisation of the instance. An implementation can use this function * to initialise the subsystems needed to realize the operations of this @@ -670,6 +697,16 @@ struct Gap { bool enable ) = 0; + /** + * Checked support for a feature in the link controller. + * + * @param feature feature to be checked. + * @return TRUE if feature is supported. + */ + virtual bool is_feature_supported( + ControllerSupportedFeatures_t feature + ) = 0; + /** * Register a callback which will handle Gap events. * diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index dc7e8c058a..1a4d061e13 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -417,6 +417,8 @@ GenericGap::GenericGap( _scan_timeout(), _connection_event_handler(NULL) { + _pal_gap.initialize(); + _pal_gap.when_gap_event_received( mbed::callback(this, &GenericGap::on_gap_event_received) ); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 52fae1eed3..022941ee38 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -13,8 +13,13 @@ namespace cordio { * Implementation of ble::pal::Gap for the Cordio stack. */ class Gap : public ::ble::pal::Gap { - public: + virtual bool is_feature_supported( + Gap::ControllerSupportedFeatures_t feature + ) { + return (HciGetLeSupFeat() & (1 << feature.value())); + } + virtual ble_error_t initialize() { return BLE_ERROR_NONE; } From 8090e7acd88c0b24857c3d9e0c931bf9267cd95c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 16 Jul 2018 14:03:12 +0100 Subject: [PATCH 05/14] phy API implementation for cordio phy set types added, nordic implementation updated --- features/FEATURE_BLE/ble/BLETypes.h | 99 +++- features/FEATURE_BLE/ble/Gap.h | 10 +- features/FEATURE_BLE/ble/generic/GenericGap.h | 43 +- features/FEATURE_BLE/ble/pal/PalGap.h | 70 ++- .../FEATURE_BLE/source/generic/GenericGap.cpp | 59 +++ .../targets/TARGET_CORDIO/CordioPalGap.h | 298 ++--------- .../TARGET_CORDIO/source/CordioPalGap.cpp | 461 ++++++++++++++++++ .../TARGET_NRF52/source/nRF5xGap.cpp | 40 +- .../TARGET_NRF52/source/nRF5xGap.h | 8 +- 9 files changed, 776 insertions(+), 312 deletions(-) create mode 100644 features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index f30a4da2d0..e5bbbb72ee 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -628,23 +628,98 @@ struct phy_t : SafeEnum { }; /** - * Type that describe a set of PHY(sical) transports. + * Type that describe a set of PHY(sical) transports. This is used to + * indicate preference for the PHY transports set within it. */ -struct phys_t { - /** - * If equal to 1 then the set includes phy_t::LE_1M. - */ - uint8_t le_1m:1; +class phy_set_t { +public: + enum PhysFlags_t { + PHY_SET_1M = 0x01, + PHY_SET_2M = 0x02, + PHY_SET_CODED = 0x04 + }; + + phy_set_t() : _value(0) { } + phy_set_t(uint8_t value) : _value(value) { } + phy_set_t( + bool phy_1m, + bool phy_2m, + bool phy_coded + ) { + set_1m(phy_1m); + set_2m(phy_2m); + set_coded(phy_coded); + } /** - * If equal to 1 then the set includes phy_t::LE_2M. + * Create an ALL_PHYS parameter used in LE Set PHY Command + * and LE Set Default PHY Command. + * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E - 7.8.49 */ - uint8_t le_2m:1; + static uint8_t all_phys_value( + const phy_set_t& tx_phys, + const phy_set_t& rx_phys + ) { + /* if phy set is empty set corresponding all_phys bit to 1 */ + uint8_t all_phys = 0; + if (tx_phys.value() == 0) { + all_phys |= 0x01; + } + if (rx_phys.value() == 0) { + all_phys |= 0x02; + } + return all_phys; + } - /** - * If equal to 1 then the set includes phy_t::LE_CODED. - */ - uint8_t le_coded:1; + /** Prefer 1M PHY. */ + void set_1m(bool enabled = true) { + if (enabled) { + _value |= PHY_SET_1M; + } else { + _value &= ~PHY_SET_1M; + } + } + + /** Prefer 2M PHY. */ + void set_2m(bool enabled = true) { + if (enabled) { + _value |= PHY_SET_2M; + } else { + _value &= ~PHY_SET_2M; + } + } + + /** Prefer coded PHY. */ + void set_coded(bool enabled = true) { + if (enabled) { + _value |= PHY_SET_CODED; + } else { + _value &= ~PHY_SET_CODED; + } + } + + bool get_1m() { + return (_value & PHY_SET_1M); + } + + bool get_2m() { + return (_value & PHY_SET_2M); + } + + bool get_coded() { + return (_value & PHY_SET_CODED); + } + + operator uint8_t() { + return _value; + } + + uint8_t value() const { + return _value; + } + +private: + uint8_t _value; }; /** diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index cc146e2c7f..dd834fbbec 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -555,7 +555,7 @@ public: /** * Set of BLE PHYs */ - typedef ble::phys_t Phys_t; + typedef ble::phy_set_t PhySet_t; /** * Enumeration of type of symbols that can be used with LE coded PHY. @@ -1451,8 +1451,8 @@ public: * error code. */ virtual ble_error_t setPreferedPhys( - const Phys_t* txPhys, - const Phys_t* rxPhys + const PhySet_t* txPhys, + const PhySet_t* rxPhys ) { return BLE_ERROR_NOT_IMPLEMENTED; } @@ -1481,8 +1481,8 @@ public: */ virtual ble_error_t setPhy( Handle_t connection, - const Phys_t* txPhys, - const Phys_t* rxPhys, + const PhySet_t* txPhys, + const PhySet_t* rxPhys, CodedSymbolPerBit_t codedSymbol ) { return BLE_ERROR_NOT_IMPLEMENTED; diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index 33fa638fda..c972730ba8 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -43,7 +43,8 @@ namespace generic { * @attention: Not part of the public interface of BLE API. */ class GenericGap : public ::Gap, - public pal::ConnectionEventMonitor { + public pal::ConnectionEventMonitor, + public pal::Gap::EventHandler { public: /** @@ -133,6 +134,29 @@ public: const GapScanningParams *scanParams ); + /** + * @see Gap::readPhy + */ + virtual ble_error_t readPhy(Handle_t connection); + + /** + * @see Gap::setPreferedPhys + */ + virtual ble_error_t setPreferedPhys( + const phy_set_t* txPhys, + const phy_set_t* rxPhys + ); + + /** + * @see Gap::setPhy + */ + virtual ble_error_t setPhy( + Handle_t connection, + const phy_set_t* txPhys, + const phy_set_t* rxPhys, + CodedSymbolPerBit_t codedSymbol + ); + /** * @see Gap::disconnect */ @@ -371,6 +395,23 @@ private: void on_address_rotation_timeout(); + /* implements pal::Gap::EventHandler */ +private: + virtual void on_read_phy( + pal::hci_error_code_t hci_status, + Handle_t connection_handle, + ble::phy_t tx_phy, + ble::phy_t rx_phy + ); + + virtual void on_phy_update_complete( + pal::hci_error_code_t hci_status, + Handle_t connection_handle, + ble::phy_t tx_phy, + ble::phy_t rx_phy + ); + +private: pal::EventQueue& _event_queue; pal::Gap &_pal_gap; pal::GenericAccessService &_gap_service; diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 0df5756e5d..7f45f437c2 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -18,8 +18,9 @@ #define BLE_PAL_GAP_H_ #include "platform/Callback.h" -#include "GapTypes.h" +#include "ble/pal/GapTypes.h" #include "GapEvents.h" +#include "blecommon.h" namespace ble { namespace pal { @@ -59,6 +60,28 @@ struct Gap { ControllerSupportedFeatures_t(type value) : SafeEnum(value) { } }; + struct EventHandler { + /** + * @copydoc Gap::EventHandler::onReadPhy + */ + virtual void on_read_phy( + pal::hci_error_code_t status, + connection_handle_t connectionHandle, + ble::phy_t tx_phy, + ble::phy_t rx_phy + ) = 0; + + /** + * @copydoc Gap::EventHandler::onPhyUpdateComplete + */ + virtual void on_phy_update_complete( + pal::hci_error_code_t status, + connection_handle_t connection_handle, + ble::phy_t tx_phy, + ble::phy_t rx_phy + ) = 0; + }; + /** * Initialisation of the instance. An implementation can use this function * to initialise the subsystems needed to realize the operations of this @@ -706,6 +729,29 @@ struct Gap { virtual bool is_feature_supported( ControllerSupportedFeatures_t feature ) = 0; + + /** + * @see Gap::readPhy + */ + virtual ble_error_t read_phy(connection_handle_t connection) = 0; + + /** + * @see Gap::setPreferedPhys + */ + virtual ble_error_t set_prefered_phys( + const phy_set_t& tx_phys, + const phy_set_t& rx_phys + ) = 0; + + /** + * @see Gap::setPhy + */ + virtual ble_error_t set_phy( + connection_handle_t connection, + const phy_set_t& tx_phys, + const phy_set_t& rx_phys, + coded_symbol_per_bit_t coded_symbol + ) = 0; /** * Register a callback which will handle Gap events. @@ -719,8 +765,27 @@ struct Gap { _gap_event_cb = cb; } +public: + /** + * Sets the event handler that us called by the PAL porters to notify the stack of events + * which will in turn be passed onto the user application when appropriate. + * + * @param[in] event_handler the new event handler interface implementation. Memory + * owned by caller who is responsible for updating this pointer if interface changes. + */ + void set_event_handler(EventHandler *event_handler) { + _pal_event_handler = event_handler; + } + + EventHandler* get_event_handler() { + return _pal_event_handler; + } + protected: - Gap() { } + EventHandler *_pal_event_handler; + +protected: + Gap() : _pal_event_handler(NULL) { } virtual ~Gap() { } @@ -743,6 +808,7 @@ private: */ mbed::Callback _gap_event_cb; +private: // Disallow copy construction and copy assignment. Gap(const Gap&); Gap& operator=(const Gap&); diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 1a4d061e13..551472af0c 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -425,6 +425,8 @@ GenericGap::GenericGap( // Recover static random identity _random_static_identity_address = _pal_gap.get_random_address(); + + _pal_gap.set_event_handler(this); } GenericGap::~GenericGap() @@ -587,6 +589,63 @@ ble_error_t GenericGap::connect( ); } +ble_error_t GenericGap::readPhy(Handle_t connection) { + return _pal_gap.read_phy(connection); +} + +ble_error_t GenericGap::setPreferedPhys( + const phy_set_t* txPhys, + const phy_set_t* rxPhys +) { + phy_set_t tx_phys(txPhys? txPhys->value() : 0); + phy_set_t rx_phys(rxPhys? rxPhys->value() : 0); + return _pal_gap.set_prefered_phys(tx_phys, rx_phys); +} + +ble_error_t GenericGap::setPhy( + Handle_t connection, + const phy_set_t* txPhys, + const phy_set_t* rxPhys, + CodedSymbolPerBit_t codedSymbol +) { + phy_set_t tx_phys(txPhys? txPhys->value() : 0); + phy_set_t rx_phys(rxPhys? rxPhys->value() : 0); + return _pal_gap.set_phy(connection, tx_phys, rx_phys, codedSymbol); +} + + +void GenericGap::on_read_phy( + pal::hci_error_code_t hci_status, + Handle_t connection_handle, + ble::phy_t tx_phy, + ble::phy_t rx_phy +) { + ble_error_t status = BLE_ERROR_NONE; + if (pal::hci_error_code_t::SUCCESS != hci_status) { + status = BLE_ERROR_UNSPECIFIED; + } + + if (_eventHandler) { + _eventHandler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); + } +} + +void GenericGap::on_phy_update_complete( + pal::hci_error_code_t hci_status, + Handle_t connection_handle, + ble::phy_t tx_phy, + ble::phy_t rx_phy +) { + ble_error_t status = BLE_ERROR_NONE; + if (pal::hci_error_code_t::SUCCESS != hci_status) { + status = BLE_ERROR_UNSPECIFIED; + } + + if (_eventHandler) { + _eventHandler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); + } +} + ble_error_t GenericGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) { if (is_disconnection_reason_valid(reason) == false) { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 022941ee38..2f9fc076b8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -16,31 +16,17 @@ class Gap : public ::ble::pal::Gap { public: virtual bool is_feature_supported( Gap::ControllerSupportedFeatures_t feature - ) { - return (HciGetLeSupFeat() & (1 << feature.value())); - } + ); - virtual ble_error_t initialize() { - return BLE_ERROR_NONE; - } + virtual ble_error_t initialize(); - virtual ble_error_t terminate() { - return BLE_ERROR_NONE; - } + virtual ble_error_t terminate(); - virtual address_t get_device_address() { - return address_t(HciGetBdAddr()); - } + virtual address_t get_device_address(); - virtual address_t get_random_address() { - return device_random_address; - } + virtual address_t get_random_address(); - virtual ble_error_t set_random_address(const address_t& address) { - device_random_address = address; - DmDevSetRandAddr(const_cast(address.data())); - return BLE_ERROR_NONE; - } + virtual ble_error_t set_random_address(const address_t& address); virtual ble_error_t set_advertising_parameters( uint16_t advertising_interval_min, @@ -51,75 +37,19 @@ public: const address_t& peer_address, advertising_channel_map_t advertising_channel_map, advertising_filter_policy_t advertising_filter_policy - ) { - DmAdvSetInterval( - DM_ADV_HANDLE_DEFAULT, - advertising_interval_min, - advertising_interval_max - ); - - DmAdvSetAddrType(own_address_type.value()); - - DmAdvSetChannelMap( - DM_ADV_HANDLE_DEFAULT, - advertising_channel_map.value() - ); - - DmDevSetFilterPolicy( - DM_FILT_POLICY_MODE_ADV, - advertising_filter_policy.value() - ); - - DmAdvConfig( - DM_ADV_HANDLE_DEFAULT, - advertising_type.value(), - peer_address_type.value(), - const_cast(peer_address.data()) - ); - - return BLE_ERROR_NONE; - } + ); virtual ble_error_t set_advertising_data( uint8_t advertising_data_length, const advertising_data_t& advertising_data - ) { - DmAdvSetData( - DM_ADV_HANDLE_DEFAULT, - HCI_ADV_DATA_OP_COMP_FRAG, - DM_DATA_LOC_ADV, - advertising_data_length, - const_cast(advertising_data.data()) - ); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t set_scan_response_data( uint8_t scan_response_data_length, const advertising_data_t& scan_response_data - ) { - DmAdvSetData( - DM_ADV_HANDLE_DEFAULT, - HCI_ADV_DATA_OP_COMP_FRAG, - DM_DATA_LOC_SCAN, - scan_response_data_length, - const_cast(scan_response_data.data()) - ); - return BLE_ERROR_NONE; - } + ); - virtual ble_error_t advertising_enable(bool enable) { - if (enable) { - uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; - uint16_t adv_durations[] = { /* infinite */ 0 }; - uint8_t max_ea_events[] = { 0 }; - DmAdvStart(1, adv_handles, adv_durations, max_ea_events); - } else { - uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; - DmAdvStop(1, adv_handles); - } - return BLE_ERROR_NONE; - } + virtual ble_error_t advertising_enable(bool enable); virtual ble_error_t set_scan_parameters( bool active_scanning, @@ -127,36 +57,12 @@ public: uint16_t scan_window, own_address_type_t own_address_type, scanning_filter_policy_t filter_policy - ) { - use_active_scanning = active_scanning; - DmScanSetInterval(HCI_INIT_PHY_LE_1M_BIT, &scan_interval, &scan_window); - DmScanSetAddrType(own_address_type.value()); - DmDevSetFilterPolicy( - DM_FILT_POLICY_MODE_SCAN, - filter_policy.value() - ); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t scan_enable( bool enable, bool filter_duplicates - ) { - if (enable) { - uint8_t scanType = use_active_scanning ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE; - DmScanStart( - HCI_SCAN_PHY_LE_1M_BIT, - DM_DISC_MODE_NONE, - &scanType, - filter_duplicates, - 0, - 0 - ); - } else { - DmScanStop(); - } - return BLE_ERROR_NONE; - } + ); virtual ble_error_t create_connection( uint16_t scan_interval, @@ -171,74 +77,23 @@ public: uint16_t supervision_timeout, uint16_t minimum_connection_event_length, uint16_t maximum_connection_event_length - ) { - DmConnSetScanInterval(scan_interval, scan_window); - DmDevSetFilterPolicy(DM_FILT_POLICY_MODE_INIT, initiator_policy.value()); - DmConnSetAddrType(own_address_type.value()); + ); - hciConnSpec_t conn_spec = { - connection_interval_min, - connection_interval_max, - connection_latency, - supervision_timeout, - minimum_connection_event_length, - maximum_connection_event_length - }; - DmConnSetConnSpec(&conn_spec); + virtual ble_error_t cancel_connection_creation(); - dmConnId_t connection_id = DmConnOpen( - DM_CLIENT_ID_APP, - HCI_INIT_PHY_LE_1M_BIT, - peer_address_type.value(), - const_cast(peer_address.data()) - ); + virtual uint8_t read_white_list_capacity(); - if (connection_id == DM_CONN_ID_NONE) { - return BLE_ERROR_INTERNAL_STACK_FAILURE; - } - - return BLE_ERROR_NONE; - } - - virtual ble_error_t cancel_connection_creation() { - DmConnClose( - DM_CLIENT_ID_APP, - /* connection handle - invalid */ DM_CONN_ID_NONE, - /* reason - invalid (use success) */ 0x00 - ); - return BLE_ERROR_NONE; - } - - virtual uint8_t read_white_list_capacity() { - return HciGetWhiteListSize(); - } - - virtual ble_error_t clear_whitelist() { - DmDevWhiteListClear(); - return BLE_ERROR_NONE; - } + virtual ble_error_t clear_whitelist(); virtual ble_error_t add_device_to_whitelist( whitelist_address_type_t address_type, address_t address - ) { - DmDevWhiteListAdd( - address_type.value(), - const_cast(address.data()) - ); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t remove_device_from_whitelist( whitelist_address_type_t address_type, address_t address - ) { - DmDevWhiteListRemove( - address_type.value(), - const_cast(address.data()) - ); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t connection_parameters_update( connection_handle_t connection, @@ -248,26 +103,7 @@ public: uint16_t supervision_timeout, uint16_t minimum_connection_event_length, uint16_t maximum_connection_event_length - ) { - if (DmConnCheckIdle(connection) != 0) { - return BLE_ERROR_INVALID_STATE; - } - - hciConnSpec_t connection_spec = { - connection_interval_min, - connection_interval_max, - connection_latency, - supervision_timeout, - minimum_connection_event_length, - maximum_connection_event_length - }; - DmConnUpdate( - connection, - &connection_spec - ); - - return BLE_ERROR_NONE; - } + ); virtual ble_error_t accept_connection_parameter_request( connection_handle_t connection_handle, @@ -277,104 +113,52 @@ public: uint16_t supervision_timeout, uint16_t minimum_connection_event_length, uint16_t maximum_connection_event_length - ) { - hciConnSpec_t connection_spec = { - interval_min, - interval_max, - latency, - supervision_timeout, - minimum_connection_event_length, - maximum_connection_event_length - }; - DmRemoteConnParamReqReply(connection_handle, &connection_spec); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t reject_connection_parameter_request( connection_handle_t connection_handle, hci_error_code_t rejection_reason - ) { - DmRemoteConnParamReqNegReply( - connection_handle, - rejection_reason.value() - ); - return BLE_ERROR_NONE; - } + ); virtual ble_error_t disconnect( connection_handle_t connection, disconnection_reason_t disconnection_reason - ) { - DmConnClose( - DM_CLIENT_ID_APP, - connection, - disconnection_reason.value() - ); - return BLE_ERROR_NONE; - } + ); - virtual bool is_privacy_supported() { - // We only support controller-based privacy, so return whether the controller supports it - return HciLlPrivacySupported(); - } + virtual bool is_privacy_supported(); virtual ble_error_t set_address_resolution( bool enable - ) { - DmPrivSetAddrResEnable(enable); - return BLE_ERROR_NONE; - } + ); + + virtual ble_error_t read_phy(connection_handle_t connection); + + virtual ble_error_t set_prefered_phys( + const phy_set_t& tx_phys, + const phy_set_t& rx_phys + ); + + virtual ble_error_t set_phy( + connection_handle_t connection, + const phy_set_t& tx_phys, + const phy_set_t& rx_phys, + coded_symbol_per_bit_t coded_symbol + ); // singleton of the ARM Cordio client - static Gap& get_gap() { - static Gap _gap; - return _gap; - } + static Gap& get_gap(); -private: - typedef bool (*event_handler_t)(const wsfMsgHdr_t* msg); - -public: /** * Callback which handle wsfMsgHdr_t and forward them to emit_gap_event. */ - static void gap_handler(const wsfMsgHdr_t* msg) { - if (msg == NULL) { - return; - } - - // all handlers are stored in a static array - static const event_handler_t handlers[] = { - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler - }; - - // event->hdr.param: connection handle - - // 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](msg)) { - return; - } - } - } + static void gap_handler(const wsfMsgHdr_t* msg); private: /** * T shall define a can_convert and convert function and a type */ template - static bool event_handler(const wsfMsgHdr_t* msg) { - if (T::can_convert(msg)) { - get_gap().emit_gap_event(T::convert((const typename T::type*)msg)); - return true; - } - return false; - } + static bool event_handler(const wsfMsgHdr_t* msg); /** * Traits defining can_convert for events. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp new file mode 100644 index 0000000000..979ef34abc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp @@ -0,0 +1,461 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-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 "CordioPalGap.h" +#include "hci_api.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace cordio { + +bool Gap::is_feature_supported( + Gap::ControllerSupportedFeatures_t feature +) { + return (HciGetLeSupFeat() & (1 << feature.value())); +} + +ble_error_t Gap::initialize() { + return BLE_ERROR_NONE; +} + +ble_error_t Gap::terminate() { + return BLE_ERROR_NONE; +} + +address_t Gap::get_device_address() { + return address_t(HciGetBdAddr()); +} + +address_t Gap::get_random_address() { + return device_random_address; +} + +ble_error_t Gap::set_random_address(const address_t& address) { + device_random_address = address; + DmDevSetRandAddr(const_cast(address.data())); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_advertising_parameters( + uint16_t advertising_interval_min, + uint16_t advertising_interval_max, + advertising_type_t advertising_type, + own_address_type_t own_address_type, + advertising_peer_address_type_t peer_address_type, + const address_t& peer_address, + advertising_channel_map_t advertising_channel_map, + advertising_filter_policy_t advertising_filter_policy +) { + DmAdvSetInterval( + DM_ADV_HANDLE_DEFAULT, + advertising_interval_min, + advertising_interval_max + ); + + DmAdvSetAddrType(own_address_type.value()); + + DmAdvSetChannelMap( + DM_ADV_HANDLE_DEFAULT, + advertising_channel_map.value() + ); + + DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_ADV, + advertising_filter_policy.value() + ); + + DmAdvConfig( + DM_ADV_HANDLE_DEFAULT, + advertising_type.value(), + peer_address_type.value(), + const_cast(peer_address.data()) + ); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_advertising_data( + uint8_t advertising_data_length, + const advertising_data_t& advertising_data +) { + DmAdvSetData( + DM_ADV_HANDLE_DEFAULT, + HCI_ADV_DATA_OP_COMP_FRAG, + DM_DATA_LOC_ADV, + advertising_data_length, + const_cast(advertising_data.data()) + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_scan_response_data( + uint8_t scan_response_data_length, + const advertising_data_t& scan_response_data +) { + DmAdvSetData( + DM_ADV_HANDLE_DEFAULT, + HCI_ADV_DATA_OP_COMP_FRAG, + DM_DATA_LOC_SCAN, + scan_response_data_length, + const_cast(scan_response_data.data()) + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::advertising_enable(bool enable) { + if (enable) { + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + uint16_t adv_durations[] = { /* infinite */ 0 }; + uint8_t max_ea_events[] = { 0 }; + DmAdvStart(1, adv_handles, adv_durations, max_ea_events); + } else { + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + DmAdvStop(1, adv_handles); + } + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_scan_parameters( + bool active_scanning, + uint16_t scan_interval, + uint16_t scan_window, + own_address_type_t own_address_type, + scanning_filter_policy_t filter_policy +) { + use_active_scanning = active_scanning; + DmScanSetInterval(HCI_INIT_PHY_LE_1M_BIT, &scan_interval, &scan_window); + DmScanSetAddrType(own_address_type.value()); + DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_SCAN, + filter_policy.value() + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::scan_enable( + bool enable, + bool filter_duplicates +) { + if (enable) { + uint8_t scanType = use_active_scanning ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE; + DmScanStart( + HCI_SCAN_PHY_LE_1M_BIT, + DM_DISC_MODE_NONE, + &scanType, + filter_duplicates, + 0, + 0 + ); + } else { + DmScanStop(); + } + return BLE_ERROR_NONE; +} + +ble_error_t Gap::create_connection( + uint16_t scan_interval, + uint16_t scan_window, + initiator_policy_t initiator_policy, + connection_peer_address_type_t peer_address_type, + const address_t& peer_address, + own_address_type_t own_address_type, + uint16_t connection_interval_min, + uint16_t connection_interval_max, + uint16_t connection_latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length +) { + DmConnSetScanInterval(scan_interval, scan_window); + DmDevSetFilterPolicy(DM_FILT_POLICY_MODE_INIT, initiator_policy.value()); + DmConnSetAddrType(own_address_type.value()); + + hciConnSpec_t conn_spec = { + connection_interval_min, + connection_interval_max, + connection_latency, + supervision_timeout, + minimum_connection_event_length, + maximum_connection_event_length + }; + DmConnSetConnSpec(&conn_spec); + + dmConnId_t connection_id = DmConnOpen( + DM_CLIENT_ID_APP, + HCI_INIT_PHY_LE_1M_BIT, + peer_address_type.value(), + const_cast(peer_address.data()) + ); + + if (connection_id == DM_CONN_ID_NONE) { + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::cancel_connection_creation() { + DmConnClose( + DM_CLIENT_ID_APP, + /* connection handle - invalid */ DM_CONN_ID_NONE, + /* reason - invalid (use success) */ 0x00 + ); + return BLE_ERROR_NONE; +} + +uint8_t Gap::read_white_list_capacity() { + return HciGetWhiteListSize(); +} + +ble_error_t Gap::clear_whitelist() { + DmDevWhiteListClear(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::add_device_to_whitelist( + whitelist_address_type_t address_type, + address_t address +) { + DmDevWhiteListAdd( + address_type.value(), + const_cast(address.data()) + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::remove_device_from_whitelist( + whitelist_address_type_t address_type, + address_t address +) { + DmDevWhiteListRemove( + address_type.value(), + const_cast(address.data()) + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::connection_parameters_update( + connection_handle_t connection, + uint16_t connection_interval_min, + uint16_t connection_interval_max, + uint16_t connection_latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length +) { + if (DmConnCheckIdle(connection) != 0) { + return BLE_ERROR_INVALID_STATE; + } + + hciConnSpec_t connection_spec = { + connection_interval_min, + connection_interval_max, + connection_latency, + supervision_timeout, + minimum_connection_event_length, + maximum_connection_event_length + }; + DmConnUpdate( + connection, + &connection_spec + ); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::accept_connection_parameter_request( + connection_handle_t connection_handle, + uint16_t interval_min, + uint16_t interval_max, + uint16_t latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length +) { + hciConnSpec_t connection_spec = { + interval_min, + interval_max, + latency, + supervision_timeout, + minimum_connection_event_length, + maximum_connection_event_length + }; + DmRemoteConnParamReqReply(connection_handle, &connection_spec); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::reject_connection_parameter_request( + connection_handle_t connection_handle, + hci_error_code_t rejection_reason +) { + DmRemoteConnParamReqNegReply( + connection_handle, + rejection_reason.value() + ); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect( + connection_handle_t connection, + disconnection_reason_t disconnection_reason +) { + DmConnClose( + DM_CLIENT_ID_APP, + connection, + disconnection_reason.value() + ); + return BLE_ERROR_NONE; +} + +bool Gap::is_privacy_supported() { + // We only support controller-based privacy, so return whether the controller supports it + return HciLlPrivacySupported(); +} + +ble_error_t Gap::set_address_resolution( + bool enable +) { + DmPrivSetAddrResEnable(enable); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::read_phy(connection_handle_t connection) { + HciLeReadPhyCmd(connection); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_prefered_phys( + const phy_set_t& tx_phys, + const phy_set_t& rx_phys +) { + HciLeSetDefaultPhyCmd( + phy_set_t::all_phys_value(tx_phys, rx_phys), + tx_phys.value(), + rx_phys.value() + ); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::set_phy( + connection_handle_t connection, + const phy_set_t& tx_phys, + const phy_set_t& rx_phys, + coded_symbol_per_bit_t coded_symbol +) { + /* if phy set is empty set corresponding all_phys bit to 1 */ + uint8_t all_phys = 0; + if (tx_phys.value() == 0) { + all_phys |= 0x01; + } + if (rx_phys.value() == 0) { + all_phys |= 0x02; + } + + HciLeSetPhyCmd( + connection, + phy_set_t::all_phys_value(tx_phys, rx_phys), + tx_phys.value(), + rx_phys.value(), + coded_symbol.value() + ); + + return BLE_ERROR_NONE; +} + +// singleton of the ARM Cordio client +Gap& Gap::get_gap() { + static Gap _gap; + return _gap; +} + +/** + * Callback which handle wsfMsgHdr_t and forward them to emit_gap_event. + */ +void Gap::gap_handler(const wsfMsgHdr_t* msg) { + typedef bool (*event_handler_t)(const wsfMsgHdr_t* msg); + + if (msg == NULL) { + return; + } + + connection_handle_t handle = (connection_handle_t)msg->param; + + switch(msg->event) { + case DM_PHY_READ_IND: + if (get_gap()._pal_event_handler) { + const hciLeReadPhyCmdCmplEvt_t* evt = (const hciLeReadPhyCmdCmplEvt_t*)msg; + + get_gap()._pal_event_handler->on_read_phy( + (hci_error_code_t::type)msg->status, + handle, + (ble::phy_t::type)evt->txPhy, + (ble::phy_t::type)evt->rxPhy + ); + } + break; + case DM_PHY_UPDATE_IND: + if (get_gap()._pal_event_handler) { + const hciLePhyUpdateEvt_t* evt = (const hciLePhyUpdateEvt_t*)msg; + + get_gap()._pal_event_handler->on_phy_update_complete( + (hci_error_code_t::type)msg->status, + handle, + (ble::phy_t::type)evt->txPhy, + (ble::phy_t::type)evt->rxPhy + ); + } + break; + } + + // all handlers are stored in a static array + static const event_handler_t handlers[] = { + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler + }; + + // event->hdr.param: connection handle + + // 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](msg)) { + return; + } + } +} + +/** + * T shall define a can_convert and convert function and a type + */ +template +bool Gap::event_handler(const wsfMsgHdr_t* msg) { + if (T::can_convert(msg)) { + get_gap().emit_gap_event(T::convert((const typename T::type*)msg)); + return true; + } + return false; +} + + +} // cordio +} // vendor +} // pal +} // ble diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 689a6ae96d..58a850ff62 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -120,28 +120,6 @@ peer_address_type_t convert_identity_address(advertising_peer_address_type_t add #define BLE_GAP_PHY_AUTO 0 #endif -uint8_t to_nordic_phy_set(const ble::phys_t* phys) { - if (!phys) { - return BLE_GAP_PHY_AUTO; - } - - uint8_t nordic_phys = 0; - - if (phys->le_1m) { - nordic_phys |= BLE_GAP_PHY_1MBPS; - } - - if (phys->le_2m) { - nordic_phys |= BLE_GAP_PHY_2MBPS; - } - - if (phys->le_coded) { - nordic_phys |= BLE_GAP_PHY_CODED; - } - - return nordic_phys; -} - } // namespace void radioNotificationStaticCallback(bool param) { @@ -165,7 +143,7 @@ nRF5xGap::nRF5xGap() : Gap(), _prefered_rx_phys(BLE_GAP_PHY_AUTO), _connections_role() { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; + m_connectionHandle = BLE_CONN_HANDLE_INVALID; } /**************************************************************************/ /*! @@ -694,11 +672,11 @@ ble_error_t nRF5xGap::readPhy(Handle_t connection) { } ble_error_t nRF5xGap::setPreferedPhys( - const Phys_t* txPhys, - const Phys_t* rxPhys + const ble::phy_set_t* txPhys, + const ble::phy_set_t* rxPhys ) { - uint8_t prefered_tx_phys = to_nordic_phy_set(txPhys); - uint8_t prefered_rx_phys = to_nordic_phy_set(rxPhys); + uint8_t prefered_tx_phys = txPhys? txPhys->value() : 0; + uint8_t prefered_rx_phys = rxPhys? rxPhys->value() : 0; #ifdef S140 ble_opt_t opt = { 0 }; @@ -732,8 +710,8 @@ ble_error_t nRF5xGap::setPreferedPhys( ble_error_t nRF5xGap::setPhy( Handle_t connection, - const Phys_t* txPhys, - const Phys_t* rxPhys, + const ble::phy_set_t* txPhys, + const ble::phy_set_t* rxPhys, CodedSymbolPerBit_t codedSymbol ) { #ifdef S140 @@ -741,8 +719,8 @@ ble_error_t nRF5xGap::setPhy( #else // TODO handle coded symbol once supported by the softdevice. ble_gap_phys_t gap_phys = { - to_nordic_phy_set(txPhys), - to_nordic_phy_set(rxPhys) + txPhys? txPhys->value() : 0, + rxPhys? rxPhys->value() : 0 }; uint32_t err = sd_ble_gap_phy_update(connection, &gap_phys); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index b482c4a5b6..d8f0bcf365 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -92,13 +92,13 @@ public: virtual ble_error_t readPhy(Handle_t connection); virtual ble_error_t setPreferedPhys( - const Phys_t* txPhys, - const Phys_t* rxPhys + const ble::phy_set_t* txPhys, + const ble::phy_set_t* rxPhys ); virtual ble_error_t setPhy( Handle_t connection, - const Phys_t* txPhys, - const Phys_t* rxPhys, + const ble::phy_set_t* txPhys, + const ble::phy_set_t* rxPhys, CodedSymbolPerBit_t codedSymbol ); From e0ca4a093fe1dc263ecea989788bd61b140380dd Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 18 Jul 2018 10:02:21 +0100 Subject: [PATCH 06/14] update cordio pal phy to new 5.0 stack --- .../FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp | 1 + .../targets/TARGET_CORDIO/source/CordioPalGap.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 085a7cebb6..4fbbc9e87b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -338,6 +338,7 @@ void BLE::stack_setup() DmConnMasterInit(); DmConnSlaveInit(); DmSecInit(); + DmPhyInit(); // Note: enable once security is supported DmSecLescInit(); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp index 979ef34abc..0bf2f14c2a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp @@ -334,7 +334,7 @@ ble_error_t Gap::set_address_resolution( } ble_error_t Gap::read_phy(connection_handle_t connection) { - HciLeReadPhyCmd(connection); + DmReadPhy(connection); return BLE_ERROR_NONE; } @@ -342,7 +342,7 @@ ble_error_t Gap::set_prefered_phys( const phy_set_t& tx_phys, const phy_set_t& rx_phys ) { - HciLeSetDefaultPhyCmd( + DmSetDefaultPhy( phy_set_t::all_phys_value(tx_phys, rx_phys), tx_phys.value(), rx_phys.value() @@ -366,7 +366,7 @@ ble_error_t Gap::set_phy( all_phys |= 0x02; } - HciLeSetPhyCmd( + DmSetPhy( connection, phy_set_t::all_phys_value(tx_phys, rx_phys), tx_phys.value(), From d64479a2eea1846e18bed214acb6dced1d81af33 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 18 Jul 2018 15:31:09 +0100 Subject: [PATCH 07/14] docuemnted PHY api --- features/FEATURE_BLE/ble/Gap.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index dd834fbbec..ab55037e0e 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -299,6 +299,21 @@ class GapAdvertisingData; * controller/stack. To catch all disconnection events, application code may * set up an handler taking care of disconnection events by calling * onDisconnection(). + * + * * @par Modulation Schemes + * + * When supported by the host and controller you can select modulation schemes + * from available ones + * (@see BLUETOOTH SPECIFICATION Version 5.0 | Vol 1, Part A - 1.2). You may set + * preferred PHY, separately for RX and TX using setPreferredPhys(). You may also + * set the currently used PHY on a selected connection using setPhy(). Both of these + * are however only advisory and the controller is allowed to make its own decision + * on the best PHY to use based on your request, the peer's supported features and + * physical conditions. You may query the currently used PHY using readPhy() which + * will return the result through a call to the registered Gap::EventHandler. + * You may register the event handler with setEventHandler(). The events inform + * about the currently used PHY and of any changes to PHY which may be triggered + * autonomously byt the controller or by the peer. */ class Gap { /* From baaebb47dc46fd249c3384046667855a3b81bb96 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 18 Jul 2018 15:58:16 +0100 Subject: [PATCH 08/14] fix typo in preferred --- features/FEATURE_BLE/ble/Gap.h | 16 +++++++------- features/FEATURE_BLE/ble/generic/GenericGap.h | 4 ++-- features/FEATURE_BLE/ble/pal/PalGap.h | 4 ++-- .../FEATURE_BLE/source/generic/GenericGap.cpp | 4 ++-- .../targets/TARGET_CORDIO/CordioPalGap.h | 2 +- .../TARGET_CORDIO/source/CordioPalGap.cpp | 2 +- .../TARGET_NRF52/source/nRF5xGap.cpp | 22 +++++++++---------- .../TARGET_NRF52/source/nRF5xGap.h | 6 ++--- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index ab55037e0e..500feca6bc 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -1454,18 +1454,18 @@ public: } /** - * Set the prefered PHYs to use in a connection. + * Set the preferred PHYs to use in a connection. * - * @param txPhy: Set of PHYs prefered for tx operations. If NULL then no - * prefered PHYs are set and the default value of the subsytem is used. + * @param txPhy: Set of PHYs preferred for tx operations. If NULL then no + * preferred PHYs are set and the default value of the subsytem is used. * - * @param rxPhy: Set of PHYs prefered for rx operations. If NULL then no - * prefered PHYs are set and the default value of the subsytem is used. + * @param rxPhy: Set of PHYs preferred for rx operations. If NULL then no + * preferred PHYs are set and the default value of the subsytem is used. * * @return BLE_ERROR_NONE if the preferences have been set or an appropriate * error code. */ - virtual ble_error_t setPreferedPhys( + virtual ble_error_t setPreferredPhys( const PhySet_t* txPhys, const PhySet_t* rxPhys ) { @@ -1481,10 +1481,10 @@ public: * * @param connection Handle of the connection to update. * - * @param txPhys Set of PHYs prefered for tx operations. If NULL then the + * @param txPhys Set of PHYs preferred for tx operations. If NULL then the * choice is up to the Bluetooth subsystem. * - * @param rxPhys Set of PHYs prefered for rx operations. If NULL then the + * @param rxPhys Set of PHYs preferred for rx operations. If NULL then the * choice is up to the Bluetooth subsystem. * * @param codedSymbol Number of symbols used to code a bit when le coded is diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index c972730ba8..746371ebcd 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -140,9 +140,9 @@ public: virtual ble_error_t readPhy(Handle_t connection); /** - * @see Gap::setPreferedPhys + * @see Gap::setPreferredPhys */ - virtual ble_error_t setPreferedPhys( + virtual ble_error_t setPreferredPhys( const phy_set_t* txPhys, const phy_set_t* rxPhys ); diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 7f45f437c2..14fd51112e 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -736,9 +736,9 @@ struct Gap { virtual ble_error_t read_phy(connection_handle_t connection) = 0; /** - * @see Gap::setPreferedPhys + * @see Gap::setPreferredPhys */ - virtual ble_error_t set_prefered_phys( + virtual ble_error_t set_preferred_phys( const phy_set_t& tx_phys, const phy_set_t& rx_phys ) = 0; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 551472af0c..94bddf9711 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -593,13 +593,13 @@ ble_error_t GenericGap::readPhy(Handle_t connection) { return _pal_gap.read_phy(connection); } -ble_error_t GenericGap::setPreferedPhys( +ble_error_t GenericGap::setPreferredPhys( const phy_set_t* txPhys, const phy_set_t* rxPhys ) { phy_set_t tx_phys(txPhys? txPhys->value() : 0); phy_set_t rx_phys(rxPhys? rxPhys->value() : 0); - return _pal_gap.set_prefered_phys(tx_phys, rx_phys); + return _pal_gap.set_preferred_phys(tx_phys, rx_phys); } ble_error_t GenericGap::setPhy( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 2f9fc076b8..286fc341f5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -133,7 +133,7 @@ public: virtual ble_error_t read_phy(connection_handle_t connection); - virtual ble_error_t set_prefered_phys( + virtual ble_error_t set_preferred_phys( const phy_set_t& tx_phys, const phy_set_t& rx_phys ); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp index 0bf2f14c2a..b8a33f72b3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp @@ -338,7 +338,7 @@ ble_error_t Gap::read_phy(connection_handle_t connection) { return BLE_ERROR_NONE; } -ble_error_t Gap::set_prefered_phys( +ble_error_t Gap::set_preferred_phys( const phy_set_t& tx_phys, const phy_set_t& rx_phys ) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 58a850ff62..ae12ee7c27 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -139,8 +139,8 @@ nRF5xGap::nRF5xGap() : Gap(), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), _non_private_address_type(LegacyAddressType::RANDOM_STATIC), - _prefered_tx_phys(BLE_GAP_PHY_AUTO), - _prefered_rx_phys(BLE_GAP_PHY_AUTO), + _preferred_tx_phys(BLE_GAP_PHY_AUTO), + _preferred_rx_phys(BLE_GAP_PHY_AUTO), _connections_role() { m_connectionHandle = BLE_CONN_HANDLE_INVALID; @@ -671,17 +671,17 @@ ble_error_t nRF5xGap::readPhy(Handle_t connection) { return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5xGap::setPreferedPhys( +ble_error_t nRF5xGap::setPreferredPhys( const ble::phy_set_t* txPhys, const ble::phy_set_t* rxPhys ) { - uint8_t prefered_tx_phys = txPhys? txPhys->value() : 0; - uint8_t prefered_rx_phys = rxPhys? rxPhys->value() : 0; + uint8_t preferred_tx_phys = txPhys? txPhys->value() : 0; + uint8_t preferred_rx_phys = rxPhys? rxPhys->value() : 0; #ifdef S140 ble_opt_t opt = { 0 }; - opt.gap_opt.preferred_phys.tx_phys = prefered_tx_phys; - opt.gap_opt.preferred_phys.rx_phys = prefered_rx_phys; + opt.gap_opt.preferred_phys.tx_phys = preferred_tx_phys; + opt.gap_opt.preferred_phys.rx_phys = preferred_rx_phys; uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PREFERRED_PHYS_SET, &opt); @@ -702,8 +702,8 @@ ble_error_t nRF5xGap::setPreferedPhys( #endif - _prefered_tx_phys = prefered_tx_phys; - _prefered_rx_phys = prefered_rx_phys; + _preferred_tx_phys = preferred_tx_phys; + _preferred_rx_phys = preferred_rx_phys; return BLE_ERROR_NONE; } @@ -1641,8 +1641,8 @@ void nRF5xGap::on_phy_update_request( const ble_gap_evt_phy_update_request_t& evt ) { ble_gap_phys_t phys = { - _prefered_tx_phys & evt.peer_preferred_phys.tx_phys, - _prefered_rx_phys & evt.peer_preferred_phys.rx_phys + _preferred_tx_phys & evt.peer_preferred_phys.tx_phys, + _preferred_rx_phys & evt.peer_preferred_phys.rx_phys }; if (!phys.tx_phys) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index d8f0bcf365..19273e815c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -91,7 +91,7 @@ public: ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams, bool identity); virtual ble_error_t readPhy(Handle_t connection); - virtual ble_error_t setPreferedPhys( + virtual ble_error_t setPreferredPhys( const ble::phy_set_t* txPhys, const ble::phy_set_t* rxPhys ); @@ -314,8 +314,8 @@ private: CentralPrivacyConfiguration_t _central_privacy_configuration; AddressType_t _non_private_address_type; Address_t _non_private_address; - uint8_t _prefered_tx_phys; - uint8_t _prefered_rx_phys; + uint8_t _preferred_tx_phys; + uint8_t _preferred_rx_phys; struct connection_role_t { connection_role_t() : From 5598958c6d899e2a09c4d797fc8b88049bf02a82 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 18 Jul 2018 16:13:19 +0100 Subject: [PATCH 09/14] formatting for docs --- features/FEATURE_BLE/ble/Gap.h | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 500feca6bc..7653f36ec8 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -300,20 +300,25 @@ class GapAdvertisingData; * set up an handler taking care of disconnection events by calling * onDisconnection(). * - * * @par Modulation Schemes + * @par Modulation Schemes * - * When supported by the host and controller you can select modulation schemes - * from available ones - * (@see BLUETOOTH SPECIFICATION Version 5.0 | Vol 1, Part A - 1.2). You may set - * preferred PHY, separately for RX and TX using setPreferredPhys(). You may also - * set the currently used PHY on a selected connection using setPhy(). Both of these - * are however only advisory and the controller is allowed to make its own decision - * on the best PHY to use based on your request, the peer's supported features and - * physical conditions. You may query the currently used PHY using readPhy() which - * will return the result through a call to the registered Gap::EventHandler. - * You may register the event handler with setEventHandler(). The events inform - * about the currently used PHY and of any changes to PHY which may be triggered - * autonomously byt the controller or by the peer. + * When supported by the host and controller you can select different modulation + * schemes (@see BLUETOOTH SPECIFICATION Version 5.0 | Vol 1, Part A - 1.2): + * - LE 1M PHY + * - LE 2M PHY + * - LE coded PHY + * + * You may set preferred PHYs (separately for RX and TX) using setPreferredPhys(). + * You may also set the currently used PHYs on a selected connection using setPhy(). + * Both of these settings are only advisory and the controller is allowed to make + * its own decision on the best PHY to use based on your request, the peer's + * supported features and the connection's physical conditions. + * + * You may query the currently used PHY using readPhy() which will return the + * result through a call to the registered event handler. You may register the + * handler with setEventHandler(). The events inform about the currently used + * PHY and of any changes to PHYs which may be triggered autonomously by the + * controller or by the peer. */ class Gap { /* From 76624ad6ecec7ac79b08e7470c29aaf42ebffdd9 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 19 Jul 2018 09:44:49 +0100 Subject: [PATCH 10/14] provide stubs for events use gap.h typedef for Phy_t for consistency --- features/FEATURE_BLE/ble/Gap.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 7653f36ec8..ee953ab9ad 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -1142,9 +1142,14 @@ public: virtual void onReadPhy( ble_error_t status, Handle_t connectionHandle, - ble::phy_t txPhy, - ble::phy_t rxPhy - ) = 0; + Phy_t txPhy, + Phy_t rxPhy + ) { + (void)status; + (void)connectionHandle; + (void)txPhy; + (void)rxPhy; + } /** * Function invoked when the update process of the PHY has been completed. @@ -1170,9 +1175,14 @@ public: virtual void onPhyUpdateComplete( ble_error_t status, Handle_t connectionHandle, - ble::phy_t txPhy, - ble::phy_t rxPhy - ) = 0; + Phy_t txPhy, + Phy_t rxPhy + ) { + (void)status; + (void)connectionHandle; + (void)txPhy; + (void)rxPhy; + } protected: /** From 8ac6e2c30d8b008f1edf92a04a8780c8d3dc9ed7 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 19 Jul 2018 14:04:58 +0100 Subject: [PATCH 11/14] added doxygen to constructors and const to getters --- features/FEATURE_BLE/ble/BLETypes.h | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index e5bbbb72ee..615fdeae25 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -639,8 +639,25 @@ public: PHY_SET_CODED = 0x04 }; + /** + * Create set that indicates no preference. + */ phy_set_t() : _value(0) { } + + /** + * Create a set based on the mask specified in the Bluetooth spec. + * + * @param value Octet containing the set of preferred PHYs + */ phy_set_t(uint8_t value) : _value(value) { } + + /** + * Create a set based on individual settings. + * + * @param phy_1m Prefer LE 1M + * @param phy_2m Prefer LE 2M if avaiable + * @param phy_coded Prefer coded modulation if avaiable + */ phy_set_t( bool phy_1m, bool phy_2m, @@ -698,23 +715,23 @@ public: } } - bool get_1m() { + bool get_1m() const { return (_value & PHY_SET_1M); } - bool get_2m() { + bool get_2m() const { return (_value & PHY_SET_2M); } - bool get_coded() { + bool get_coded() const { return (_value & PHY_SET_CODED); } - operator uint8_t() { + operator uint8_t() const { return _value; } - uint8_t value() const { + uint8_t value() const const { return _value; } From 03f44e7a299ec5572d01e90f0dc34fa5dcd7441b Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 19 Jul 2018 14:07:27 +0100 Subject: [PATCH 12/14] accidental spare const removed --- features/FEATURE_BLE/ble/BLETypes.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 615fdeae25..b4e8d5a3ae 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -719,19 +719,19 @@ public: return (_value & PHY_SET_1M); } - bool get_2m() const { + bool get_2m() const { return (_value & PHY_SET_2M); } - bool get_coded() const { + bool get_coded() const { return (_value & PHY_SET_CODED); } - operator uint8_t() const { + operator uint8_t() const { return _value; } - uint8_t value() const const { + uint8_t value() const { return _value; } From db3d124516e58ea9d117d1f2db0fe011c9fdb883 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 19 Jul 2018 15:47:06 +0100 Subject: [PATCH 13/14] moved the utility function into the pal since it's only useful below pal --- features/FEATURE_BLE/ble/BLETypes.h | 20 ------------------ features/FEATURE_BLE/ble/pal/PalGap.h | 21 +++++++++++++++++++ .../TARGET_CORDIO/source/CordioPalGap.cpp | 4 ++-- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index b4e8d5a3ae..0aed57d9c0 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -668,26 +668,6 @@ public: set_coded(phy_coded); } - /** - * Create an ALL_PHYS parameter used in LE Set PHY Command - * and LE Set Default PHY Command. - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E - 7.8.49 - */ - static uint8_t all_phys_value( - const phy_set_t& tx_phys, - const phy_set_t& rx_phys - ) { - /* if phy set is empty set corresponding all_phys bit to 1 */ - uint8_t all_phys = 0; - if (tx_phys.value() == 0) { - all_phys |= 0x01; - } - if (rx_phys.value() == 0) { - all_phys |= 0x02; - } - return all_phys; - } - /** Prefer 1M PHY. */ void set_1m(bool enabled = true) { if (enabled) { diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 14fd51112e..a32b0ebbf8 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -802,6 +802,27 @@ protected: } } +public: + /** + * Create an ALL_PHYS parameter used in LE Set PHY Command + * and LE Set Default PHY Command. + * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E - 7.8.49 + */ + static uint8_t create_all_phys_value( + const phy_set_t& tx_phys, + const phy_set_t& rx_phys + ) { + /* if phy set is empty set corresponding all_phys bit to 1 */ + uint8_t all_phys = 0; + if (tx_phys.value() == 0) { + all_phys |= 0x01; + } + if (rx_phys.value() == 0) { + all_phys |= 0x02; + } + return all_phys; + } + private: /** * Callback called when an event is emitted by the LE subsystem. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp index b8a33f72b3..7fca33e470 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalGap.cpp @@ -343,7 +343,7 @@ ble_error_t Gap::set_preferred_phys( const phy_set_t& rx_phys ) { DmSetDefaultPhy( - phy_set_t::all_phys_value(tx_phys, rx_phys), + create_all_phys_value(tx_phys, rx_phys), tx_phys.value(), rx_phys.value() ); @@ -368,7 +368,7 @@ ble_error_t Gap::set_phy( DmSetPhy( connection, - phy_set_t::all_phys_value(tx_phys, rx_phys), + create_all_phys_value(tx_phys, rx_phys), tx_phys.value(), rx_phys.value(), coded_symbol.value() From 7a503ca1a22a136a5101e396c6ed02a2e6c72abb Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 30 Aug 2018 09:25:50 +0100 Subject: [PATCH 14/14] BLE: Fix doxygen. --- features/FEATURE_BLE/ble/Gap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index ee953ab9ad..2c7e9168d3 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -1471,10 +1471,10 @@ public: /** * Set the preferred PHYs to use in a connection. * - * @param txPhy: Set of PHYs preferred for tx operations. If NULL then no + * @param txPhys: Set of PHYs preferred for tx operations. If NULL then no * preferred PHYs are set and the default value of the subsytem is used. * - * @param rxPhy: Set of PHYs preferred for rx operations. If NULL then no + * @param rxPhys: Set of PHYs preferred for rx operations. If NULL then no * preferred PHYs are set and the default value of the subsytem is used. * * @return BLE_ERROR_NONE if the preferences have been set or an appropriate