From e4c27e50719a6fdeb5c324ca2794eda7e6f8811d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Nov 2018 21:12:16 +0000 Subject: [PATCH] BLE: Introduce new type for extended advertising parameters. --- .../FEATURE_BLE/ble/AdvertisingParameters.h | 704 ++++++++++++++++++ 1 file changed, 704 insertions(+) create mode 100644 features/FEATURE_BLE/ble/AdvertisingParameters.h diff --git a/features/FEATURE_BLE/ble/AdvertisingParameters.h b/features/FEATURE_BLE/ble/AdvertisingParameters.h new file mode 100644 index 0000000000..f5898100f4 --- /dev/null +++ b/features/FEATURE_BLE/ble/AdvertisingParameters.h @@ -0,0 +1,704 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 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. +*/ + +#ifndef MBED_ADVERTISING_PARAMETERS_H__ +#define MBED_ADVERTISING_PARAMETERS_H__ + +#include "BLETypes.h" +#include "BLEProtocol.h" +#include "blecommon.h" +#include "SafeEnum.h" + +/* TODO: std::clamp */ +#define CLAMP(value, min, max) \ + if (value > max) { \ + value = max; \ + } else if (value < min) { \ + value = min; \ + } + +/** + * @addtogroup ble + * @{ + * @addtogroup gap + * @{ + */ + +/** + * Parameters defining the advertising process. + * + * Advertising parameters for legacy advertising are a triplet of three value: + * - The Advertising mode modelled after ble::advertising_type_t. It defines + * if the device is connectable and scannable. This value can be set at + * construction time, updated with setAdvertisingType() and queried by + * getAdvertisingType(). + * - Time interval between advertisement. It can be set at construction time, + * updated by setInterval() and obtained from getInterval(). + * - Duration of the advertising process. As others, it can be set at + * construction time, modified by setTimeout() and retrieved by getTimeout(). + */ +class GapAdvertisingParameters { +public: + + /** + * Minimum Advertising interval for connectable undirected and connectable + * directed events in 625us units. + * + * @note Equal to 20 ms. + */ + static const unsigned GAP_ADV_PARAMS_INTERVAL_MIN = 0x0020; + + /** + * Minimum Advertising interval for scannable and nonconnectable + * undirected events in 625us units. + * + * @note Equal to 100ms. + */ + static const unsigned GAP_ADV_PARAMS_INTERVAL_MIN_NONCON = 0x00A0; + + /** + * Maximum Advertising interval in 625us units. + * + * @note Equal to 10.24s. + */ + static const unsigned GAP_ADV_PARAMS_INTERVAL_MAX = 0x4000; + + /** + * Maximum advertising timeout allowed; in seconds. + */ + static const unsigned GAP_ADV_PARAMS_TIMEOUT_MAX = 0x3FFF; + + /** + * Alias for GapAdvertisingParams::ble::advertising_type_t. + * + * @deprecated Future releases will drop this type alias. + */ + typedef ble::advertising_type_t AdvertisingType; + + typedef ble::advertising_type_t AdvertisingType_t; + + static const ble::advertising_type_t ADV_CONNECTABLE_UNDIRECTED = ble::ADV_CONNECTABLE_UNDIRECTED; + static const ble::advertising_type_t ADV_CONNECTABLE_DIRECTED = ble::ADV_CONNECTABLE_DIRECTED; + static const ble::advertising_type_t ADV_SCANNABLE_UNDIRECTED = ble::ADV_SCANNABLE_UNDIRECTED; + static const ble::advertising_type_t ADV_NON_CONNECTABLE_UNDIRECTED = ble::ADV_NON_CONNECTABLE_UNDIRECTED; + + struct own_address_type_t : ble::SafeEnum { + enum type { + PUBLIC = 0, /**< Public Device Address. */ + RANDOM, /**< Random Device Address. */ + RANDOM_RESOLVABLE_PUBLIC_FALLBACK, /**< Controller generates the Resolvable Private Address based on + the local IRK from the resolving list. If the resolving list + contains no matching entry, use the public address. */ + RANDOM_RESOLVABLE_RANDOM_FALLBACK /**< Controller generates the Resolvable Private Address based on + the local IRK from the resolving list. If the resolving list + contains no matching entry, use previously set random address. */ + }; + own_address_type_t(type value) : ble::SafeEnum(value) { } + }; + + struct peer_address_type_t : ble::SafeEnum { + enum type { + PUBLIC = 0, /**< Public Device Address or Public Identity Address. */ + RANDOM /**< Random Device Address or Random (static) Identity Address. */ + }; + peer_address_type_t(type value) : ble::SafeEnum(value) { } + }; + +public: + /** + * Construct an instance of GapAdvertisingParams. + * + * @param[in] advType Type of advertising. + * @param[in] interval Time interval between two advertisement in units of + * 0.625ms. + * @param[in] timeout Duration in seconds of the advertising process. A + * value of 0 indicate that there is no timeout of the advertising process. + * + * @note If value in input are out of range, they will be normalized. + */ + GapAdvertisingParameters( + ble::advertising_type_t advType = ble::ADV_CONNECTABLE_UNDIRECTED, + uint16_t interval = GAP_ADV_PARAMS_INTERVAL_MIN_NONCON, + uint16_t timeout = 0 + ) : + _advType(advType), + _interval(interval), + _maxInterval(interval), + _timeout(timeout), + _peerAddressType(peer_address_type_t::PUBLIC), + _ownAddressType(own_address_type_t::PUBLIC), + _policy(ble::ADV_POLICY_IGNORE_WHITELIST), + _primaryPhy(ble::phy_t::LE_1M), + _secondaryPhy(ble::phy_t::LE_1M), + _peerAddress(), + _txPower(127), + _maxSkip(0), + _channel37(1), + _channel38(1), + _channel39(1), + _anonymous(0), + _notifyOnScan(0), + _legacyPDU(1), + _includeHeaderTxPower(0) + { + /* Interval checks. */ + if (_advType == ble::ADV_CONNECTABLE_DIRECTED) { + /* Interval must be 0 in directed connectable mode. */ + _interval = 0; + _maxInterval = 0; + } else if (_advType == ble::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min interval is slightly larger than in other modes. */ + CLAMP(_interval, GAP_ADV_PARAMS_INTERVAL_MIN_NONCON, GAP_ADV_PARAMS_INTERVAL_MAX); + CLAMP(_maxInterval, GAP_ADV_PARAMS_INTERVAL_MIN_NONCON, GAP_ADV_PARAMS_INTERVAL_MAX); + } else { + CLAMP(_interval, GAP_ADV_PARAMS_INTERVAL_MIN, GAP_ADV_PARAMS_INTERVAL_MAX); + CLAMP(_maxInterval, GAP_ADV_PARAMS_INTERVAL_MIN, GAP_ADV_PARAMS_INTERVAL_MAX); + } + + /* Timeout checks. */ + if (timeout) { + /* Stay within timeout limits. */ + if (_timeout > GAP_ADV_PARAMS_TIMEOUT_MAX) { + _timeout = GAP_ADV_PARAMS_TIMEOUT_MAX; + } + } + } + +public: + /** + * Number of microseconds in 0.625 milliseconds. + */ + static const uint16_t UNIT_0_625_MS = 625; + + /** + * Convert milliseconds to units of 0.625ms. + * + * @param[in] durationInMillis Number of milliseconds to convert. + * + * @return The value of @p durationInMillis in units of 0.625ms. + */ + static uint16_t MSEC_TO_ADVERTISEMENT_DURATION_UNITS(uint32_t durationInMillis) + { + return (durationInMillis * 1000) / UNIT_0_625_MS; + } + + /** + * Convert units of 0.625ms to milliseconds. + * + * @param[in] gapUnits The number of units of 0.625ms to convert. + * + * @return The value of @p gapUnits in milliseconds. + */ + static uint16_t ADVERTISEMENT_DURATION_UNITS_TO_MS(uint16_t gapUnits) + { + return (gapUnits * UNIT_0_625_MS) / 1000; + } + + /** + * Get the advertising type. + * + * @return The advertising type. + */ + ble::advertising_type_t getAdvertisingType(void) const + { + return _advType; + } + + /** + * Get the advertising interval in milliseconds. + * + * @return The advertisement interval (in milliseconds). + */ + uint16_t getInterval(void) const + { + return ADVERTISEMENT_DURATION_UNITS_TO_MS(_interval); + } + + /** + * Get the advertisement interval in units of 0.625ms. + * + * @return The advertisement interval in advertisement duration units + * (0.625ms units). + */ + uint16_t getIntervalInADVUnits(void) const + { + return _interval; + } + + /** + * Get the advertising timeout. + * + * @return The advertising timeout (in seconds). + */ + uint16_t getTimeout(void) const + { + return _timeout; + } + + /** + * Update the advertising type. + * + * @param[in] newAdvType The new advertising type. + */ + void setAdvertisingType(ble::advertising_type_t newAdvType) + { + _advType = newAdvType; + } + + /** + * Update the advertising interval in milliseconds. + * + * @param[in] newInterval The new advertising interval in milliseconds. + */ + void setInterval(uint16_t newInterval) + { + _interval = MSEC_TO_ADVERTISEMENT_DURATION_UNITS(newInterval); + _maxInterval = _interval; + } + + /** + * Update the advertising timeout. + * + * @param[in] newTimeout The new advertising timeout (in seconds). + * + * @note 0 is a special value meaning the advertising process never ends. + */ + void setTimeout(uint16_t newTimeout) + { + _timeout = newTimeout; + } + + /** + * Update the advertising type. + * + * @param[in] newAdvType The new advertising type. + */ + void setType( + ble::advertising_type_t newAdvType + ) { + _advType = newAdvType; + } + + /** + * Return advertising type. + * + * @return Advertising type. + */ + ble::advertising_type_t getType() const { + return _advType; + } + + /** Check if advertising is anonymous. + * + * @return True if advertising is anonymous. + */ + bool getAnonymousAdvertising() const { + return _anonymous; + } + + /** Advertise without your own address. + * + * @param enable Advertising anonymous if true. + */ + void setAnonymousAdvertising( + bool enable + ) { + _anonymous = enable; + } + + /** Get the advertising intervals on the primary channels. + * + * @param min Minimum interval in milliseconds. + * @param max Maximum interval in milliseconds. + * + * @return Error if pointers are invalid. + */ + ble_error_t getPrimaryInterval( + uint32_t *min /* ms */, + uint32_t *max /* ms */ + ) const { + if (!min || !max) { + return BLE_ERROR_INVALID_PARAM; + } + *min = ADVERTISEMENT_DURATION_UNITS_TO_MS(_interval); + *max = ADVERTISEMENT_DURATION_UNITS_TO_MS(_maxInterval); + return BLE_ERROR_NONE; + } + + /** Set the advertising intervals on the primary channels. + * + * @param min Minimum interval in milliseconds. + * @param max Maximum interval in milliseconds. + */ + void setPrimaryInterval( + uint32_t min /* ms */, + uint32_t max /* ms */ + ) { + _interval = MSEC_TO_ADVERTISEMENT_DURATION_UNITS(min); + _maxInterval = MSEC_TO_ADVERTISEMENT_DURATION_UNITS(max); + } + + /** Get channels set for primary advertising. + * + * @param channel37 Use channel 37. + * @param channel38 Use channel 38. + * @param channel39 Use channel 39. + * + * @return Error if pointers are invalid. + */ + ble_error_t getPrimaryChannels( + bool *channel37, + bool *channel38, + bool *channel39 + ) const { + if (!channel37 || !channel38 || !channel39) { + return BLE_ERROR_INVALID_PARAM; + } + *channel37 = _channel37; + *channel38 = _channel38; + *channel39 = _channel39; + return BLE_ERROR_NONE; + } + + /** Set which channels are to be used for primary advertising. + * At least must be used. If all are set to disabled all channels will be used. + * + * @param channel37 Use channel 37. + * @param channel38 Use channel 38. + * @param channel39 Use channel 39. + */ + void setPrimaryChannels( + bool channel37, + bool channel38, + bool channel39 + ) { + if (!channel37 && !channel38 && !channel39) { + channel37 = channel38 = channel39 = true; + } + _channel37 = channel37; + _channel38 = channel38; + _channel39 = channel39; + } + + /** Get what type of address is to be used as your own address during advertising. + * + * @return Addres tpe used. + */ + own_address_type_t getOwnAddressType() const { + return _ownAddressType; + } + + /** Get what type of address is to be used as your own address during advertising. + */ + void setOwnAddressType( + own_address_type_t addressType + ) { + _ownAddressType = addressType; + } + + /** Get peer address and type used during directed advertising. + * + * @param address Address that will have the peer address written to. + * @param addressType Pointer to type which will have the address type written to. + * + * @return Error if pointers are invalid. + */ + ble_error_t getPeer( + BLEProtocol::AddressBytes_t *address, + peer_address_type_t *addressType + ) const { + if (!address || !addressType) { + return BLE_ERROR_INVALID_PARAM; + } + memcpy(address, _peerAddress, sizeof(BLEProtocol::AddressBytes_t)); + *addressType = _peerAddressType; + return BLE_ERROR_NONE; + }; + + /** Set peer address and type used during directed advertising. + * + * @param address Peer's address bytes. + * @param addressType Peer's address type. + */ + void setPeer( + const BLEProtocol::AddressBytes_t address, + peer_address_type_t addressType + ) { + memcpy(_peerAddress, address, sizeof(BLEProtocol::AddressBytes_t)); + _peerAddressType = addressType; + }; + + /** Get the policy of whitelist use during advertising; + * + * @return Policy used. + */ + ble::advertising_policy_mode_t getPolicyMode() const { + return _policy; + } + /** Set the policy of whitelist use during advertising; + * + * @param Policy to use. + */ + void setPolicyMode( + ble::advertising_policy_mode_t mode + ) { + _policy = mode; + } + + /** Get the advertising TX power. + * + * @return Advertising TX power. + */ + int8_t getTxPower() const { + return _txPower; + } + + /** Set the advertising TX power. + * + * @param txPower Advertising TX power. + */ + void setTxPower( + int8_t txPower + ) { + _txPower = txPower; + } + + /** Get PHYs used on primary and secondary advertising channels. + * + * @param primaryPhy,secondaryPhy Pointer where the result is written to. + * + * @return Error if pointers are invalid. + */ + ble_error_t getPhy( + ble::phy_t *primaryPhy, + ble::phy_t *secondaryPhy + ) const { + if (!primaryPhy || !secondaryPhy) { + return BLE_ERROR_INVALID_PARAM; + } + *primaryPhy = _primaryPhy; + *secondaryPhy = _secondaryPhy; + return BLE_ERROR_NONE; + } + + /** Get PHYs used on primary and secondary advertising channels. + * + * @param primaryPhy Primary advertising channels PHY. + * @param secondaryPhy Secondary advertising channels PHY. + */ + void setPhy( + ble::phy_t primaryPhy, + ble::phy_t secondaryPhy + ) { + _primaryPhy = primaryPhy; + _secondaryPhy = secondaryPhy; + } + + /** Return how many events can be skipped on the secondary channel. + * + * @return How many events can be skipped on the secondary channel. + */ + uint8_t getSecondaryMaxSkip() const { + return _maxSkip; + } + + /** Set how many events can be skipped on the secondary channel. + * + * @param eventNumber Number of events that can be skipped. + */ + void setSecondaryMaxSkip( + uint8_t eventNumber + ) { + _maxSkip = eventNumber; + } + + /** Enabled or disable the callback that notifies the user about a scan request. + * + * @param enable Enable callback if true. + */ + void setScanRequestNotification( + bool enable = true + ) { + _notifyOnScan = enable; + } + + /** Return of the callback for scan request is enabled. + * + * @return True if callback is enabled. + */ + bool getScanRequestNotification() const { + return _notifyOnScan; + } + + /** Use legacy PDU during advertising. + * + * @param enable If true legacy PDU will be used. + */ + void setUseLegacyPDU( + bool enable = true + ) { + _legacyPDU = enable; + } + + /** Check if legacy PDU is used during advertising. + * + * @return True legacy PDU will be used. + */ + bool getUseLegacyPDU() const { + return _legacyPDU; + } + + /** Set if TX power should be included in the header. + * + * @param enable If true include the TX power in the header. + */ + void includeTxPowerInHeader( + bool enable = true + ) { + _includeHeaderTxPower = enable; + } + + /** Check if TX power should be included in the header. + * + * @return True if TX power is included in the header. + */ + bool getTxPowerInHeader() const { + return _includeHeaderTxPower; + } + + /** Get the minimum advertisement interval in units of 0.625ms. + * + * @return The advertisement interval in advertisement duration units + * (0.625ms units). + */ + uint16_t getMinPrimaryIntervalInADVUnits() const { + return _interval; + } + + /** Get the maximum advertisement interval in units of 0.625ms. + * + * @return The advertisement interval in advertisement duration units + * (0.625ms units). + */ + uint16_t getMaxPrimaryIntervalInADVUnits() const { + return _maxInterval; + } + + /** Get the minimum advertisement interval in milliseconds. + * + * @return The advertisement interval in milliseconds. + */ + uint32_t getMinPrimaryInterval() const { + return ADVERTISEMENT_DURATION_UNITS_TO_MS(_interval); + } + + /** Get the maximum advertisement interval in milliseconds. + * + * @return The advertisement interval in milliseconds. + */ + uint32_t getMaxPrimaryInterval() const { + return ADVERTISEMENT_DURATION_UNITS_TO_MS(_maxInterval); + } + + /** Peer address for directed advertising. + * + * @return Peer address. + */ + const BLEProtocol::AddressBytes_t& getPeerAddress() const { + return _peerAddress; + }; + + /** Peer address type for directed advertising. + * + * @return Peer address type. + */ + peer_address_type_t getPeerAddressType() const { + return _peerAddressType; + }; + + /** Get PHY used for primary advertising. + * + * @return PHY used for primary advertising. + */ + ble::phy_t getPrimaryPhy() const { + return _primaryPhy; + } + + /** Get PHY used for secondary advertising. + * + * @return PHY used for secondary advertising. + */ + ble::phy_t getSecondaryPhy() const { + return _secondaryPhy; + } + + /** Check if channel 37 is used for primary advertising. + * + * @return True if channel used. + */ + bool getChannel37() const { + return _channel37; + } + + + /** Check if channel 38 is used for primary advertising. + * + * @return True if channel used. + */ + bool getChannel38() const { + return _channel37; + } + + + /** Check if channel 39 is used for primary advertising. + * + * @return True if channel used. + */ + bool getChannel39() const { + return _channel37; + } + +private: + ble::advertising_type_t _advType; + /* The advertising interval in ADV duration units (in other words, 0.625ms). */ + uint16_t _interval; + /* The advertising timeout in ADV duration units (in other words, 0.625ms). */ + uint16_t _timeout; + /* The advertising max interval in ADV duration units (in other words, 0.625ms) used in extended advertising. */ + uint16_t _maxInterval; + peer_address_type_t _peerAddressType; + own_address_type_t _ownAddressType; + ble::advertising_policy_mode_t _policy; + ble::phy_t _primaryPhy; + ble::phy_t _secondaryPhy; + BLEProtocol::AddressBytes_t _peerAddress; + uint8_t _txPower; + uint8_t _maxSkip; + uint8_t _channel37:1; + uint8_t _channel38:1; + uint8_t _channel39:1; + uint8_t _anonymous:1; + uint8_t _notifyOnScan:1; + uint8_t _legacyPDU:1; + uint8_t _includeHeaderTxPower:1; +}; + +/** + * @} + * @} + */ + +#endif /* ifndef MBED_ADVERTISING_PARAMETERS_H__ */