diff --git a/.gitignore b/.gitignore index 88ff051ecc..7b85cc3417 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,5 @@ tags # Visual Studio Code .vscode/ + +features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/ diff --git a/features/FEATURE_BLE/ble/ArrayView.h b/features/FEATURE_BLE/ble/ArrayView.h index d2a2b6d135..fad829eba1 100644 --- a/features/FEATURE_BLE/ble/ArrayView.h +++ b/features/FEATURE_BLE/ble/ArrayView.h @@ -17,8 +17,11 @@ #ifndef BLE_ARRAY_VIEW_H_ #define BLE_ARRAY_VIEW_H_ +#include + #include #include +#include "platform/mbed_assert.h" /** * @addtogroup ble @@ -33,11 +36,18 @@ namespace ble { +/** + * Special value for the Size parameter of ArrayView. + * If the type use this value then the size of the array is stored in the object + * at runtime. + */ +#define ARRAY_VIEW_DYNAMIC_SIZE -1 + /** * Immutable view to an array. * * Array views encapsulate the pointer to an array and its size into a single - * object; however, it does not manage the lifetime of the array viewed. + * object or type; however, it does not manage the lifetime of the array viewed. * You can use instances of ArrayView to replace the traditional pair of pointer * and size arguments in function calls. * @@ -48,20 +58,28 @@ namespace ble { * @note You can create ArrayView instances with the help of the function * template make_ArrayView() and make_const_ArrayView(). * + * @note ArrayView objects can be implicitly converted to ArrayView + * objects where required. + * * @tparam T type of objects held by the array. + * @tparam Size The size of the array viewed. The default value + * ARRAY_VIEW_DYNAMIC_SIZE is special as it allows construction of ArrayView + * objects of any size (set at runtime). */ -template +template struct ArrayView { + MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView"); + /** * Construct a view to an empty array. * * @post a call to size() will return 0, and data() will return NULL. */ - ArrayView() : _array(0), _size(0) { } + ArrayView() : _array(NULL) { } /** - * Construct an array view from a pointer to a buffer and its size. + * Construct an array view from a pointer to a buffer. * * @param array_ptr Pointer to the array data * @param array_size Number of elements of T present in the array. @@ -70,7 +88,9 @@ struct ArrayView { * array_tpr. */ ArrayView(T* array_ptr, size_t array_size) : - _array(array_ptr), _size(array_size) { } + _array(array_ptr) { + MBED_ASSERT(array_size >= (size_t) Size); + } /** * Construct an array view from the reference to an array. @@ -82,9 +102,8 @@ struct ArrayView { * @post a call to size() will return Size, and data() will return * a pointer to elements. */ - template ArrayView(T (&elements)[Size]): - _array(elements), _size(Size) { } + _array(elements) { } /** * Return the size of the array viewed. @@ -93,7 +112,7 @@ struct ArrayView { */ size_t size() const { - return _size; + return _array ? Size : 0; } /** @@ -144,40 +163,115 @@ struct ArrayView { return _array; } +private: + T* const _array; +}; + +/** + * ArrayView specialisation that handle dynamic array size. + */ +template +struct ArrayView { + /** - * Equality operator. + * Construct a view to an empty array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. - * - * @return True if arrays in input have the same size and the same content - * and false otherwise. + * @post a call to size() will return 0, and data() will return NULL. */ - friend bool operator==(const ArrayView& lhs, const ArrayView& rhs) + ArrayView() : _array(0), _size(0) { } + + /** + * Construct an array view from a pointer to a buffer and its size. + * + * @param array_ptr Pointer to the array data + * @param array_size Number of elements of T present in the array. + * + * @post a call to size() will return array_size and data() will return + * array_tpr. + */ + ArrayView(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct an array view from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Size Number of elements of T presents in the array. + * + * @post a call to size() will return Size, and data() will return + * a pointer to elements. + */ + template + ArrayView(T (&elements)[Size]): + _array(elements), _size(Size) { } + + + /** + * Construct a ArrayView object with a dynamic size from an ArrayView object + * with a static size. + * @param other The ArrayView object used to construct this. + */ + template + ArrayView(ArrayView other): + _array(other.data()), _size(other.size()) { } + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + size_t size() const { - if (lhs.size() != rhs.size()) { - return false; - } - - if (lhs.data() == rhs.data()) { - return true; - } - - return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + return _size; } /** - * Not equal operator + * Access to a mutable element of the array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param index Element index to access. * - * @return True if arrays in input do not have the same size or the same - * content and false otherwise. + * @return A reference to the element at the index specified in input. + * + * @pre index shall be less than size(). */ - friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs) + T& operator[](size_t index) { - return !(lhs == rhs); + return _array[index]; + } + + /** + * Access to an immutable element of the array. + * + * @param index Element index to access. + * + * @return A const reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + const T& operator[](size_t index) const + { + return _array[index]; + } + + /** + * Get the raw pointer to the array. + * + * @return The raw pointer to the array. + */ + T* data() + { + return _array; + } + + /** + * Get the raw const pointer to the array. + * + * @return The raw pointer to the array. + */ + const T* data() const + { + return _array; } private: @@ -186,6 +280,45 @@ private: }; +/** + * Equality operator. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(const ArrayView& lhs, const ArrayView& rhs) +{ + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data()); +} + +/** + * Not equal operator + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input do not have the same size or the same + * content and false otherwise. + */ +template +bool operator!=(const ArrayView& lhs, const ArrayView& rhs) +{ + return !(lhs == rhs); +} + + /** * Generate an array view from a reference to a C/C++ array. * @@ -200,9 +333,28 @@ private: * created 'inline'. */ template -ArrayView make_ArrayView(T (&elements)[Size]) +ArrayView make_ArrayView(T (&elements)[Size]) { - return ArrayView(elements); + return ArrayView(elements); +} + +/** + * Generate an array view from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The ArrayView to elements. + * + * @note This helper avoids the typing of template parameter when ArrayView is + * created 'inline'. + */ +template +ArrayView make_ArrayView(T* elements) +{ + return ArrayView(elements, Size); } /** @@ -237,9 +389,28 @@ ArrayView make_ArrayView(T* array_ptr, size_t array_size) * created 'inline'. */ template -ArrayView make_const_ArrayView(T (&elements)[Size]) +ArrayView make_const_ArrayView(T (&elements)[Size]) { - return ArrayView(elements); + return ArrayView(elements); +} + +/** + * Generate a const array view from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The ArrayView to elements. + * + * @note This helper avoids the typing of template parameter when ArrayView is + * created 'inline'. + */ +template +ArrayView make_const_ArrayView(const T* elements) +{ + return ArrayView(elements, Size); } /** diff --git a/features/FEATURE_BLE/ble/BLE.h b/features/FEATURE_BLE/ble/BLE.h index 66bb545c3e..d117e5614a 100644 --- a/features/FEATURE_BLE/ble/BLE.h +++ b/features/FEATURE_BLE/ble/BLE.h @@ -457,9 +457,7 @@ public: ble_error_t setAddress( BLEProtocol::AddressType_t type, const BLEProtocol::AddressBytes_t address - ) { - return gap().setAddress(type, address); - } + ); /** * Fetch the Bluetooth Low Energy MAC address and type. @@ -1009,9 +1007,7 @@ public: ble_error_t connect(const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC, const Gap::ConnectionParams_t *connectionParams = NULL, - const GapScanningParams *scanParams = NULL) { - return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams); - } + const GapScanningParams *scanParams = NULL); /** * This call initiates the disconnection procedure, and its completion is @@ -1045,9 +1041,7 @@ public: * connection. */ MBED_DEPRECATED("Use ble.gap().disconnect(...)") - ble_error_t disconnect(Gap::DisconnectionReason_t reason) { - return gap().disconnect(reason); - } + ble_error_t disconnect(Gap::DisconnectionReason_t reason); /** * Returns the current Gap state of the device using a bitmask that diff --git a/features/FEATURE_BLE/ble/BLEProtocol.h b/features/FEATURE_BLE/ble/BLEProtocol.h index 4fdcb59bc5..cce3e24c49 100644 --- a/features/FEATURE_BLE/ble/BLEProtocol.h +++ b/features/FEATURE_BLE/ble/BLEProtocol.h @@ -61,16 +61,31 @@ namespace BLEProtocol { /** * Random static device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_STATIC, /** * Private resolvable device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_PRIVATE_RESOLVABLE, /** * Private non-resolvable device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_PRIVATE_NON_RESOLVABLE }; diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 856f3ca84d..7e57b17e2d 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -21,6 +21,7 @@ #include #include #include "ble/SafeEnum.h" +#include "ble/ArrayView.h" /** * @addtogroup ble @@ -128,7 +129,8 @@ struct link_encryption_t : SafeEnum { NOT_ENCRYPTED, /**< The link is not secured. */ ENCRYPTION_IN_PROGRESS, /**< Link security is being established. */ ENCRYPTED, /**< The link is secure. */ - ENCRYPTED_WITH_MITM /**< The link is secure and authenticated. */ + ENCRYPTED_WITH_MITM, /**< The link is secure and authenticated. */ + ENCRYPTED_WITH_SC_AND_MITM /**< The link is secure and authenticated with a secure connection key. */ }; /** @@ -261,8 +263,34 @@ private: uint8_t ascii[PASSKEY_LEN]; }; +/** + * Returns true if every byte is equal to zero + */ +template +bool is_all_zeros(byte_array_class &byte_array) { + for (size_t i = 0; i < byte_array.size(); i++) { + if (byte_array[i] != 0) { + return false; + } + } + return true; +} + +/** + * Zero out all bytes + */ +template +void set_all_zeros(byte_array_class &byte_array) { + memset(&byte_array[0], 0x00, byte_array.size()); +} + template struct byte_array_t { + /** + * Size of the array; accessible at compile time. + */ + static const size_t size_ = array_size; + /** * Default to all zeroes */ @@ -306,7 +334,14 @@ struct byte_array_t { /** * Subscript operator to access data content */ - uint8_t& operator[](uint8_t i) { + uint8_t& operator[](size_t i) { + return _value[i]; + } + + /** + * Subscript operator to access data content + */ + uint8_t operator[](size_t i) const { return _value[i]; } @@ -320,7 +355,7 @@ struct byte_array_t { /** * Return the pointer to the buffer holding data. */ - uint8_t* buffer() { + uint8_t* data() { return _value; } @@ -335,6 +370,32 @@ protected: uint8_t _value[array_size]; }; +/** + * Construct a fixed size ArrayView from a byte_array_t. + * + * @param src byte_array_t to create a view from. + * + * @return An ArrayView to @p src. + */ +template +ArrayView make_ArrayView(byte_array_t& src) +{ + return ArrayView(src.data(), src.size()); +} + +/** + * Construct a fixed size ArrayView from a const byte_array_t. + * + * @param src byte_array_t to create a view from. + * + * @return An ArrayView to @p src. + */ +template +ArrayView make_const_ArrayView(const byte_array_t& src) +{ + return ArrayView(src.data(), src.size()); +} + /** 128 bit keys used by paired devices */ typedef byte_array_t<16> irk_t; typedef byte_array_t<16> csrk_t; @@ -358,15 +419,18 @@ typedef byte_array_t<32> public_key_coord_t; /** Diffie-Hellman key */ typedef byte_array_t<32> dhkey_t; +/** counter for signed data writes done by GattClient */ +typedef uint32_t sign_count_t; + /** * MAC address data type. */ struct address_t : public byte_array_t<6> { /** - * Create an invalid mac address, equal to FF:FF:FF:FF:FF:FF + * Create an invalid mac address, equal to 00:00:00:00:00:00 */ address_t() { - memset(_value, 0xFF, sizeof(_value)); + memset(_value, 0x00, sizeof(_value)); } /** @@ -379,6 +443,135 @@ struct address_t : public byte_array_t<6> { } }; +/** + * Type that describes a random device address type. + */ +struct random_address_type_t : SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + STATIC, /**< Random static device address. */ + NON_RESOLVABLE_PRIVATE, /**< Random non resolvable private address. */ + RESOLVABLE_PRIVATE /**< Random resolvable private address. */ + }; + + /** + * Construct a new instance of random_address_type_t. + */ + random_address_type_t(type value) : + SafeEnum(value) { } +}; + +/** + * Security requirement that can be attached to an attribute operation. + */ +struct att_security_requirement_t : SafeEnum { + /** + * Number of bits required to store the value. + * + * This value can be used to define a bitfield that host a value of this + * enum. + */ + static const uint8_t size = 2; + + /** struct scoped enum wrapped by the class */ + enum type { + /** + * The operation does not have security requirements. + * + * It is equivalent to: SecurityMode 1 level 1: No authentication, no + * encryption and no signing required. + * + * @note This security mode is not applicable for signed operation. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK. + */ + NONE, + + /** + * The operation requires security and there's no requirement towards + * peer authentication. + * + * @note Security can be achieved either by signing messages or + * encrypting the link. + * + * @note Signing is only applicable for signed write operations. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM + * or SecurityManager::SECURITY_MODE_SIGNED_NO_MITM. + */ + UNAUTHENTICATED, + + /** + * The operation requires security and the peer must be authenticated. + * + * @note Security can be achieved either by signing messages or + * encrypting the link. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM + * or SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM. + */ + AUTHENTICATED, + + /** + * The operation require encryption with an authenticated peer that + * paired using secure connection pairing. + * + * @note This security mode is not applicable for signed operation; + * security is achieved with link encryption. + */ + SC_AUTHENTICATED + }; + + /** + * Construct a new instance of att_security_requirement_t. + */ + att_security_requirement_t(type value) : + SafeEnum(value) { } +}; + +/** + * Type that describes a peer device address type. + */ +struct peer_address_type_t :SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + /** + * Public device address. + */ + PUBLIC = 0, + + /** + * Random address. + * + * Use Gap::getRandomAddressType to retrieve the type of the random + * address. + */ + RANDOM, + + /** + * A Public address used as a device identity address. + */ + PUBLIC_IDENTITY, + + /** + * A Random static address used as a device identity address. + */ + RANDOM_STATIC_IDENTITY + }; + + /** + * Construct a new instance of peer_address_type_t. + */ + peer_address_type_t(type value) : + SafeEnum(value) { } + + /** + * Default initialization of peer_address_type_t. + */ + peer_address_type_t() : + SafeEnum(PUBLIC) { } +}; + } // namespace ble /** diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index d42c5826fc..aa7d2f6d74 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -121,6 +121,27 @@ class GapAdvertisingData; * gap.startAdvertising(); * @endcode * + * @par Privacy + * + * Privacy is a feature that allows a device to avoid being tracked by other + * (untrusted) devices. The device achieves it by periodically generating a + * new random address. The random address may be a resolvable random address, + * enabling trusted devices to recognise it as belonging to the same + * device. These trusted devices receive an Identity Resolution Key (IRK) + * during pairing. This is handled by the SecurityManager and relies on the + * other device accepting and storing the IRK. + * + * Privacy needs to be enabled by calling enablePrivacy() after having + * initialised the SecurityManager since privacy requires SecurityManager + * to handle IRKs. The behaviour of privacy enabled devices is set by + * using setCentralPrivacyConfiguration() which specifies what the device + * should be with devices using random addresses. Random addresses + * generated by privacy enabled device can be of two types: resolvable + * (by devices who have the IRK) and unresolvable. Unresolvable addresses + * can't be used for connecting and connectable advertising therefore a + * resolvable one will be used for these regardless of the privacy + * configuration. + * * @par Scanning * * Scanning consist of listening for peer advertising packets. From a scan, a @@ -353,6 +374,12 @@ public: * disconnection reason to be transmitted to the peer. */ enum DisconnectionReason_t { + + /** + * GAP or GATT failed to authenticate the peer. + */ + AUTHENTICATION_FAILURE = 0x05, + /** * The connection timed out. * @@ -496,6 +523,16 @@ public: */ typedef ble::connection_handle_t Handle_t; + /** + * Enumeration of random address types. + */ + typedef ble::random_address_type_t RandomAddressType_t; + + /** + * Enumeration of peer address types + */ + typedef ble::peer_address_type_t PeerAddressType_t; + /** * Parameters of a BLE connection. */ @@ -579,6 +616,11 @@ public: * startScan(). */ struct AdvertisementCallbackParams_t { + /** + * Default constructor. + */ + AdvertisementCallbackParams_t(); + /** * BLE address of the device that has advertised the packet. */ @@ -610,9 +652,28 @@ public: const uint8_t *advertisingData; /** - * Type of the address received + * Type of the address received. + * + * @deprecated AddressType_t do not carry enough information to be used + * when privacy is enabled. Use peerAddressType instead. + * + * @note This value should be used in the connect function to establish + * a connection with the peer that has sent this advertisement packet. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "addressType won't work in connect when privacy is enabled; please" + "use peerAddrType" + ) AddressType_t addressType; + + /** + * Type of the address received. + * + * @note This value should be used in the connect function to establish + * a connection with the peer that has sent this advertisement packet. + */ + PeerAddressType_t peerAddrType; }; /** @@ -644,7 +705,15 @@ public: /** * Type of the address the peer uses. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use peerAddressType instead. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use peerAddressType instead." + ) BLEProtocol::AddressType_t peerAddrType; /** @@ -659,7 +728,18 @@ public: /** * Address of the local device. + * + * @deprecated The local address used for the connection may not be known, + * Therefore this field is not reliable. + * + * @note All bytes of the address are set to 0 if not applicable */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "A Bluetooth controller is not supposed to return the address it used" + "to connect. With privacy enabled the controller address may be unknown" + "to the host. There is no replacement for this deprecation." + ) BLEProtocol::AddressBytes_t ownAddr; /** @@ -667,6 +747,53 @@ public: */ const ConnectionParams_t *connectionParams; + /** + * Resolvable address used by the peer. + * + * @note All bytes of the address are set to 0 if not applicable + */ + BLEProtocol::AddressBytes_t peerResolvableAddr; + + /** + * resolvable address of the local device. + * + * @note All bytes of the address are set to 0 if not applicable + */ + BLEProtocol::AddressBytes_t localResolvableAddr; + + /** + * Type of the address the peer uses. + */ + PeerAddressType_t peerAddressType; + + /** + * Construct an instance of ConnectionCallbackParams_t. + * + * @param[in] handleIn Value to assign to handle. + * @param[in] roleIn Value to assign to role. + * @param[in] peerAddrTypeIn Value to assign to peerAddrType. + * @param[in] peerAddrIn Value to assign to peerAddr. + * @param[in] ownAddrTypeIn Value to assign to ownAddrType. + * @param[in] ownAddrIn Value to assign to ownAddr. This may be NULL. + * @param[in] connectionParamsIn Value to assign to connectionParams. + * @param[in] peerResolvableAddrIn Value to assign to peerResolvableAddr. + * @param[in] localResolvableAddrIn Value to assign to localResolvableAddr. + * + * @note Constructor is not meant to be called by user code. + * The BLE API vendor code generates ConnectionCallbackParams_t. + */ + ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + PeerAddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn = NULL, + const uint8_t *localResolvableAddrIn = NULL + ); + /** * Construct an instance of ConnectionCallbackParams_t. * @@ -677,10 +804,21 @@ public: * @param[in] ownAddrTypeIn Value to assign to ownAddrType. * @param[in] ownAddrIn Value to assign to ownAddr. * @param[in] connectionParamsIn Value to assign to connectionParams. + * @param[in] peerResolvableAddrIn Value to assign to peerResolvableAddr. + * @param[in] localResolvableAddrIn Value to assign to localResolvableAddr. * * @note Constructor is not meant to be called by user code. * The BLE API vendor code generates ConnectionCallbackParams_t. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the constructor that accepts a + * PeerAddressType_t instead. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the constructor that accepts a PeerAddressType_t instead." + ) ConnectionCallbackParams_t( Handle_t handleIn, Role_t roleIn, @@ -688,18 +826,18 @@ public: const uint8_t *peerAddrIn, BLEProtocol::AddressType_t ownAddrTypeIn, const uint8_t *ownAddrIn, - const ConnectionParams_t *connectionParamsIn - ) : handle(handleIn), - role(roleIn), - peerAddrType(peerAddrTypeIn), - peerAddr(), - ownAddrType(ownAddrTypeIn), - ownAddr(), - connectionParams(connectionParamsIn) - { - memcpy(peerAddr, peerAddrIn, ADDR_LEN); - memcpy(ownAddr, ownAddrIn, ADDR_LEN); - } + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn = NULL, + const uint8_t *localResolvableAddrIn = NULL + ); + + private: + void constructor_helper( + const uint8_t *peerAddrIn, + const uint8_t *ownAddrIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn + ); }; /** @@ -736,11 +874,119 @@ public: {} }; + /** + * Privacy Configuration of the peripheral role. + * + * @note This configuration also applies to the broadcaster role configuration. + */ + struct PeripheralPrivacyConfiguration_t { + /** + * Indicates if non resolvable random address should be used when the + * peripheral advertises non connectable packets. + * + * Resolvable random address continues to be used for connectable packets. + */ + bool use_non_resolvable_random_address; + + /** + * Resolution strategy for initiator resolvable addresses when a + * connection request is received. + */ + enum ResolutionStrategy { + /** + * Do not resolve the address of the initiator and accept the + * connection request. + */ + DO_NOT_RESOLVE, + + /** + * If a bond is present in the secure database and the address + * resolution fail then reject the connection request with the error + * code AUTHENTICATION_FAILLURE. + */ + REJECT_NON_RESOLVED_ADDRESS, + + /** + * Perform the pairing procedure if the initiator resolvable + * address failed the resolution process. + */ + PERFORM_PAIRING_PROCEDURE, + + /** + * Perform the authentication procedure if the initiator resolvable + * address failed the resolution process. + */ + PERFORM_AUTHENTICATION_PROCEDURE + }; + + /** + * Connection strategy to use when a connection request contains a + * private resolvable address. + */ + ResolutionStrategy resolution_strategy; + }; + + /** + * Privacy Configuration of the central role. + * + * @note This configuration is also used when the local device operates as + * an observer. + */ + struct CentralPrivacyConfiguration_t { + /** + * Indicates if non resolvable random address should be used when the + * central or observer sends scan request packets. + * + * Resolvable random address continue to be used for connection requests. + */ + bool use_non_resolvable_random_address; + + + /** + * Resolution strategy of resolvable addresses received in advertising + * packets. + */ + enum ResolutionStrategy { + /** + * Do not resolve the address received in advertising packets. + */ + DO_NOT_RESOLVE, + + /** + * Resolve the resolvable addresses in the advertising packet and + * forward advertising packet to the application independently of + * the address resolution procedure result. + */ + RESOLVE_AND_FORWARD, + + /** + * Filter out packets containing a resolvable that cannot be resolved + * by this device. + * + * @note Filtering is applied if the local device contains at least + * one bond. + */ + RESOLVE_AND_FILTER + }; + + /** + * Resolution strategy applied to advertising packets received by the + * local device. + */ + ResolutionStrategy resolution_strategy; + }; + /** * Number of microseconds in 1.25 milliseconds. */ static const uint16_t UNIT_1_25_MS = 1250; + static const PeripheralPrivacyConfiguration_t + default_peripheral_privacy_configuration; + + static const CentralPrivacyConfiguration_t + default_central_privacy_configuration; + /** * Convert milliseconds into 1.25ms units. * @@ -844,8 +1090,29 @@ public: * @note Some implementation may refuse to set a new PUBLIC address. * @note Random static address set does not change. * + * @deprecated Starting with mbed-os-5.9.0 this function is deprecated and + * address management is delegated to implementation. Implementations may or + * may not continue to support this function. Compliance with the Bluetooth + * specification and unification of behaviour between implementations are + * the key reasons behind this change: + * - Many implementations do not allow changing of the public address. + * Therefore programs relying on this function are not portable across BLE + * implementations. + * - The Bluetooth specification forbid replacement of the random static + * address; this address can be set once and only once: at startup. + * Depending on the underlying implementation the random address may or + * may not have been set automatically at startup; therefore update of the + * Random Static address after ble initialisation may be a fault. As a + * result calls to this function were not portable. + * Furthermore replacement of the random static address silently + * invalidates the bond stored in the secure database. + * @return BLE_ERROR_NONE on success. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "Non portable API, use enablePrivacy to enable use of private addresses" + ) virtual ble_error_t setAddress( BLEProtocol::AddressType_t type, const BLEProtocol::AddressBytes_t address @@ -865,6 +1132,9 @@ public: * @param[out] typeP Type of the current address set. * @param[out] address Value of the current address. * + * @note If privacy is enabled the device address may be unavailable to + * application code. + * * @return BLE_ERROR_NONE on success. */ virtual ble_error_t getAddress( @@ -880,6 +1150,22 @@ public: return BLE_ERROR_NOT_IMPLEMENTED; } + /** + * Return the type of a random address. + * + * @param[in] address The random address to retrieve the type from. The + * address must be ordered in little endian. + * + * @param[out] addressType Type of the address to fill. + * + * @return BLE_ERROR_NONE in case of success or BLE_ERROR_INVALID_PARAM if + * the address in input was not identifiable as a random address. + */ + static ble_error_t getRandomAddressType( + const BLEProtocol::AddressBytes_t address, + RandomAddressType_t* addressType + ); + /** * Get the minimum advertising interval in milliseconds, which can be used * for connectable advertising types. @@ -956,7 +1242,8 @@ public: * emitted to handlers that have been registered with onConnection(). * * @param[in] peerAddr MAC address of the peer. It must be in LSB format. - * @param[in] peerAddrType Address type of the peer. + * @param[in] peerAddrType Address type of the peer. It is usually obtained + * from advertising frames. * @param[in] connectionParams Connection parameters to use. * @param[in] scanParams Scan parameters used to find the peer. * @@ -964,6 +1251,47 @@ public: * successfully. The connectionCallChain (if set) is invoked upon * a connection event. */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams + ) { + /* Avoid compiler warnings about unused variables. */ + (void)peerAddr; + (void)peerAddrType; + (void)connectionParams; + (void)scanParams; + + /* Requesting action from porter(s): override this API if this capability + is supported. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Initiate a connection to a peer. + * + * Once the connection is established, a ConnectionCallbackParams_t event is + * emitted to handlers that have been registered with onConnection(). + * + * @param[in] peerAddr MAC address of the peer. It must be in LSB format. + * @param[in] peerAddrType Address type of the peer. + * @param[in] connectionParams Connection parameters to use. + * @param[in] scanParams Scan parameters used to find the peer. + * + * @deprecated BLEProtocol::AddressType_t is not able to to carry accurate + * meaning when privacy is in use. Please Uses the connect overload that + * accept a PeerAddressType_t as the peer address type. + * + * @return BLE_ERROR_NONE if connection establishment procedure is started + * successfully. The connectionCallChain (if set) is invoked upon + * a connection event. + */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "This function won't work if privacy is enabled; You must use the overload " + "accepting PeerAddressType_t." + ) virtual ble_error_t connect( const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t peerAddrType, @@ -1001,15 +1329,7 @@ public: DeprecatedAddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams - ) { - return connect( - peerAddr, - (BLEProtocol::AddressType_t) - peerAddrType, - connectionParams, - scanParams - ); - } + ); /** * Initiate a disconnection procedure. @@ -1955,6 +2275,97 @@ public: return BLE_ERROR_NOT_IMPLEMENTED; } + /** + * Enable or disable privacy mode of the local device. + * + * When privacy is enabled, the system use private addresses while it scans, + * advertises or initiate a connection. The device private address is + * renewed every 15 minutes. + * + * @par Configuration + * + * The privacy feature can be configured with the help of the functions + * setPeripheralPrivacyConfiguration and setCentralPrivacyConfiguration + * which respectively set the privacy configuration of the peripheral and + * central role. + * + * @par Default configuration of peripheral role + * + * By default private resolvable addresses are used for all procedures; + * including advertisement of non connectable packets. Connection request + * from an unknown initiator with a private resolvable address triggers the + * pairing procedure. + * + * @par Default configuration of central role + * + * By default private resolvable addresses are used for all procedures; + * including active scanning. Addresses present in advertisement packet are + * resolved and advertisement packets are forwarded to the application + * even if the advertiser private address is unknown. + * + * @param[in] enable Should be set to true to enable the privacy mode and + * false to disable it. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t enablePrivacy(bool enable) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Set the privacy configuration used by the peripheral role. + * + * @param[in] configuration The configuration to set. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Get the privacy configuration used by the peripheral role. + * + * @param[out] configuration The variable filled with the current + * configuration. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Set the privacy configuration used by the central role. + * + * @param[in] configuration The configuration to set. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Get the privacy configuration used by the central role. + * + * @param[out] configuration The variable filled with the current + * configuration. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + private: /** * Set the advertising data and scan response in the vendor subsytem. @@ -2271,6 +2682,36 @@ protected: /* Entry points for the underlying stack to report events back to the user. */ public: + /** + * Notify all registered connection event handlers of a connection event. + * + * @attention This function is meant to be called from the BLE stack specific + * implementation when a connection event occurs. + * + * @param[in] handle Handle of the new connection. + * @param[in] role Role of this BLE device in the connection. + * @param[in] peerAddrType Address type of the connected peer. + * @param[in] peerAddr Address of the connected peer. + * @param[in] ownAddrType Address type this device uses for this + * connection. + * @param[in] ownAddr Address this device uses for this connection. This + * parameter may be NULL if the local address is not available. + * @param[in] connectionParams Parameters of the connection. + * @param[in] peerResolvableAddr Resolvable address used by the peer. + * @param[in] localResolvableAddr resolvable address used by the local device. + */ + void processConnectionEvent( + Handle_t handle, + Role_t role, + PeerAddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr = NULL, + const uint8_t *localResolvableAddr = NULL + ); + /** * Notify all registered connection event handlers of a connection event. * @@ -2285,7 +2726,18 @@ public: * connection. * @param[in] ownAddr Address this device uses for this connection. * @param[in] connectionParams Parameters of the connection. + * @param[in] peerResolvableAddr Resolvable address used by the peer. + * @param[in] localResolvableAddr resolvable address used by the local device. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the overload that accepts a PeerAddressType_t + * instead. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the overload that accepts a PeerAddressType_t instead." + ) void processConnectionEvent( Handle_t handle, Role_t role, @@ -2293,25 +2745,10 @@ public: const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams - ) { - /* Update Gap state */ - state.advertising = 0; - state.connected = 1; - ++connectionCount; - - ConnectionCallbackParams_t callbackParams( - handle, - role, - peerAddrType, - peerAddr, - ownAddrType, - ownAddr, - connectionParams - ); - - connectionCallChain.call(&callbackParams); - } + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr = NULL, + const uint8_t *localResolvableAddr = NULL + ); /** * Notify all registered disconnection event handlers of a disconnection event. @@ -2348,7 +2785,8 @@ public: * @param[in] type Advertising type of the packet. * @param[in] advertisingDataLen Length of the advertisement data received. * @param[in] advertisingData Pointer to the advertisement packet's data. - * @param[in] addressType Type of the address of the peer that has emitted the packet. + * @param[in] addressType Type of the address of the peer that has emitted + * the packet. */ void processAdvertisementReport( const BLEProtocol::AddressBytes_t peerAddr, @@ -2357,22 +2795,43 @@ public: GapAdvertisingParams::AdvertisingType_t type, uint8_t advertisingDataLen, const uint8_t *advertisingData, - BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM_STATIC - ) { - // FIXME: remove default parameter for addressType when ST shield is merged; - // this has been added to mitigate the lack of dependency management in - // testing jobs .... + PeerAddressType_t addressType + ); - AdvertisementCallbackParams_t params; - memcpy(params.peerAddr, peerAddr, ADDR_LEN); - params.rssi = rssi; - params.isScanResponse = isScanResponse; - params.type = type; - params.advertisingDataLen = advertisingDataLen; - params.advertisingData = advertisingData; - params.addressType = addressType; - onAdvertisementReport.call(¶ms); - } + /** + * Forward a received advertising packet to all registered event handlers + * listening for scanned packet events. + * + * @attention This function is meant to be called from the BLE stack specific + * implementation when a disconnection event occurs. + * + * @param[in] peerAddr Address of the peer that has emitted the packet. + * @param[in] rssi Value of the RSSI measured for the received packet. + * @param[in] isScanResponse If true, then the packet is a response to a scan + * request. + * @param[in] type Advertising type of the packet. + * @param[in] advertisingDataLen Length of the advertisement data received. + * @param[in] advertisingData Pointer to the advertisement packet's data. + * @param[in] addressType Type of the address of the peer that has emitted the packet. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the overload that accepts a PeerAddressType_t + * instead. + */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the overload that accepts a PeerAddressType_t instead." + ) + void processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM_STATIC + ); /** * Notify the occurrence of a timeout event to all registered timeout events diff --git a/features/FEATURE_BLE/ble/GattAttribute.h b/features/FEATURE_BLE/ble/GattAttribute.h index 59bb7285bc..b9c6c32e66 100644 --- a/features/FEATURE_BLE/ble/GattAttribute.h +++ b/features/FEATURE_BLE/ble/GattAttribute.h @@ -72,6 +72,9 @@ public: static const Handle_t INVALID_HANDLE = 0x0000; public: + + typedef ble::att_security_requirement_t Security_t; + /** * Construct an attribute. * @@ -102,6 +105,9 @@ public: * true // variable length * ); * @endcode + * + * @note By default, read and write operations are allowed and does not + * require any security. */ GattAttribute( const UUID &uuid, @@ -113,8 +119,12 @@ public: _valuePtr(valuePtr), _lenMax(maxLen), _len(len), + _handle(), _hasVariableLen(hasVariableLen), - _handle() { + _read_allowed(true), + _read_security(Security_t::NONE), + _write_allowed(true), + _write_security(Security_t::NONE) { } public: @@ -209,6 +219,78 @@ public: return _hasVariableLen; } + /** + * Allow or disallow read operation from a client. + * @param allow_read Read is allowed if true. + */ + void allowRead(bool allow_read) + { + _read_allowed = allow_read; + } + + /** + * Indicate if a client is allowed to read the attribute. + * @return true if a client is allowed to read the attribute. + */ + bool isReadAllowed(void) const + { + return _read_allowed; + } + + /** + * Set the security requirements of the read operations. + * @param requirement The security level required by the read operations. + */ + void setReadSecurityRequirement(Security_t requirement) + { + _read_security = requirement.value(); + } + + /** + * Return the security level required by read operations. + * @return The security level of the read operations. + */ + Security_t getReadSecurityRequirement() const + { + return static_cast(_read_security); + } + + /** + * Allow or disallow write operation from a client. + * @param allow_write Write is allowed if true. + */ + void allowWrite(bool allow_write) + { + _write_allowed = allow_write; + } + + /** + * Indicate if a client is allowed to write the attribute. + * @return true if a client is allowed to write the attribute. + */ + bool isWriteAllowed(void) const + { + return _write_allowed; + } + + /** + * Set the security requirements of the write operations. + * @param requirement The security level required by the write operations. + */ + void setWriteSecurityRequirement(Security_t requirement) + { + _write_security = requirement.value(); + } + + /** + * Return the security level required by write operations. + * @return The security level of the write operations. + */ + Security_t getWriteSecurityRequirement() const + { + return static_cast(_write_security); + } + private: /** * Characteristic's UUID. @@ -230,15 +312,35 @@ private: */ uint16_t _len; + /** + * The attribute's handle in the ATT table. + */ + Handle_t _handle; + /** * Whether the length of the value can change throughout time. */ bool _hasVariableLen; /** - * The attribute's handle in the ATT table. + * Whether read is allowed or not. */ - Handle_t _handle; + uint8_t _read_allowed:1; + + /** + * Security applied to the read operation. + */ + uint8_t _read_security: Security_t::size; + + /** + * Whether write is allowed or not. + */ + uint8_t _write_allowed:1; + + /** + * Security applied to the write operation. + */ + uint8_t _write_security: Security_t::size; private: /* Disallow copy and assignment. */ diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 671665f4e5..2f0754b051 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -73,24 +73,23 @@ * of the characteristic. Clients use this handle to interact with the * characteristic. This handle is used locally in GattServer APIs. * + * @par Security requirements * + * Verification of security requirements happens whenever a client request to + * read the characteristic; write it or even register to its updates. Different + * requirements may be defined for these three type of operation. As an example: + * it is possible to define a characteristic that do not require security to be + * read and require an authenticated link to be written. * + * By default all security requirements are set to att_security_requirement_t::NONE + * except if the characteristic supports signed write; in such case the security + * requirement for write operations is set to att_security_requirement_t::UNAUTHENTICATED. * - * - * - * - * - * Representation of a GattServer characteristic. - * - * A characteristic is a typed value used in a service. It contains a set of - * properties that define client operations supported by the characteristic. - * A characteristic may also include descriptors; a descriptor exposes - * metainformation associated to a characteristic, such as the unit of its value, - * its human readable name or a control point attribute that allows the client to - * subscribe to the characteristic notifications. - * - * The GattCharacteristic class allows application code to construct - * and monitor characteristics presents in a GattServer. + * @note If a peer uses an operation that is not set in the characteristic + * properties then the request request is discarded regardless of the security + * requirements and current security level. The only exception being signed + * write: signed write are converted into regular write without response if + * the link is encrypted. */ class GattCharacteristic { public: @@ -1276,9 +1275,40 @@ public: * defines additional characteristic properties. */ BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES = 0x80 - }; + /** + * Indicates if the properties has at least one of the writable flags. + * + * @param[in] properties The properties to inspect. + * + * @return True if the properties set at least one of the writable flags and + * false otherwise. + */ + static bool isWritable(uint8_t properties) + { + const uint8_t writable = + BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | + BLE_GATT_CHAR_PROPERTIES_WRITE | + BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; + + return properties & writable; + } + + /** + * Indicates if the properties is readable. + * + * @param[in] properties The properties to inspect. + * + * @return True if the properties has its readable flag set and false + * otherwise. + */ + static bool isReadable(uint8_t properties) + { + const uint8_t readable = BLE_GATT_CHAR_PROPERTIES_READ; + return properties & readable; + } + /** * Value of a Characteristic Presentation Format descriptor. * @@ -1327,6 +1357,11 @@ public: }; + /** + * Security level applied to GATT operations. + */ + typedef ble::att_security_requirement_t SecurityRequirement_t; + /** * @brief Constructs a new GattCharacteristic. * @@ -1371,13 +1406,21 @@ public: bool hasVariableLen = true ) : _valueAttribute(uuid, valuePtr, len, maxLen, hasVariableLen), _properties(props), - _requiredSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK), _descriptors(descriptors), _descriptorCount(numDescriptors), - enabledReadAuthorization(false), - enabledWriteAuthorization(false), readAuthorizationCallback(), - writeAuthorizationCallback() { + writeAuthorizationCallback(), + _update_security(SecurityRequirement_t::NONE) { + _valueAttribute.allowWrite(isWritable(_properties)); + _valueAttribute.allowRead(isReadable(_properties)); + + // signed writes requires at least an unauthenticated CSRK or an + // unauthenticated ltk if the link is encrypted. + if (_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) { + _valueAttribute.setWriteSecurityRequirement( + SecurityRequirement_t::UNAUTHENTICATED + ); + } } public: @@ -1387,10 +1430,120 @@ public: * * @param[in] securityMode Can be one of encryption or signing, with or * without protection for man in the middle attacks (MITM). + * + * @deprecated Fine grained security check has been added to with mbed OS + * 5.9. It is possible to set independently security requirements for read, + * write and update operations. In the meantime SecurityManager::SecurityMode_t + * is not used anymore to represent security requirements as it maps + * incorrectly the Bluetooth standard. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "Use setWriteSecurityRequirements, setReadSecurityRequirements and " + "setUpdateSecurityRequirements" + ) void requireSecurity(SecurityManager::SecurityMode_t securityMode) { - _requiredSecurity = securityMode; + SecurityRequirement_t sec_requirements = SecurityModeToAttSecurity(securityMode); + + _valueAttribute.setReadSecurityRequirement(sec_requirements); + _valueAttribute.setWriteSecurityRequirement(sec_requirements); + _update_security = sec_requirements.value(); + } + + /** + * Set all security requirements of the characteristic. + * + * @param read_security The security requirement of the read operations. + * @param write_security The security requirement of write operations. + * @param update_security The security requirement of update operations. + */ + void setSecurityRequirements( + SecurityRequirement_t read_security, + SecurityRequirement_t write_security, + SecurityRequirement_t update_security + ) { + setReadSecurityRequirement(read_security); + setWriteSecurityRequirement(write_security); + setUpdateSecurityRequirement(update_security); + } + + /** + * Set the security of the read operation. + * + * @param[in] security The security requirement of the read operation. + */ + void setReadSecurityRequirement(SecurityRequirement_t security) + { + _valueAttribute.setReadSecurityRequirement(security); + } + + /** + * Get the security requirement of the read operation. + * + * @return The security requirement of the read operation. + */ + SecurityRequirement_t getReadSecurityRequirement() const + { + return _valueAttribute.getReadSecurityRequirement(); + } + + /** + * Set the security requirement of the write operations. + * + * @note If the signed write flag is set in the characteristic properties + * then the security requirement applied to write operation must be either + * AUTHENTICATED or UNAUTHENTICATED. Security requirements NONE and + * SC_AUTHENTICATED are not applicable to signing operation. + * + * @param[in] security The security requirement of write operations. + */ + void setWriteSecurityRequirement(SecurityRequirement_t security) + { + MBED_ASSERT( + ((_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) && + ((security == SecurityRequirement_t::NONE) || + (security == SecurityRequirement_t::SC_AUTHENTICATED))) == false + ); + _valueAttribute.setWriteSecurityRequirement(security); + } + + /** + * Get the security requirement of write operations. + * + * @return The security requirement of write operations. + */ + SecurityRequirement_t getWriteSecurityRequirement() const + { + return _valueAttribute.getWriteSecurityRequirement(); + } + + /** + * Set the security requirement of update operations. + * + * @note This security requirement is also applied to the write operation of + * the Client Characteristic Configuration Descriptor. + * + * @param[in] security The security requirement that must be met to send + * updates and accept write of the CCCD. + */ + void setUpdateSecurityRequirement(SecurityRequirement_t security) + { + _update_security = security.value(); + } + + /** + * Get the security requirement of update operations. + * + * @note This security requirement is also applied to the write operation of + * the Client Characteristic Configuration Descriptor. + * + * @return The security requirement that must be met to send updates and + * accept write of the CCCD. + */ + SecurityRequirement_t getUpdateSecurityRequirement() const + { + return static_cast(_update_security); } public: @@ -1407,7 +1560,6 @@ public: void (*callback)(GattWriteAuthCallbackParams *) ) { writeAuthorizationCallback.attach(callback); - enabledWriteAuthorization = true; } /** @@ -1428,7 +1580,6 @@ public: void (T::*member)(GattWriteAuthCallbackParams *) ) { writeAuthorizationCallback.attach(object, member); - enabledWriteAuthorization = true; } /** @@ -1445,7 +1596,6 @@ public: void (*callback)(GattReadAuthCallbackParams *) ) { readAuthorizationCallback.attach(callback); - enabledReadAuthorization = true; } /** @@ -1467,7 +1617,6 @@ public: void (T::*member)(GattReadAuthCallbackParams *) ) { readAuthorizationCallback.attach(object, member); - enabledReadAuthorization = true; } /** @@ -1580,10 +1729,54 @@ public: * Get the characteristic's required security. * * @return The characteristic's required security. + * + * @deprecated Fine grained security check has been added to with mbed OS + * 5.9. It is possible to set independently security requirements for read, + * write and update operations. In the meantime SecurityManager::SecurityMode_t + * is not used anymore to represent security requirements as it maps + * incorrectly the Bluetooth standard. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "Use getWriteSecurityRequirements, getReadSecurityRequirements and " + "getUpdateSecurityRequirements" + ) SecurityManager::SecurityMode_t getRequiredSecurity() const { - return _requiredSecurity; + SecurityRequirement_t max_sec = std::max( + std::max( + getReadSecurityRequirement(), + getWriteSecurityRequirement() + ), + getUpdateSecurityRequirement() + ); + + bool needs_signing = + _properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; + + switch(max_sec.value()) { + case SecurityRequirement_t::NONE: + MBED_ASSERT(needs_signing == false); + return SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; + + case SecurityRequirement_t::UNAUTHENTICATED: + return (needs_signing) ? + SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : + SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; + + case SecurityRequirement_t::AUTHENTICATED: + return (needs_signing) ? + SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : + SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; + + case SecurityRequirement_t::SC_AUTHENTICATED: + MBED_ASSERT(needs_signing == false); + // fallback to encryption with MITM + return SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; + default: + MBED_ASSERT(false); + return SecurityManager::SECURITY_MODE_NO_ACCESS; + } } /** @@ -1606,7 +1799,7 @@ public: */ bool isReadAuthorizationEnabled() const { - return enabledReadAuthorization; + return readAuthorizationCallback; } /** @@ -1619,7 +1812,7 @@ public: */ bool isWriteAuthorizationEnabled() const { - return enabledWriteAuthorization; + return writeAuthorizationCallback; } /** @@ -1640,6 +1833,39 @@ public: } private: + + /** + * Loosely convert a SecurityManager::SecurityMode_t into a + * SecurityRequirement_t. + * + * @param[in] mode The security mode to convert + * + * @return The security requirement equivalent to the security mode in input. + */ + SecurityRequirement_t SecurityModeToAttSecurity( + SecurityManager::SecurityMode_t mode + ) { + switch(mode) { + case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: + case SecurityManager::SECURITY_MODE_NO_ACCESS: + // assuming access is managed by property and orthogonal to + // security mode ... + return SecurityRequirement_t::NONE; + + case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: + case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: + return SecurityRequirement_t::UNAUTHENTICATED; + + case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: + case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: + return SecurityRequirement_t::AUTHENTICATED; + + default: + // should not happens; makes the compiler happy. + return SecurityRequirement_t::NONE; + } + } + /** * Attribute that contains the actual value of this characteristic. */ @@ -1651,11 +1877,6 @@ private: */ uint8_t _properties; - /** - * The characteristic's required security. - */ - SecurityManager::SecurityMode_t _requiredSecurity; - /** * The characteristic's descriptor attributes. */ @@ -1666,16 +1887,6 @@ private: */ uint8_t _descriptorCount; - /** - * Whether read authorization is enabled. - */ - bool enabledReadAuthorization; - - /** - * Whether write authorization is enabled. - */ - bool enabledWriteAuthorization; - /** * The registered callback handler for read authorization reply. */ @@ -1688,6 +1899,14 @@ private: FunctionPointerWithContext writeAuthorizationCallback; + /** + * Security requirements of update operations. + * + * The peer must meet the security requirement to enable, disable and + * receive updates + */ + uint8_t _update_security: SecurityRequirement_t::size; + private: /* Disallow copy and assignment. */ GattCharacteristic(const GattCharacteristic &); diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index 137304bc23..cabfaf9a19 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -116,6 +116,15 @@ public: * The server does not acknowledge the status of the operation. */ GATT_OP_WRITE_CMD = 0x02, + + /** + * Signed Write command. + * + * It is used to request the server to write the value of an attribute + * using a signed packet. The server does not acknowledge the status + * of the operation. + */ + GATT_OP_SIGNED_WRITE_CMD = 0x03 }; /** diff --git a/features/FEATURE_BLE/ble/SafeEnum.h b/features/FEATURE_BLE/ble/SafeEnum.h index 0f9a0a5554..eed1b8b7e1 100644 --- a/features/FEATURE_BLE/ble/SafeEnum.h +++ b/features/FEATURE_BLE/ble/SafeEnum.h @@ -139,6 +139,57 @@ struct SafeEnum { return !(lhs == rhs); } + /** + * Less than operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is less than rhs and false otherwise. + */ + friend bool operator<(SafeEnum lhs, SafeEnum rhs) { + return lhs.value() < rhs.value(); + } + + /** + * Less than or equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is less than or equal to rhs and + * false otherwise. + */ + friend bool operator<=(SafeEnum lhs, SafeEnum rhs) { + return lhs.value() < rhs.value() || lhs == rhs; + } + + /** + * Greater than operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is greater than rhs; false + * otherwise. + */ + friend bool operator>(SafeEnum lhs, SafeEnum rhs) { + return !(lhs <= rhs); + } + + /** + * Greater than or equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is greater than or equal to rhs; + * false otherwise. + */ + friend bool operator>=(SafeEnum lhs, SafeEnum rhs) { + return !(lhs < rhs); + } + /** * Explicit access to the inner value of the SafeEnum instance. */ diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index a01882959a..6f9f4c83ed 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -31,7 +31,9 @@ * and/or exchanging keys used for the current connection. Bonding means saving this information so that * it can later be used after reconnecting without having to pair again. This saves time and power. * - * There are many ways to provide these at different levels of security depending on your requirements + * @par Paring + * + * There are several ways to provide different levels of security during pairing depending on your requirements * and the facilities provided by the application. The process starts with initialising the SecurityManager * with default options for new connections. Some settings can later be changed per link or globally. * @@ -43,6 +45,8 @@ * You can change the IO capabilities after initialisation with setIoCapability(). This will take effect * for all subsequent pairings. * + * @par Out of Band data used in pairing + * * Sharing this information through IO capabilities means user interaction which limits the degree of * protection due to the limit of the amount of data that we can expect the user to transfer. Another * solution is using OOB (out of band) communication to transfer this data instead which can send much @@ -57,7 +61,27 @@ * it. If either side doesn't support it Legacy Pairing will be used. This is an older standard of pairing. * If higher security is required legacy pairing can be disabled by calling allowLegacyPairing(false); * - * \par How to use + * @par Signing + * + * Applications may require a level of security providing confidence that data transfers are coming + * from a trusted source. This can be achieved by encrypting the link which also provides added confidentiality. + * Encryption is a good choice when a device stays connected but introduces latency due to the need of encrypting the + * link if the device only connects periodically to transfer data. If confidentiality is not required data GATT + * server may allow writes to happen over an unencrypted link but authenticated by a signature present in each packet. + * This signature relies on having sent a signing key to the peer during pairing prior to sending any signed packets. + * + * @par Persistence of Security information + * + * Security Manager stores all the data required for its operation on active links. Depending on resources + * available on the device it will also attempt to store data for disconnected devices which have bonded to be + * reused when reconnected. + * + * If the application has initialised a filesystem and the Security Manager has been provided with a + * filepath during the init() call it may also provide data persistence across resets. This must be enabled by + * calling preserveBondingStateOnReset(). Persistence is not guaranteed and may fail if abnormally terminated. + * The Security Manager may also fall back to a non-persistent implementation if the resources are too limited. + * + * @par How to use * * First thing you need to do is to initialise the manager by calling init() with your chosen settings. * @@ -87,7 +111,7 @@ * accetPairing() or cancelPairing(). The result will be communicated on both peers through an event calling * pairingResult() in the EventHandler. * - * \par Sequence diagrams + * @par Sequence diagrams * * Sequence diagram "Just Works" pairing * @@ -103,7 +127,7 @@ * | | |<---[pairing complete]----->| | | * |<- pairingResult() <---------------| |----------------> pairingResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * * @note the requestPairing() call isn't required to trigger pairing. Pairing will also be triggered * if you request encryption and authentication and no bonding information is available. The sequence will @@ -121,7 +145,7 @@ * | | |<-[encryption established]->| | | * |<- linkEncryptionResult() <--------| |---------> linkEncryptionResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * * @note if bonding information is not available, pairing will be triggered * @@ -149,7 +173,7 @@ * | | |<---[pairing complete]----->| | | * |<- pairingResult() <---------------| |----------------> pairingResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * */ @@ -417,6 +441,9 @@ public: * support out-of-band exchanges of security data. * @param[in] passkey To specify a static passkey. * @param[in] signing Generate and distribute signing key during pairing + * @param[in] dbFilepath Path to the file used to store keys in the filesystem, + * if NULL keys will be only stored in memory + * * * @return BLE_ERROR_NONE on success. */ @@ -424,16 +451,34 @@ public: bool requireMITM = true, SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, - bool signing = true) { + bool signing = true, + const char *dbFilepath = NULL) { /* Avoid compiler warnings about unused variables. */ (void)enableBonding; (void)requireMITM; (void)iocaps; (void)passkey; + (void)dbFilepath; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ } + /** + * Change the file used for the security database. If path is invalid or a NULL is passed + * keys will only be stored in memory. + * + * @note This operation is only allowed with no active connections. + * + * @param[in] dbFilepath Path to the file used to store keys in the filesystem, + * if NULL keys will be only stored in memory + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t setDatabaseFilepath(const char *dbFilepath = NULL) { + (void)dbFilepath; + return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ + } + /** * Notify all registered onShutdown callbacks that the SecurityManager is * about to be shutdown and clear all SecurityManager state of the @@ -736,13 +781,47 @@ public: // /** - * Enable OOB data usage during paring. + * Generate OOB data with the given address. If Secure Connections is supported this will + * also generate Secure Connections OOB data on top of legacy pairing OOB data. This can be used + * to generate such data before the connection takes place. + * + * In this model the OOB exchange takes place before the devices connect. Devices should establish + * communication over another channel and exchange the OOB data. The address provided will be used + * by the peer to associate the received data with the address of the device it will then connect + * to over BLE. + * + * @param[in] address The local address you will use in the connection using this OOB data. This + * address will be returned along with the rest of the OOB data when generation + * is complete. Using an invalid address is illegal. + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + virtual ble_error_t generateOOB(const ble::address_t *address) { + /* Avoid compiler warnings about unused variables */ + (void) address; + return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ + } + + /** + * Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will + * generate Secure Connections OOB data through oobGenerated() on top of legacy pairing OOB data. + * + * You do not have to call this function to return received OOB data. Use legacyPairingOobReceived + * or oobReceived to hand it in. This will allow the stack to use it if possible. You only need to + * call this function to attempt legacy OOB data exchange after pairing start and to inform + * the stack OOB data does not provide MITM protection (by default it is set to provide this). + * + * In this model the OOB exchange takes places after the devices have connected but possibly + * prior to pairing. For secure connections pairing must not be started until after the OOB + * data has been sent and/or received. The address in the OOB data generated will match + * the original address used to establish the connection and will be used by the peer to + * identify which connection the OOB data belongs to. * * @param[in] connectionHandle Handle to identify the connection. * @param[in] useOOB If set to true, authenticate using OOB data. * @param[in] OOBProvidesMITM If set to true keys exchanged during pairing using OOB data - * will provide MITM protection. This indicates that the form - * of exchange used by the OOB data itself provides MITM protection. + * will provide Man-in-the-Middle protection. This indicates that + * the form of exchange used by the OOB data itself provides MITM + * protection. * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ virtual ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true) { @@ -933,15 +1012,31 @@ public: */ ble_error_t getLinkSecurity(ble::connection_handle_t connectionHandle, LinkSecurityStatus_t *securityStatus) { ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); - ble_error_t status = getLinkEncryption(connectionHandle, &encryption); - /* legacy support limits the return values */ - if (encryption.value() == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { - *securityStatus = ENCRYPTED; - } else { - *securityStatus = (LinkSecurityStatus_t)encryption.value(); + ble_error_t err = getLinkEncryption(connectionHandle, &encryption); + if (err) { + return err; } - return status; + switch (encryption.value()) { + case ble::link_encryption_t::NOT_ENCRYPTED: + *securityStatus = NOT_ENCRYPTED; + break; + case ble::link_encryption_t::ENCRYPTION_IN_PROGRESS: + *securityStatus = ENCRYPTION_IN_PROGRESS; + break; + case ble::link_encryption_t::ENCRYPTED: + case ble::link_encryption_t::ENCRYPTED_WITH_MITM: + case ble::link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM: + *securityStatus = ENCRYPTED; + break; + default: + // should never happen + MBED_ASSERT(false); + *securityStatus = NOT_ENCRYPTED; + break; + } + + return BLE_ERROR_NONE; } /** @@ -1045,7 +1140,10 @@ private: SecurityManager::SecurityMode_t securityMode; if (result == ble::link_encryption_t::ENCRYPTED) { securityMode = SECURITY_MODE_ENCRYPTION_NO_MITM; - } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { + } else if ( + result == ble::link_encryption_t::ENCRYPTED_WITH_MITM || + result == ble::link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { securityMode = SECURITY_MODE_ENCRYPTION_WITH_MITM; } else { securityMode = SECURITY_MODE_ENCRYPTION_OPEN_LINK; diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h new file mode 100644 index 0000000000..4c57d67005 --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -0,0 +1,157 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GENERIC_FILE_SECURITY_DB_H_ +#define GENERIC_FILE_SECURITY_DB_H_ + +#include "SecurityDb.h" + +#include + +namespace ble { +namespace generic { + +/** Filesystem implementation */ +class FileSecurityDb : public SecurityDb { +private: + + struct entry_t { + SecurityDistributionFlags_t flags; + sign_count_t peer_sign_counter; + size_t file_offset; + }; + + static const size_t MAX_ENTRIES = 5; + + static entry_t* as_entry(entry_handle_t db_handle) { + return reinterpret_cast(db_handle); + } + + template + void db_read(T *value, long int offset) { + fseek(_db_file, offset, SEEK_SET); + fread(value, sizeof(T), 1, _db_file); + } + + template + void db_write(T *value, long int offset) { + fseek(_db_file, offset, SEEK_SET); + fwrite(value, sizeof(T), 1, _db_file); + } + +public: + FileSecurityDb(FILE *db_file); + virtual ~FileSecurityDb(); + + /** + * Validates or creates a file for the security database. + * @param db_path path to the file + * @return FILE handle open and ready for use by the database or NULL if unavailable + */ + static FILE* open_db_file(const char *db_path); + + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle + ); + + + /* local keys */ + + /* set */ + virtual void set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k + ); + + virtual void set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ); + + /* peer's keys */ + + /* set */ + + virtual void set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k + ); + + virtual void set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ); + + virtual void set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk + ); + + virtual void set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address + ); + + virtual void set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk + ); + + virtual void set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter + ); + + /* saving and loading from nvm */ + + virtual void restore(); + + virtual void sync(entry_handle_t db_handle); + + virtual void set_restore(bool reload); + +private: + virtual uint8_t get_entry_count(); + + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index); + + virtual void reset_entry(entry_handle_t db_handle); + + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle); + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle); + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle); + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle); + + /** + * Zero the db file. + * @param db_file filehandle for file to erase + * @return filehandle when successful, otherwise NULL + */ + static FILE* erase_db_file(FILE* db_file); + +private: + entry_t _entries[MAX_ENTRIES]; + FILE *_db_file; + uint8_t _buffer[sizeof(SecurityEntryKeys_t)]; +}; + +} /* namespace pal */ +} /* namespace ble */ + +#endif /*GENERIC_FILE_SECURITY_DB_H_*/ diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index e6b72b6866..33fa638fda 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -23,6 +23,7 @@ #include "ble/BLEProtocol.h" #include "ble/Gap.h" #include "ble/pal/PalGap.h" +#include "ble/pal/PalSecurityManager.h" #include "ble/pal/GapEvents.h" #include "ble/pal/GapTypes.h" #include "ble/BLETypes.h" @@ -55,11 +56,15 @@ public: * * @param generic_access_service Platform abstraction instance managing * the GATT generic access service. + * + * @param pal_sm Security Manager Platform abstraction instance containing the base + * Security Manager primitives. */ GenericGap( pal::EventQueue &event_queue, pal::Gap &pal_gap, - pal::GenericAccessService &generic_access_service + pal::GenericAccessService &generic_access_service, + pal::SecurityManager &pal_sm ); /** @@ -108,6 +113,16 @@ public: */ virtual ble_error_t stopScan(); + /** + * @see Gap::connect + */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams + ); + /** * @see Gap::connect */ @@ -233,6 +248,39 @@ public: */ virtual ble_error_t initRadioNotification(void); + /** + * @see Gap::enablePrivacy + */ + virtual ble_error_t enablePrivacy(bool enable); + + /** + * @see Gap::setPeripheralPrivacyConfiguration + */ + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::getPeripheralPrivacyConfiguration + */ + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::setCentralPrivacyConfiguration + */ + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::getCentralPrivacyConfiguration + */ + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); + /** * @see Gap::setAdvertisingData */ @@ -257,11 +305,13 @@ public: void processConnectionEvent( Handle_t handle, Role_t role, - BLEProtocol::AddressType_t peerAddrType, + peer_address_type_t peerAddrType, const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr ); /** @@ -302,21 +352,45 @@ private: void on_unexpected_error(const pal::GapUnexpectedErrorEvent &e); - pal::own_address_type_t get_own_address_type(); + enum AddressUseType_t { + CENTRAL_CONNECTION, + CENTRAL_SCAN, + PERIPHERAL_CONNECTABLE, + PERIPHERAL_NON_CONNECTABLE + }; + + pal::own_address_type_t get_own_address_type(AddressUseType_t address_use_type); bool initialize_whitelist() const; + ble_error_t update_address_resolution_setting(); + + void set_random_address_rotation(bool enable); + + void update_random_address(); + + void on_address_rotation_timeout(); + pal::EventQueue& _event_queue; pal::Gap &_pal_gap; pal::GenericAccessService &_gap_service; + pal::SecurityManager &_pal_sm; BLEProtocol::AddressType_t _address_type; ble::address_t _address; pal::initiator_policy_t _initiator_policy_mode; pal::scanning_filter_policy_t _scanning_filter_policy; pal::advertising_filter_policy_t _advertising_filter_policy; mutable Whitelist_t _whitelist; + + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + ble::address_t _random_static_identity_address; + bool _random_address_rotating; + mbed::Timeout _advertising_timeout; mbed::Timeout _scan_timeout; + mbed::Ticker _address_rotation_ticker; pal::ConnectionEventMonitor::EventHandler *_connection_event_handler; }; diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h index f0a8462ff9..7dbb0e185d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGattClient.h +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -20,6 +20,7 @@ #include #include "ble/GattClient.h" #include "ble/pal/PalGattClient.h" +#include "ble/pal/SigningEventMonitor.h" // IMPORTANT: private header. Not part of the public interface. @@ -31,7 +32,8 @@ namespace generic { * It requires a pal::GattClient injected at construction site. * @attention: Not part of the public interface of BLE API. */ -class GenericGattClient : public GattClient { +class GenericGattClient : public GattClient, + public pal::SigningEventMonitor { public: /** * Create a GenericGattClient from a pal::GattClient @@ -114,6 +116,11 @@ public: */ virtual ble_error_t reset(void); + /** + * @see ble::pal::SigningEventMonitor::set_signing_event_handler + */ + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *signing_event_handler); + private: struct ProcedureControlBlock; struct DiscoveryControlBlock; @@ -136,6 +143,7 @@ private: pal::GattClient* const _pal_client; ServiceDiscovery::TerminationCallback_t _termination_callback; + pal::SigningEventMonitor::EventHandler* _signing_event_handler; mutable ProcedureControlBlock* control_blocks; bool _is_reseting; }; diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 0164376513..928ba19d05 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -19,11 +19,13 @@ #include "ble/pal/GapTypes.h" #include "ble/BLETypes.h" -#include "ble/pal/SecurityDb.h" +#include "ble/generic/SecurityDb.h" #include "platform/Callback.h" #include "ble/pal/ConnectionEventMonitor.h" +#include "ble/pal/SigningEventMonitor.h" #include "ble/generic/GenericGap.h" #include "ble/pal/PalSecurityManager.h" +#include "ble/ArrayView.h" namespace ble { namespace generic { @@ -32,10 +34,9 @@ typedef SecurityManager::SecurityIOCapabilities_t SecurityIOCapabilities_t; class GenericSecurityManager : public SecurityManager, public pal::SecurityManager::EventHandler, - public pal::ConnectionEventMonitor::EventHandler { + public pal::ConnectionEventMonitor::EventHandler, + public pal::SigningEventMonitor::EventHandler { public: - typedef ble::pal::SecurityDistributionFlags_t SecurityDistributionFlags_t; - typedef ble::pal::SecurityEntryKeys_t SecurityEntryKeys_t; /* implements SecurityManager */ @@ -48,9 +49,12 @@ public: bool mitm = true, SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, - bool signing = true + bool signing = true, + const char* db_path = NULL ); + virtual ble_error_t setDatabaseFilepath(const char *db_path = NULL); + virtual ble_error_t reset(); virtual ble_error_t preserveBondingStateOnReset( @@ -192,6 +196,10 @@ public: // MITM // + virtual ble_error_t generateOOB( + const address_t *address + ); + virtual ble_error_t setOOBDataUsage( connection_handle_t connection, bool useOOB, @@ -229,18 +237,27 @@ public: public: GenericSecurityManager( pal::SecurityManager &palImpl, - pal::SecurityDb &dbImpl, - pal::ConnectionEventMonitor &connMonitorImpl + pal::ConnectionEventMonitor &connMonitorImpl, + pal::SigningEventMonitor &signingMonitorImpl ) : _pal(palImpl), - _db(dbImpl), _connection_monitor(connMonitorImpl), + _signing_monitor(signingMonitorImpl), + _db(NULL), _default_authentication(0), _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), _legacy_pairing_allowed(true), - _master_sends_keys(false), - _public_keys_generated(false) { + _master_sends_keys(false) { _pal.set_event_handler(this); + + /* We create a fake value for oob to allow creation of the next oob which needs + * the last process to finish first before restarting (this is to simplify checking). + * This fake value will not be used as the oob address is currently invalid */ + _oob_local_random[0] = 1; + } + + ~GenericSecurityManager() { + delete _db; } //////////////////////////////////////////////////////////////////////////// @@ -248,6 +265,22 @@ public: // private: + + /** + * Initialise the database, if database already exists it will close it and open the new one. + * + * @param db_path path to file to store secure db + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + ble_error_t init_database(const char *db_path = NULL); + + /** + * Generate identity list based on the database of IRK and apply it to the resolving list. + * + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + ble_error_t init_resolving_list(); + /** * Generate the CSRK if needed. * @@ -295,7 +328,7 @@ private: * @param[in] entryKeys security entry containing keys. */ void enable_encryption_cb( - pal::SecurityDb::entry_handle_t entry, + SecurityDb::entry_handle_t entry, const SecurityEntryKeys_t* entryKeys ); @@ -306,7 +339,7 @@ private: * @param[in] entryKeys security entry containing keys. */ void set_ltk_cb( - pal::SecurityDb::entry_handle_t entry, + SecurityDb::entry_handle_t entry, const SecurityEntryKeys_t* entryKeys ); @@ -314,23 +347,23 @@ private: * Returns the CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. - * @param[in] entryKeys security entry containing keys. + * @param[in] signing connection signature resolving key and counter. */ void return_csrk_cb( - pal::SecurityDb::entry_handle_t connection, - const csrk_t *csrk + SecurityDb::entry_handle_t connection, + const SecurityEntrySigning_t *signing ); -#if defined(MBEDTLS_CMAC_C) /** - * Generate local OOB data to be sent to the application which sends it to the peer. + * Set the peer CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. + * @param[in] signing connection signature resolving key and counter. */ - void generate_secure_connections_oob( - connection_handle_t connection + void set_peer_csrk_cb( + SecurityDb::entry_handle_t connection, + const SecurityEntrySigning_t *signing ); -#endif /** * Updates the entry for the connection with OOB data presence. @@ -341,26 +374,6 @@ private: connection_handle_t connection ); -#if defined(MBEDTLS_CMAC_C) - /** - * Calculate the confirmation value for secure connections OOB data based - * on local public key and a random number. - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.2.6 - - * @param[in] U public key x component - * @param[in] V public key y component - * @param[in] X random number - * @param[out] confirm confirmation value - * @return true if cryptography functioned worked - */ - static bool crypto_toolbox_f4( - const public_key_coord_t &U, - const public_key_coord_t &V, - const oob_lesc_value_t &X, - oob_confirm_t &confirm - ); -#endif - /** * Set the MITM protection setting on the database entry * @@ -386,7 +399,7 @@ private: virtual void on_connected( connection_handle_t connection, Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, @@ -406,25 +419,32 @@ private: ); /** - * Inform the security manager of a new connection. - * - * @param[in] params information about the new connection. + * Callback invoked by the secure DB when an identity entry has been + * retrieved. + * @param entry Handle of the entry. + * @param identity The identity associated with the entry; may be NULL. */ - void connection_callback( - const Gap::ConnectionCallbackParams_t* params + void on_security_entry_retrieved( + SecurityDb::entry_handle_t entry, + const SecurityEntryIdentity_t* identity ); /** - * Inform the security manager that a connection ended. + * Callback invoked by the secure DB when the identity list has been + * retrieved. * - * @param[in] params handle and reason of the disconnection. + * @param identity View to the array passed to the secure DB. It contains + * identity entries retrieved. + * + * @param count Number of identities entries retrieved. */ - void disconnection_callback( - const Gap::DisconnectionCallbackParams_t* params + void on_identity_list_retrieved( + ble::ArrayView& identity_list, + size_t count ); private: - struct ControlBlock_t : public pal::SecurityDistributionFlags_t { + struct ControlBlock_t { ControlBlock_t(); pal::KeyDistribution get_initiator_key_distribution() { @@ -441,7 +461,7 @@ private: }; connection_handle_t connection; - pal::SecurityDb::entry_handle_t db_entry; + SecurityDb::entry_handle_t db_entry; address_t local_address; /**< address used for connection, possibly different from identity */ @@ -465,11 +485,25 @@ private: uint8_t attempt_oob:1; uint8_t oob_mitm_protection:1; uint8_t oob_present:1; + uint8_t legacy_pairing_oob_request_pending:1; + + uint8_t csrk_failures:2; }; pal::SecurityManager &_pal; - pal::SecurityDb &_db; pal::ConnectionEventMonitor &_connection_monitor; + pal::SigningEventMonitor &_signing_monitor; + + SecurityDb *_db; + + /* OOB data */ + address_t _oob_local_address; + address_t _oob_peer_address; + oob_lesc_value_t _oob_peer_random; + oob_confirm_t _oob_peer_confirm; + oob_lesc_value_t _oob_local_random; + address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */ + oob_tk_t _oob_temporary_key; /**< used for legacy pairing */ pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; @@ -477,13 +511,6 @@ private: bool _pairing_authorisation_required; bool _legacy_pairing_allowed; bool _master_sends_keys; - bool _public_keys_generated; - - /** There is always only one OOB data set stored at a time */ - address_t _peer_sc_oob_address; - oob_lesc_value_t _peer_sc_oob_random; - oob_confirm_t _peer_sc_oob_confirm; - oob_lesc_value_t _local_sc_oob_random; static const size_t MAX_CONTROL_BLOCKS = 5; ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS]; @@ -533,6 +560,23 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_signed_write_received + */ + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ); + + /** @copydoc ble::pal::SecurityManager::on_signed_write_verification_failure + */ + virtual void on_signed_write_verification_failure( + connection_handle_t connection + ); + + /** @copydoc ble::pal::SecurityManager::on_signed_write + */ + virtual void on_signed_write(); + /** @copydoc ble::pal::SecurityManager::on_slave_security_request */ virtual void on_slave_security_request( @@ -587,31 +631,29 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_request + */ + virtual void on_secure_connections_oob_request( + connection_handle_t connection + ); + /** @copydoc ble::pal::SecurityManager::on_legacy_pairing_oob_request */ virtual void on_legacy_pairing_oob_request( connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_oob_data_verification_request + /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ); //////////////////////////////////////////////////////////////////////////// // Keys // - /** @copydoc ble::pal::SecurityManager::on_public_key_generated - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ); - /** @copydoc ble::pal::SecurityManager::on_secure_connections_ltk_generated */ virtual void on_secure_connections_ltk_generated( @@ -695,7 +737,7 @@ public: ControlBlock_t* get_control_block(const address_t &peer_address); - ControlBlock_t* get_control_block(pal::SecurityDb::entry_handle_t db_entry); + ControlBlock_t* get_control_block(SecurityDb::entry_handle_t db_entry); void release_control_block(ControlBlock_t* entry); }; diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h new file mode 100644 index 0000000000..6ca9c3b3b0 --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -0,0 +1,196 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GENERIC_MEMORY_SECURITY_DB_H_ +#define GENERIC_MEMORY_SECURITY_DB_H_ + +#include "SecurityDb.h" + +namespace ble { +namespace generic { + +/** Naive memory implementation for verification. */ +class MemorySecurityDb : public SecurityDb { +private: + struct entry_t { + entry_t() { }; + SecurityDistributionFlags_t flags; + SecurityEntryKeys_t local_keys; + SecurityEntryKeys_t peer_keys; + SecurityEntryIdentity_t peer_identity; + SecurityEntrySigning_t peer_signing; + }; + + static const size_t MAX_ENTRIES = 5; + + static entry_t* as_entry(entry_handle_t db_handle) + { + return reinterpret_cast(db_handle); + } + +public: + MemorySecurityDb() : SecurityDb() { } + virtual ~MemorySecurityDb() { } + + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle + ) { + return reinterpret_cast(db_handle); + } + + /* local keys */ + + /* set */ + virtual void set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->flags.ltk_sent = true; + entry->local_keys.ltk = ltk; + } + } + + virtual void set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->local_keys.ediv = ediv; + entry->local_keys.rand = rand; + } + } + + /* peer's keys */ + + /* set */ + + virtual void set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_keys.ltk = ltk; + entry->flags.ltk_stored = true; + } + } + + virtual void set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_keys.ediv = ediv; + entry->peer_keys.rand = rand; + } + } + + virtual void set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_identity.irk = irk; + entry->flags.irk_stored = true; + } + } + + virtual void set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_identity.identity_address = peer_address; + entry->peer_identity.identity_address_is_public = address_is_public; + } + } + + virtual void set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->flags.csrk_stored = true; + entry->peer_signing.csrk = csrk; + } + } + + virtual void set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter + ) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_signing.counter = sign_counter; + } + } + +private: + virtual uint8_t get_entry_count() { + return MAX_ENTRIES; + } + + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) { + if (index < MAX_ENTRIES) { + return &_entries[index].flags; + } else { + return NULL; + } + } + + virtual void reset_entry(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + *entry = entry_t(); + } + + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_identity; + }; + + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_keys; + }; + + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->local_keys; + }; + + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_signing; + }; + +private: + entry_t _entries[MAX_ENTRIES]; +}; + +} /* namespace pal */ +} /* namespace ble */ + +#endif /*GENERIC_MEMORY_SECURITY_DB_H_*/ diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h new file mode 100644 index 0000000000..b8c2ea25c8 --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -0,0 +1,752 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GENERIC_SECURITY_MANAGER_DB_H__ +#define GENERIC_SECURITY_MANAGER_DB_H__ + +#include "platform/Callback.h" +#include "ble/pal/GapTypes.h" +#include "ble/BLETypes.h" +#include "ble/Gap.h" +#include + +namespace ble { +namespace generic { + + +/** + * Security flags associated with a bond. + */ +struct SecurityDistributionFlags_t { + SecurityDistributionFlags_t() : + peer_address(), + encryption_key_size(0), + peer_address_is_public(false), + csrk_stored(false), + ltk_stored(false), + ltk_sent(false), + irk_stored(false), + csrk_mitm_protected(false), + ltk_mitm_protected(false), + secure_connections_paired(false), + connected(false) { + } + + /** peer address */ + address_t peer_address; + + /** encryption key size */ + uint8_t encryption_key_size; + /** true if peer address is public, false if it's static random */ + uint8_t peer_address_is_public:1; + + /** CSRK (Connection Signature Resolving Key) has been distributed and stored */ + uint8_t csrk_stored:1; + /** LTK (Long Term Key) has been distributed and stored */ + uint8_t ltk_stored:1; + uint8_t ltk_sent:1; + /** the security entry has been distributed and stored */ + uint8_t irk_stored:1; + + /** CSRK that is stored has MITM protection */ + uint8_t csrk_mitm_protected:1; + /** LTK that is stored has MITM protection */ + uint8_t ltk_mitm_protected:1; + /** the current pairing was done using Secure Connections */ + uint8_t secure_connections_paired:1; + uint8_t connected:1; +}; + +/** Long Term Key and data used to identify it */ +struct SecurityEntryKeys_t { + /** Long Term Key */ + ltk_t ltk; + /** EDIV (Encryption diversifier) used to identify LTK during legacy pairing */ + ediv_t ediv; + /** Rand (random number) used to identify LTK during legacy pairing */ + rand_t rand; +}; + +/** CSRK and sign counter used to verify messages */ +struct SecurityEntrySigning_t { + SecurityEntrySigning_t() : counter(0) { }; + /** Signing key */ + csrk_t csrk; + /** counter used to verify message to guard from replay attacks */ + sign_count_t counter; +}; + +/** Data for resolving random resolvable addresses */ +struct SecurityEntryIdentity_t { + /** identity address */ + address_t identity_address; + /** Identity Resolving Key */ + irk_t irk; + /** true if peer identity address is public, false if it's static random */ + uint8_t identity_address_is_public:1; +}; + +/** + * SecurityDb holds the state for active connections and bonded devices. + * Keys can be stored in NVM and are returned via callbacks. + * SecurityDb is responsible for serialising any requests and keeping + * the store in a consistent state. + * Active connections state must be returned immediately. + */ +class SecurityDb { +public: + /** + * Opaque type representing a handle to a database entry. + */ + typedef void* entry_handle_t; + + /* callbacks for asynchronous data retrieval from the security db */ + + typedef mbed::Callback + SecurityEntryKeysDbCb_t; + typedef mbed::Callback + SecurityEntrySigningDbCb_t; + typedef mbed::Callback + SecurityEntryIdentityDbCb_t; + typedef mbed::Callback&, size_t count)> + IdentitylistDbCb_t; + typedef mbed::Callback + WhitelistDbCb_t; + + SecurityDb() : _local_sign_counter(0) { }; + virtual ~SecurityDb() { }; + + /** + * Return immediately security flags associated to a db entry. + * + * @param[in] db_handle Entry of the database queried. + * @return pointer to the flags or NULL if the entry do not have any + * associated flags. + */ + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle + ) = 0; + + /** + * Set the distribution flags of a DB entry. + * + * @param[in] db_handle Entry of the database that will store the flags. + * @param[in] flags Distribution flags to store in @p db_handle. + */ + virtual void set_distribution_flags( + entry_handle_t db_handle, + const SecurityDistributionFlags_t& new_flags + ) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags) { + *flags = new_flags; + } + } + + /* local keys */ + + /** + * Retrieve stored LTK based on passed in EDIV and RAND values. + * + * @param[in] cb callback that will receive the LTK struct + * @param[in] db_handle handle of the entry being queried. + * @param[in] ediv one of the values used to identify the LTK + * @param[in] rand one of the values used to identify the LTK + */ + virtual void get_entry_local_keys( + SecurityEntryKeysDbCb_t cb, + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ) { + SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + /* validate we have the correct key */ + if (keys && ediv == keys->ediv && rand == keys->rand) { + cb(db_handle, keys); + } else { + cb(db_handle, NULL); + } + } + + /** + * Retrieve stored LTK generated during secure connections pairing. + * + * @param[in] cb callback that will receive the LTK struct + * @param[in] db_handle handle of the entry being queried. + */ + virtual void get_entry_local_keys( + SecurityEntryKeysDbCb_t cb, + entry_handle_t db_handle + ) { + SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + /* validate we have the correct key */ + if (flags && keys && flags->secure_connections_paired) { + cb(db_handle, keys); + } else { + cb(db_handle, NULL); + } + } + + /** + * Save new local LTK for a connection. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] ltk the new LTK, if the device is slave, this is the LTK that + * will be used when link is encrypted + */ + virtual void set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k + ) = 0; + + /** + * Update EDIV and RAND used to identify the LTK. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] ediv new EDIV value + * @param[in] rand new RAND value + */ + virtual void set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ) = 0; + + /* peer's keys */ + + /** + * Return asynchronously the peer signing key through a callback + * so that signed packets can be verified. + * + * @param[in] cb callback which will receive the key + * @param[in] db_handle handle of the entry being queried. + */ + virtual void get_entry_peer_csrk( + SecurityEntrySigningDbCb_t cb, + entry_handle_t db_handle + ) { + SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle); + cb(db_handle, signing); + } + + /** + * Return asynchronously the peer encryption key through a callback + * so that encryption can be enabled. + * + * @param[in] cb callback which will receive the key + * @param[in] db_handle handle of the entry being queried. + */ + virtual void get_entry_peer_keys( + SecurityEntryKeysDbCb_t cb, + entry_handle_t db_handle + ) { + SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle); + cb(db_handle, keys); + } + + /** + * Save new LTK received from the peer. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] ltk the new LTK, if the peer device is slave, this is the LTK + * that will be used when link is encrypted + */ + virtual void set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k + ) = 0; + + /** + * Update EDIV and RAND used to identify the LTK sent by the peer. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] ediv new EDIV value + * @param[in] rand new RAND value + */ + virtual void set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ) = 0; + + /** + * Update IRK for this connection. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] irk new IRK value + */ + virtual void set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk + ) = 0; + + /** + * Update the identity address of the peer. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] address_is_public is the identity address public or private + * @param[in] peer_address the new address + */ + virtual void set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address + ) = 0; + + /** + * Retrieve stored identity address and IRK. + * + * @param[in] cb callback that will receive the SecurityEntryIdentity_t struct + * @param[in] db_handle handle of the entry being queried. + */ + virtual void get_entry_identity( + SecurityEntryIdentityDbCb_t cb, + entry_handle_t db_handle + ) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags && flags->irk_stored) { + SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle); + if (peer_identity) { + cb(db_handle, peer_identity); + return; + } + } + /* avoid duplicate else */ + cb(db_handle, NULL); + } + + /** + * Asynchronously return the identity list stored in NVM through a callback. + * Function takes ownership of the memory. The identity list and the + * ownership will be returned in the callback. + * + * @param[in] cb callback that will receive the whitelist + * @param[in] identity_list preallocated identity_list that will be filled + * in. + */ + virtual void get_identity_list( + IdentitylistDbCb_t cb, + ArrayView& identity_list + ) { + size_t count = 0; + for (size_t i = 0; i < get_entry_count() && count < identity_list.size(); ++i) { + + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + + if (flags && flags->irk_stored) { + SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle); + if (peer_identity) { + identity_list[count] = *peer_identity; + count++; + } + } + } + + cb(identity_list, count); + } + + /** + * Update peer signing key. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] csrk new CSRK value + */ + virtual void set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk + ) = 0; + + /** + * Update peer signing counter. + * + * @param[in] db_handle handle of the entry being updated. + * @param[in] sign_counter new signing counter value + */ + virtual void set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter + ) = 0; + + /* local csrk */ + + /** + * Return local signing key used for signing packets. + * + * @return pointer to local CSRK + */ + virtual const csrk_t* get_local_csrk() { + return &_local_csrk; + } + + /** + * Return local signing counter. + * + * @return signing counter + */ + virtual sign_count_t get_local_sign_counter() { + return _local_sign_counter; + } + + /** + * Update local signing key. + * + * @param[in] csrk new CSRK value + */ + virtual void set_local_csrk( + const csrk_t &csrk + ) { + _local_csrk = csrk; + } + + /** + * Update local signing counter. + * + * @param[in] sign_counter new signing counter value + */ + virtual void set_local_sign_counter( + sign_count_t sign_counter + ) { + _local_sign_counter = sign_counter; + } + + /* list management */ + + /** + * Open a database entry. + * + * While this entry is opened; it can be queried and updated with the help + * of the database setter and getter functions. + * + * @param[in] peer_address_type type of address + * @param[in] peer_address this address will be used to locate an existing + * entry. + * + * @return A handle to the entry. + */ + virtual entry_handle_t open_entry( + peer_address_type_t peer_address_type, + const address_t &peer_address + ) { + entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); + if (db_handle) { + return db_handle; + } + + SecurityDistributionFlags_t* flags = get_free_entry_flags(); + if (flags) { + const bool peer_address_public = + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY); + /* we need some address to store, so we store even random ones + * this address will be used as an id, possibly replaced later + * by identity address */ + flags->peer_address = peer_address; + flags->peer_address_is_public = peer_address_public; + return flags; + } + + return NULL; + } + + /** + * Find a database entry based on peer address. + * + * @param[in] peer_address_type type of address + * @param[in] peer_address this address will be used to locate an existing entry. + * + * @return A handle to the entry. + */ + virtual entry_handle_t find_entry_by_peer_address( + peer_address_type_t peer_address_type, + const address_t &peer_address + ) { + const bool peer_address_public = + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY); + + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + /* only look among disconnected entries */ + if (flags && !flags->connected) { + if (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY && + flags->irk_stored == false) { + continue; + } + + /* lookup for connection address used during bonding */ + if (flags->peer_address == peer_address && + flags->peer_address_is_public == peer_address_public) { + return flags; + } + + /* look for the identity address if stored */ + if (flags->irk_stored) { + SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle); + + if (identity && + identity->identity_address == peer_address && + identity->identity_address_is_public == peer_address_public) { + return flags; + } + } + } + } + + return NULL; + } + + /** + * Close a connection entry. + * + * @param[in] db_handle this handle will be freed up from the security db. + */ + virtual void close_entry(entry_handle_t db_handle) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags) { + flags->connected = false; + } + sync(db_handle); + } + + /** + * Remove entry for this peer from NVM. + * + * @param[in] peer_address_type type of address + * @param[in] peer_address this address will be used to locate an existing + * entry. + * + * @return A handle to the entry. + */ + virtual void remove_entry( + peer_address_type_t peer_address_type, + const address_t &peer_address + ) { + entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); + if (db_handle) { + reset_entry(db_handle); + } + } + + /** + * Remove all entries from the security DB. + */ + virtual void clear_entries() { + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + reset_entry(db_handle); + } + _local_identity = SecurityEntryIdentity_t(); + _local_csrk = csrk_t(); + } + + /** + * Asynchronously return the whitelist stored in NVM through a callback. + * Function takes ownership of the memory. The whitelist and the ownership + * will be returned in the callback. + * + * @param[in] cb callback that will receive the whitelist + * @param[in] whitelist preallocated whitelist that will be filled in + */ + virtual void get_whitelist( + WhitelistDbCb_t cb, + ::Gap::Whitelist_t *whitelist + ) { + /*TODO: fill whitelist*/ + cb(whitelist); + } + + /** + * Asynchronously return a whitelist through a callback, generated from the + * bond table. + * + * @param[in] cb callback that will receive the whitelist + * @param[in] whitelist preallocated whitelist that will be filled in + */ + virtual void generate_whitelist_from_bond_table( + WhitelistDbCb_t cb, + ::Gap::Whitelist_t *whitelist + ) { + for (size_t i = 0; i < get_entry_count() && i < whitelist->capacity; i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + if (!flags) { + continue; + } + + if (flags->peer_address_is_public) { + whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC; + } else { + whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC; + } + + SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle); + if (identity) { + memcpy( + whitelist->addresses[i].address, + identity->identity_address.data(), + sizeof(BLEProtocol::AddressBytes_t) + ); + } + } + + cb(whitelist); + } + + /** + * Update the whitelist stored in NVM by replacing it with new one. + * + * @param[in] whitelist + */ + virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { }; + + /** + * Add a new entry to the whitelist in the NVM. + * + * @param[in] address new whitelist entry + */ + virtual void add_whitelist_entry(const address_t &address) { }; + + /** + * Remove whitelist entry from NVM. + * + * @param[in] address entry to be removed + */ + virtual void remove_whitelist_entry(const address_t &address) { }; + + /** + *Remove all whitelist entries stored in the NVM. + */ + virtual void clear_whitelist() { }; + + /* saving and loading from nvm */ + + /** + * Read values from storage. + */ + virtual void restore() { }; + + /** + * Flush all values which might be stored in memory into NVM. + */ + virtual void sync(entry_handle_t db_handle) { }; + + /** + * Toggle whether values should be preserved across resets. + * + * @param[in] reload if true values will be preserved across resets. + */ + virtual void set_restore(bool reload) { }; + +private: + /** + * Get an entry for a new connection not present in the db yet. This will find a free entry + * or use a disconnected entry by reseting all the stored information. + * @return empty entry for the new connection + */ + virtual SecurityDistributionFlags_t* get_free_entry_flags() { + /* get a free one if available */ + SecurityDistributionFlags_t* match = NULL; + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + if (flags && !flags->connected) { + /* we settle for any disconnected if we don't find an empty one */ + match = flags; + if (!flags->csrk_stored + && !flags->ltk_stored + && !flags->ltk_sent + && !flags->irk_stored) { + /* empty one found, stop looking*/ + break; + } + } + } + + if (match) { + reset_entry(match); + } + + return match; + } + + /** + * How many entries can be stored in the databes. + * @return max number of entries + */ + virtual uint8_t get_entry_count() = 0; + + /** + * Return database entry based on its index. + * @param index index from 0 to get_entry_count() + * @return databse entry stored at index + */ + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) = 0; + + /** + * Delete all the information. + * @param db_handle handle for the entry to be reset + */ + virtual void reset_entry(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0; + +protected: + SecurityEntryIdentity_t _local_identity; + csrk_t _local_csrk; + sign_count_t _local_sign_counter; +}; + +} /* namespace pal */ +} /* namespace ble */ + +#endif /*GENERIC_SECURITY_MANAGER_DB_H__*/ diff --git a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h index d0a0325bde..de5a1deb7b 100644 --- a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h +++ b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h @@ -48,11 +48,13 @@ public: * @param[in] local_address_type type of address of the local device. * @param[in] local_address Address of the local device that was used during connection. * @param[in] connection_params connection parameters like interval, latency and timeout. + * @param[in] resolved_peer_address resolved address of the peer; may + * be NULL. */ virtual void on_connected( connection_handle_t connection, ::Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + ble::peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, diff --git a/features/FEATURE_BLE/ble/pal/GapEvents.h b/features/FEATURE_BLE/ble/pal/GapEvents.h index a406d6cdcc..728205479f 100644 --- a/features/FEATURE_BLE/ble/pal/GapEvents.h +++ b/features/FEATURE_BLE/ble/pal/GapEvents.h @@ -140,7 +140,6 @@ struct GapConnectionCompleteEvent : public GapEvent { * @param supervision_timeout Supervision timeout of the connection. It * shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. * - * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.1 LE Connection Complete Event * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection * Complete Event */ @@ -153,6 +152,69 @@ struct GapConnectionCompleteEvent : public GapEvent { uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout + ) : + GapEvent(GapEventType::CONNECTION_COMPLETE), + status(status), + connection_handle(connection_handle), + role(role), + peer_address_type( + peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS ? + peer_address_type_t::PUBLIC : + peer_address_type_t::RANDOM + ), + peer_address(peer_address), + connection_interval(connection_interval), + connection_latency(connection_latency), + supervision_timeout(supervision_timeout), + local_resolvable_private_address(), + peer_resolvable_private_address() { + } + + /** + * Construct a new GapConnectionCompleteEvent. + * + * @param status Status of the operation: 0x00 in case of success otherwise + * the error code associated with the failure. + * + * @param connection_handle handle of the connection created. This handle + * will be used to address the connection in any connection oriented + * operation. + * + * @param role Role of the LE subsystem in the connection. + * + * @param address_type Type of address used by the peer for this connection. + * + * @param address Address of the peer used to establish the connection. + * + * @param connection_interval Connection interval used on this connection. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + * + * @param connection_latency Number of connection events the slave can + * drop. + * + * @param supervision_timeout Supervision timeout of the connection. It + * shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + * + * @param local_resolvable_private_address Resolvable private address used + * by the local device to establish the connection. + * + * @param peer_resolvable_private_address Resolvable private address used + * by the peer to establish the connection. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection + * Complete Event + */ + GapConnectionCompleteEvent( + uint8_t status, + connection_handle_t connection_handle, + connection_role_t role, + peer_address_type_t peer_address_type, + const address_t& peer_address, + uint16_t connection_interval, + uint16_t connection_latency, + uint16_t supervision_timeout, + const address_t& local_resolvable_private_address, + const address_t& peer_resolvable_private_address ) : GapEvent(GapEventType::CONNECTION_COMPLETE), status(status), @@ -162,9 +224,12 @@ struct GapConnectionCompleteEvent : public GapEvent { peer_address(peer_address), connection_interval(connection_interval), connection_latency(connection_latency), - supervision_timeout(supervision_timeout) { + supervision_timeout(supervision_timeout), + local_resolvable_private_address(local_resolvable_private_address), + peer_resolvable_private_address(peer_resolvable_private_address) { } + /* * @param status Indicate if the connection succesfully completed or not: * - 0: Connection successfuly completed @@ -188,7 +253,7 @@ struct GapConnectionCompleteEvent : public GapEvent { /** * Peer address type. */ - const advertising_peer_address_type_t peer_address_type; + const peer_address_type_t peer_address_type; /** * Peer address. @@ -211,6 +276,18 @@ struct GapConnectionCompleteEvent : public GapEvent { * It shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. */ const uint16_t supervision_timeout; + + /** + * Resolvable private address of the local device. + * Set to all 0 if not available. + */ + const address_t local_resolvable_private_address; + + /** + * Resolvable private address of the peer. + * Set to all 0 if not available. * + */ + const address_t peer_resolvable_private_address; }; diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h deleted file mode 100644 index 1d4bbb209c..0000000000 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h +++ /dev/null @@ -1,372 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PAL_MEMORY_SECURITY_DB_H_ -#define PAL_MEMORY_SECURITY_DB_H_ - -#include "SecurityDb.h" - -namespace ble { -namespace pal { - -/** Naive memory implementation for verification. */ -class MemorySecurityDb : public SecurityDb { -private: - enum state_t { - ENTRY_FREE, - ENTRY_RESERVED, - ENTRY_WRITTEN - }; - - struct entry_t { - entry_t() : state(ENTRY_FREE) { }; - SecurityDistributionFlags_t flags; - SecurityEntryKeys_t peer_keys; - SecurityEntryKeys_t local_keys; - SecurityEntryIdentity_t peer_identity; - csrk_t csrk; - state_t state; - }; - static const size_t MAX_ENTRIES = 5; - - static entry_t* as_entry(entry_handle_t entry_handle) - { - return reinterpret_cast(entry_handle); - } - -public: - MemorySecurityDb() { }; - virtual ~MemorySecurityDb() { }; - - virtual const SecurityDistributionFlags_t* get_distribution_flags( - entry_handle_t entry_handle - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return NULL; - } - - return &entry->flags; - } - - /** - * Set the distribution flags of the DB entry - */ - virtual void set_distribution_flags( - entry_handle_t entry_handle, - const SecurityDistributionFlags_t& flags - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - entry->state = ENTRY_WRITTEN; - entry->flags = flags; - } - - /* local keys */ - - /* get */ - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle, - const ediv_t &ediv, - const rand_t &rand - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - /* validate we have the correct key */ - if (ediv == entry->local_keys.ediv && rand == entry->local_keys.rand) { - cb(entry_handle, &entry->local_keys); - } else { - cb(entry_handle, NULL); - } - } - - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - /* validate we have the correct key */ - if (entry->flags.secure_connections_paired) { - cb(entry_handle, &entry->local_keys); - } else { - cb(entry_handle, NULL); - } - } - - - /* set */ - virtual void set_entry_local_ltk( - entry_handle_t entry_handle, - const ltk_t <k - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->local_keys.ltk = ltk; - } - } - - virtual void set_entry_local_ediv_rand( - entry_handle_t entry_handle, - const ediv_t &ediv, - const rand_t &rand - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->local_keys.ediv = ediv; - entry->local_keys.rand = rand; - } - } - - /* peer's keys */ - - /* get */ - virtual void get_entry_peer_csrk( - SecurityEntryCsrkDbCb_t cb, - entry_handle_t entry_handle - ) { - csrk_t csrk; - entry_t *entry = as_entry(entry_handle); - if (entry) { - csrk = entry->csrk; - } - cb(entry_handle, &csrk); - } - - virtual void get_entry_peer_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle - ) { - SecurityEntryKeys_t *key = NULL; - entry_t *entry = as_entry(entry_handle); - if (entry) { - key = &entry->peer_keys; - } - cb(entry_handle, key); - } - - /* set */ - - virtual void set_entry_peer_ltk( - entry_handle_t entry_handle, - const ltk_t <k - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->peer_keys.ltk = ltk; - } - } - - virtual void set_entry_peer_ediv_rand( - entry_handle_t entry_handle, - const ediv_t &ediv, - const rand_t &rand - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->peer_keys.ediv = ediv; - entry->peer_keys.rand = rand; - } - } - - virtual void set_entry_peer_irk( - entry_handle_t entry_handle, - const irk_t &irk - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->peer_identity.irk = irk; - } - } - - virtual void set_entry_peer_bdaddr( - entry_handle_t entry_handle, - bool address_is_public, - const address_t &peer_address - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->peer_identity.identity_address = peer_address; - } - } - - virtual void set_entry_peer_csrk( - entry_handle_t entry_handle, - const csrk_t &csrk - ) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - entry->state = ENTRY_WRITTEN; - entry->csrk = csrk; - } - } - - /* local csrk */ - - virtual const csrk_t* get_local_csrk() { - return &_local_csrk; - } - - virtual void set_local_csrk(const csrk_t &csrk) { - _local_csrk = csrk; - } - - /* public key */ - - virtual const public_key_coord_t& get_public_key_x() { - return _public_key_x; - } - - virtual const public_key_coord_t& get_public_key_y() { - return _public_key_y; - } - - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) { - _public_key_x = public_key_x; - _public_key_y = public_key_y; - } - - /* list management */ - - virtual entry_handle_t open_entry( - BLEProtocol::AddressType_t peer_address_type, - const address_t &peer_address - ) { - const bool peer_address_public = - (peer_address_type == BLEProtocol::AddressType::PUBLIC); - - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - continue; - } else if (peer_address == _entries[i].peer_identity.identity_address - && _entries[i].flags.peer_address_is_public == peer_address_public) { - return &_entries[i]; - } - } - - /* if we din't find one grab the first disconnected slot*/ - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - _entries[i] = entry_t(); - _entries[i].flags.peer_address = peer_address; - _entries[i].flags.peer_address_is_public = peer_address_public; - _entries[i].state = ENTRY_RESERVED; - return &_entries[i]; - } - } - - return NULL; - } - - virtual void close_entry(entry_handle_t entry_handle) - { - entry_t *entry = as_entry(entry_handle); - if (entry && entry->state == ENTRY_RESERVED) { - entry->state = ENTRY_FREE; - } - } - - virtual void remove_entry(const address_t peer_identity_address) - { - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - continue; - } else if (peer_identity_address == _entries[i].peer_identity.identity_address) { - _entries[i] = entry_t(); - _entries[i].state = ENTRY_FREE; - return; - } - } - } - - virtual void clear_entries() { - for (size_t i = 0; i < MAX_ENTRIES; i++) { - _entries[i] = entry_t(); - } - _local_identity = SecurityEntryIdentity_t(); - _local_csrk = csrk_t(); - } - - virtual void get_whitelist(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) { - /*TODO: fill whitelist*/ - cb(whitelist); - } - - virtual void generate_whitelist_from_bond_table(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) { - for (size_t i = 0; i < MAX_ENTRIES && i < whitelist->capacity; i++) { - if (_entries[i].flags.peer_address_is_public) { - whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC; - } else { - whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC; - } - - memcpy( - whitelist->addresses[i].address, - _entries[i].peer_identity.identity_address.data(), - sizeof(BLEProtocol::AddressBytes_t) - ); - } - - cb(whitelist); - } - - virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { }; - - virtual void add_whitelist_entry(const address_t &address) { } - - virtual void remove_whitelist_entry(const address_t &address) { } - - virtual void clear_whitelist() { } - - /* saving and loading from nvm */ - - virtual void restore() { } - - virtual void sync() { } - - virtual void set_restore(bool reload) { } - -private: - entry_t _entries[MAX_ENTRIES]; - SecurityEntryIdentity_t _local_identity; - csrk_t _local_csrk; - public_key_coord_t _public_key_x; - public_key_coord_t _public_key_y; -}; - -} /* namespace pal */ -} /* namespace ble */ - -#endif /*PAL_MEMORY_SECURITY_DB_H_*/ diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index b365e5c23b..aec629a587 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -649,6 +649,27 @@ struct Gap { disconnection_reason_t disconnection_reason ) = 0; + /** Check if privacy feature is supported by implementation + * + * @return true if privacy is supported, false otherwise. + * + * @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature. + */ + virtual bool is_privacy_supported() = 0; + + /** Enable or disable private addresses resolution + * + * @param enable whether to enable private addresses resolution + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable command. + */ + virtual ble_error_t set_address_resolution( + bool enable + ) = 0; + /** * Register a callback which will handle Gap events. * diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 3f51299f9b..23a9badabb 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -27,10 +27,10 @@ namespace ble { namespace pal { -typedef SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; -typedef SecurityManager::SecurityMode_t SecurityMode_t; -typedef SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; -typedef SecurityManager::Keypress_t Keypress_t; +typedef ::SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; +typedef ::SecurityManager::SecurityMode_t SecurityMode_t; +typedef ::SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; +typedef ::SecurityManager::Keypress_t Keypress_t; /** * Key distribution as required by the SMP with convenient setters and getters, @@ -371,7 +371,18 @@ public: * Request OOB data from the user application. * * @param[in] connection connection handle - * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @note shall be followed by: pal::SecurityManager::secure_connections_oob_request_reply + * or a cancellation of the procedure. + */ + virtual void on_secure_connections_oob_request( + connection_handle_t connection + ) = 0; + + /** + * Request OOB data from the user application. + * + * @param[in] connection connection handle + * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_request_reply * or a cancellation of the procedure. */ virtual void on_legacy_pairing_oob_request( @@ -379,32 +390,23 @@ public: ) = 0; /** - * Request OOB data to be verified against received public keys. + * Send OOB data to the application for transport to the peer. * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) + * @param[in] connection connection handle + * @param[in] random random number used to generate the confirmation + * @param[in] confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ) = 0; //////////////////////////////////////////////////////////////////////////// // Keys // - /** - * Provide the local public key. - * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - /** * Store the results of key generation of the stage 2 of secure connections pairing * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.6.5 @@ -542,21 +544,21 @@ public: /** * Initialise stack. Called before first use. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t initialize() = 0; /** * Finalise all actions. Called before shutdown. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t terminate() = 0; /** * Reset to same state as after initialize. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t reset() = 0; @@ -571,7 +573,7 @@ public: * @warning: The number of entries is considered fixed. * * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.41 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual uint8_t read_resolving_list_capacity() = 0; @@ -582,7 +584,7 @@ public: * @param[in] peer_identity_address address of the device whose entry is to be added * @param[in] peer_irk peer identity resolving key * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.38 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t add_device_to_resolving_list( advertising_peer_address_type_t peer_identity_address_type, @@ -596,7 +598,7 @@ public: * @param[in] peer_identity_address_type public/private indicator * @param[in] peer_identity_address address of the device whose entry is to be removed * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.39 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, @@ -607,7 +609,7 @@ public: * Remove all devices from the resolving list. * * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.40 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t clear_resolving_list() = 0; @@ -624,7 +626,7 @@ public: * @param[in] initiator_dist key distribution * @param[in] responder_dist key distribution * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.1 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_pairing_request( connection_handle_t connection, @@ -643,7 +645,7 @@ public: * @param[in] authentication_requirements authentication requirements * @param[in] initiator_dist key distribution * @param[in] responder_dist key distribution - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_pairing_response( connection_handle_t connection, @@ -659,7 +661,7 @@ public: * @param[in] connection connection handle * @param[in] reason pairing failure error * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.5 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t cancel_pairing( connection_handle_t connection, @@ -674,7 +676,7 @@ public: * Check if the Secure Connections feature is supported by the stack and controller. * * @param[out] enabled true if SC are supported - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_secure_connections_support( bool &enabled @@ -684,7 +686,7 @@ public: * Set the IO capability that will be used during pairing feature exchange. * * @param[in] io_capability type of IO capabilities available on the local device - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_io_capability( io_capability_t io_capability @@ -700,7 +702,7 @@ public: * * @param[in] connection connection handle * @param[in] timeout_in_10ms time measured in units of 10 milliseconds - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_authentication_timeout( connection_handle_t connection, @@ -713,7 +715,7 @@ public: * * @param[in] connection connection handle * @param[out] timeout_in_10ms time measured in units of 10 milliseconds - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_authentication_timeout( connection_handle_t connection, @@ -731,7 +733,7 @@ public: * required for pairing. This value shall be in the range * [min_encryption_key_size : 16]. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_encryption_key_requirements( uint8_t min_encryption_key_size, @@ -746,7 +748,7 @@ public: * * @param[in] connection connection handle * @param[in] authentication authentication requirements - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t slave_security_request( connection_handle_t connection, @@ -767,7 +769,7 @@ public: * @param[in] ediv encryption diversifier from the peer * @param[in] rand random value from the peer * @param[in] mitm does the LTK have man in the middle protection - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t enable_encryption( connection_handle_t connection, @@ -784,7 +786,7 @@ public: * @param[in] connection connection handle * @param[in] ltk long term key from the peer * @param[in] mitm does the LTK have man in the middle protection - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t enable_encryption( connection_handle_t connection, @@ -798,7 +800,7 @@ public: * * @param[in] key encryption key * @param[in,out] data data to be encrypted, if successful contains the result - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t encrypt_data( const byte_array_t<16> &key, @@ -824,7 +826,7 @@ public: * @param[in] ltk long term key * @param[in] mitm does the LTK have man in the middle protection * @param[in] secure_connections is this a secure_connections pairing - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_ltk( connection_handle_t connection, @@ -837,7 +839,7 @@ public: * Inform the stack we don't have the LTK. * * @param[in] connection connection handle - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_ltk_not_found( connection_handle_t connection @@ -847,7 +849,7 @@ public: * Set the local IRK. * * @param[in] irk identity resolution key - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_irk( const irk_t &irk @@ -856,20 +858,32 @@ public: /** * Set the local CSRK. * - * @param[in] csrk signing key - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @param[in] csrk local signing key + * @param[in] sign_counter local signing counter + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_csrk( - const csrk_t &csrk + const csrk_t &csrk, + sign_count_t sign_counter ) = 0; /** - * Generate the Public key. This will also generate the private key. - * Public key will be returned as an event handler callback when it's ready. + * Set the peer CSRK for particular connection. * + * @param[in] connection connection handle + * @param[in] csrk signing key + * @param[in] authenticated is the CSRK authenticated + * @param[in] sign_counter signing counter * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ - virtual ble_error_t generate_public_key() = 0; + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ) = 0; + + virtual ble_error_t remove_peer_csrk(connection_handle_t connection) = 0; //////////////////////////////////////////////////////////////////////////// // Authentication @@ -880,7 +894,7 @@ public: * * @param[out] random_data returns 8 octets of random data * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part H 2 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_random_data( byte_array_t<8> &random_data @@ -908,7 +922,7 @@ public: * passkey is set to 0 then the security manager generates a random * passkey every time it calls SecurityManagerEvent::on_passkey_display. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_display_passkey( passkey_num_t passkey @@ -917,7 +931,7 @@ public: /** * Reply to a passkey request received from the SecurityManagerEventHandler. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t passkey_request_reply( connection_handle_t connection, @@ -925,13 +939,30 @@ public: ) = 0; /** - * Reply to an oob data request received from the SecurityManagerEventHandler. + * Reply to a Secure Connections oob data request received from the SecurityManagerEventHandler. + * + * @param[in] connection connection handle + * @param[in] local_random local random number used for the last oob exchange + * @param[in] peer_random random number used to generate the confirmation on peer + * @param[in] peer_confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ) = 0; + + /** + * Reply to a legacy pairing oob data request received from the SecurityManagerEventHandler. * * @param[in] connection connection handle * @param[in] oob_data pointer to out of band data - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) = 0; @@ -942,7 +973,7 @@ public: * * @param[in] connection connection handle * @param[in] confirmation true if the user indicated the numbers match - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t confirmation_entered( connection_handle_t connection, @@ -955,7 +986,7 @@ public: * * @param[in] connection connection handle * @param[in] keypress type of keypress event - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_keypress_notification( connection_handle_t connection, @@ -963,21 +994,10 @@ public: ) = 0; /** - * Notify the stack that the OOB data has been verified and supply the peer's random number. - * If the verification failed this will not be called and cancel_pairing will be called instead. - * - * @param[in] connection connection handle - * @param[in] local_random random number sent from the local device to be used in further - * calculations by the stack, set to 0 if peer reported no OOB present - * @param[in] peer_random random number from the peer to be used in further - * calculations by the stack, set to 0 if no OOB data received - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * Generate local OOB data to be sent to the application which sends it to the peer. + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random - ) = 0; + virtual ble_error_t generate_secure_connections_oob() = 0; /* Entry points for the underlying stack to report events back to the user. */ public: diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h deleted file mode 100644 index dc53e101e8..0000000000 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ /dev/null @@ -1,429 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PAL_SECURITY_MANAGER_DB_H__ -#define PAL_SECURITY_MANAGER_DB_H__ - -#include "platform/Callback.h" -#include "ble/pal/GapTypes.h" -#include "ble/BLETypes.h" -#include "ble/Gap.h" -#include - -namespace ble { -namespace pal { - - -/** - * Security flags associated with a bond. - */ -struct SecurityDistributionFlags_t { - SecurityDistributionFlags_t() : - peer_address(), - encryption_key_size(0), - peer_address_is_public(false), - local_address_is_public(false), - csrk_stored(false), - csrk_mitm_protected(false), - ltk_stored(false), - ltk_mitm_protected(false), - secure_connections_paired(false) { - } - - /** peer address */ - address_t peer_address; - - /** encryption key size */ - uint8_t encryption_key_size; - /** true if peer address is public, false if it's static random */ - uint8_t peer_address_is_public:1; - /** true if local address is public, false if it's static random */ - uint8_t local_address_is_public:1; - - /** CSRK (Connection Signature Resolving Key) has been distributed and stored */ - uint8_t csrk_stored:1; - /** CSRK that is stored has MITM protection */ - uint8_t csrk_mitm_protected:1; - /** LTK (Long Term Key) has been distributed and stored */ - uint8_t ltk_stored:1; - /** LTK that is stored has MITM protection */ - uint8_t ltk_mitm_protected:1; - /** the current pairing was done using Secure Connections */ - uint8_t secure_connections_paired:1; -}; - -/** Long Term Key and data used to identify it */ -struct SecurityEntryKeys_t { - /** Long Term Key */ - ltk_t ltk; - /** EDIV (Encryption diversifier) used to identify LTK during legacy pairing */ - ediv_t ediv; - /** Rand (random number) used to identify LTK during legacy pairing */ - rand_t rand; -}; - -/** Data for resolving random resolvable addresses */ -struct SecurityEntryIdentity_t { - /** identity address */ - address_t identity_address; - /** Identity Resolving Key */ - irk_t irk; -}; - -/** - * SecurityDb holds the state for active connections and bonded devices. - * Keys can be stored in NVM and are returned via callbacks. - * SecurityDb is responsible for serialising any requests and keeping - * the store in a consistent state. - * Active connections state must be returned immediately. - */ -class SecurityDb { -public: - /** - * Opaque type representing a handle to a database entry. - */ - typedef void* entry_handle_t; - - /* callbacks for asynchronous data retrieval from the security db */ - - typedef mbed::Callback - SecurityEntryKeysDbCb_t; - typedef mbed::Callback - SecurityEntryCsrkDbCb_t; - typedef mbed::Callback - WhitelistDbCb_t; - - SecurityDb() { }; - virtual ~SecurityDb() { }; - - /** - * Return immediately security flags associated to a db entry. - * - * @param[in] db_entry Entry of the database queried. - * @return pointer to the flags or NULL if the entry do not have any - * associated flags. - */ - virtual const SecurityDistributionFlags_t* get_distribution_flags( - entry_handle_t db_entry - ) = 0; - - /** - * Set the distribution flags of a DB entry. - * - * @param[in] db_entry Entry of the database that will store the flags. - * @param[in] flags Distribution flags to store in @p db_entry. - */ - virtual void set_distribution_flags( - entry_handle_t db_entry, - const SecurityDistributionFlags_t& flags - ) = 0; - - /* local keys */ - - /** - * Retrieve stored LTK based on passed in EDIV and RAND values. - * - * @param[in] cb callback that will receive the LTK struct - * @param[in] db_entry handle of the entry being queried. - * @param[in] ediv one of the values used to identify the LTK - * @param[in] rand one of the values used to identify the LTK - */ - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry, - const ediv_t &ediv, - const rand_t &rand - ) = 0; - - /** - * Retrieve stored LTK generated during secure connections pairing. - * - * @param[in] cb callback that will receive the LTK struct - * @param[in] db_entry handle of the entry being queried. - */ - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry - ) = 0; - - /** - * Save new local LTK for a connection. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] ltk the new LTK, if the device is slave, this is the LTK that - * will be used when link is encrypted - */ - virtual void set_entry_local_ltk( - entry_handle_t db_entry, - const ltk_t <k - ) = 0; - - /** - * Update EDIV and RAND used to identify the LTK. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] ediv new EDIV value - * @param[in] rand new RAND value - */ - virtual void set_entry_local_ediv_rand( - entry_handle_t db_entry, - const ediv_t &ediv, - const rand_t &rand - ) = 0; - - /* peer's keys */ - - /** - * Return asynchronously the peer signing key through a callback - * so that signed packets can be verified. - * - * @param[in] cb callback which will receive the key - * @param[in] db_entry handle of the entry being queried. - */ - virtual void get_entry_peer_csrk( - SecurityEntryCsrkDbCb_t cb, - entry_handle_t db_entry - ) = 0; - - /** - * Return asynchronously the peer encryption key through a callback - * so that encryption can be enabled. - * - * @param[in] cb callback which will receive the key - * @param[in] db_entry handle of the entry being queried. - */ - virtual void get_entry_peer_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry - ) = 0; - - /** - * Save new LTK received from the peer. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] ltk the new LTK, if the peer device is slave, this is the LTK - * that will be used when link is encrypted - */ - virtual void set_entry_peer_ltk( - entry_handle_t db_entry, - const ltk_t <k - ) = 0; - - /** - * Update EDIV and RAND used to identify the LTK sent by the peer. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] ediv new EDIV value - * @param[in] rand new RAND value - */ - virtual void set_entry_peer_ediv_rand( - entry_handle_t db_entry, - const ediv_t &ediv, - const rand_t &rand - ) = 0; - - /** - * Update IRK for this connection. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] irk new IRK value - */ - virtual void set_entry_peer_irk( - entry_handle_t db_entry, - const irk_t &irk - ) = 0; - - /** - * Update the identity address of the peer. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] address_is_public is the identity address public or private - * @param[in] peer_address the new address - */ - virtual void set_entry_peer_bdaddr( - entry_handle_t db_entry, - bool address_is_public, - const address_t &peer_address - ) = 0; - - /** - * Update peer signing key. - * - * @param[in] db_entry handle of the entry being updated. - * @param[in] csrk new CSRK value - */ - virtual void set_entry_peer_csrk( - entry_handle_t db_entry, - const csrk_t &csrk - ) = 0; - - /* local csrk */ - - /** - * Return local signing key used for signing packets. - * - * @return pointer to local CSRK - */ - virtual const csrk_t* get_local_csrk() = 0; - - /** - * Update local signing key. - * - * @param[in] csrk new CSRK value - */ - virtual void set_local_csrk(const csrk_t &csrk) = 0; - - /* public keys */ - - /** - * Return local public key. - * - * @return ref to x component of public key - */ - virtual const public_key_coord_t& get_public_key_x() = 0; - - /** - * Return local public key. - * - * @return ref to y component of public key - */ - virtual const public_key_coord_t& get_public_key_y() = 0; - - /** - * Set local public key. - * - * @param[in] public_key_x new public key value of the x coordinate - * @param[in] public_key_y new public key value of the y coordinate - */ - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - - /* list management */ - - /** - * Open a database entry. - * - * While this entry is opened; it can be queried and updated with the help - * of the database setter and getter functions. - * - * @param[in] peer_address_type type of address - * @param[in] peer_address this address will be used to locate an existing - * entry. - * - * @return A handle to the entry. - */ - virtual entry_handle_t open_entry( - BLEProtocol::AddressType_t peer_address_type, - const address_t &peer_address - ) = 0; - - /** - * Close a connection entry. - * - * @param[in] db_entry this handle will be freed up from the security db. - */ - virtual void close_entry(entry_handle_t db_entry) = 0; - - /** - * Remove entry for this peer from NVM. - * - * @param[in] peer_identity_address peer address that no longer needs NVM - * storage. - */ - virtual void remove_entry(const address_t peer_identity_address) = 0; - - /** - * Remove all entries from the security DB. - */ - virtual void clear_entries() = 0; - - /** - * Asynchronously return the whitelist stored in NVM through a callback. - * Function takes ownership of the memory. The whitelist and the ownership - * will be returned in the callback. - * - * @param[in] cb callback that will receive the whitelist - * @param[in] whitelist preallocated whitelist that will be filled in - */ - virtual void get_whitelist( - WhitelistDbCb_t cb, - ::Gap::Whitelist_t *whitelist - ) = 0; - - /** - * Asynchronously return a whitelist through a callback, generated from the - * bond table. - * - * @param[in] cb callback that will receive the whitelist - * @param[in] whitelist preallocated whitelist that will be filled in - */ - virtual void generate_whitelist_from_bond_table( - WhitelistDbCb_t cb, - ::Gap::Whitelist_t *whitelist - ) = 0; - - /** - * Update the whitelist stored in NVM by replacing it with new one. - * - * @param[in] whitelist - */ - virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) = 0; - - /** - * Add a new entry to the whitelist in the NVM. - * - * @param[in] address new whitelist entry - */ - virtual void add_whitelist_entry(const address_t &address) = 0; - - /** - * Remove whitelist entry from NVM. - * - * @param[in] address entry to be removed - */ - virtual void remove_whitelist_entry(const address_t &address) = 0; - - /** - *Remove all whitelist entries stored in the NVM. - */ - virtual void clear_whitelist() = 0; - - /* saving and loading from nvm */ - - /** - * Read values from storage. - */ - virtual void restore() = 0; - - /** - * Flush all values which might be stored in memory into NVM. - */ - virtual void sync() = 0; - - /** - * Toggle whether values should be preserved across resets. - * - * @param[in] reload if true values will be preserved across resets. - */ - virtual void set_restore(bool reload) = 0; -}; - -} /* namespace pal */ -} /* namespace ble */ - -#endif /*PAL_SECURITY_MANAGER_DB_H__*/ diff --git a/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h new file mode 100644 index 0000000000..bc6392c8be --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h @@ -0,0 +1,74 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_BLE_SIGNING_EVENT_MONITOR +#define MBED_BLE_SIGNING_EVENT_MONITOR + +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { + +/** + * Implemented by classes that need to be notified of signing events. + * Notification is done by calling functions in the passed in event handler + */ +class SigningEventMonitor { +public: + /** + * Implemented by classes that are reacting to signing events. + */ + class EventHandler { + public: + /** + * Set new signed write peer counter. + * + * @param[in] connection connection handle + * @param[in] sign_coutner counter received from peer + */ + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ) = 0; + + /** + * Indicate that signed data was rejected due to verification failure. This could + * be due to an invalid CSRK key. + * + * @param[in] connection connection handle + */ + virtual void on_signed_write_verification_failure( + connection_handle_t connection + ) = 0; + + /** + * Notify a new signed write cmd was executed. + */ + virtual void on_signed_write() = 0; + }; + + /** + * Register a handler for singing events to be used internally and serviced first. + * + * @param[in] signing_event_handler Event handler being registered. + */ + virtual void set_signing_event_handler(EventHandler *signing_event_handler) = 0; +}; + +} // namespace pal +} // namespace ble + +#endif /* MBED_BLE_SIGNING_EVENT_MONITOR */ diff --git a/features/FEATURE_BLE/source/BLE.cpp b/features/FEATURE_BLE/source/BLE.cpp index 9eba68f96e..6e71eea6ad 100644 --- a/features/FEATURE_BLE/source/BLE.cpp +++ b/features/FEATURE_BLE/source/BLE.cpp @@ -31,6 +31,28 @@ #include #endif +#if defined(__GNUC__) && !defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_BEGIN \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_BEGIN \ + _Pragma("push") \ + _Pragma("diag_suppress 1361") +#else +#define BLE_DEPRECATED_API_USE_BEGIN +#endif + +#if defined(__GNUC__) && !defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_END \ + _Pragma("GCC diagnostic pop") +#elif defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_END \ + _Pragma("pop") +#else +#define BLE_DEPRECATED_API_USE_END +#endif + static const char* error_strings[] = { "BLE_ERROR_NONE: No error", "BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted", @@ -143,14 +165,18 @@ BLE::Instance(InstanceID_t id) static BLE *singletons[NUM_INSTANCES]; if (id < NUM_INSTANCES) { if (singletons[id] == NULL) { +BLE_DEPRECATED_API_USE_BEGIN singletons[id] = new BLE(id); /* This object will never be freed. */ +BLE_DEPRECATED_API_USE_END } return *singletons[id]; } /* we come here only in the case of a bad interfaceID. */ +BLE_DEPRECATED_API_USE_BEGIN static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */); +BLE_DEPRECATED_API_USE_END return badSingleton; } @@ -162,23 +188,6 @@ void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) { #define defaultSchedulingCallback NULL #endif - -BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(), - whenEventsToProcess(defaultSchedulingCallback), - event_signaled(false) -{ - static BLEInstanceBase *transportInstances[NUM_INSTANCES]; - - if (instanceID < NUM_INSTANCES) { - if (!transportInstances[instanceID]) { - transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */ - } - transport = transportInstances[instanceID]; - } else { - transport = NULL; - } -} - bool BLE::hasInitialized(void) const { if (!transport) { @@ -332,3 +341,47 @@ void BLE::signalEventsToProcess() whenEventsToProcess(¶ms); } } + +// start of deprecated functions + +BLE_DEPRECATED_API_USE_BEGIN + +// NOTE: move and remove deprecation once private +BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(), + whenEventsToProcess(defaultSchedulingCallback), + event_signaled(false) +{ + static BLEInstanceBase *transportInstances[NUM_INSTANCES]; + + if (instanceID < NUM_INSTANCES) { + if (!transportInstances[instanceID]) { + transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */ + } + transport = transportInstances[instanceID]; + } else { + transport = NULL; + } +} + +ble_error_t BLE::setAddress( + BLEProtocol::AddressType_t type, + const BLEProtocol::AddressBytes_t address +) { + return gap().setAddress(type, address); +} + +ble_error_t BLE::connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const Gap::ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams +) { + return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams); +} + +ble_error_t BLE::disconnect(Gap::DisconnectionReason_t reason) { + return gap().disconnect(reason); +} + +BLE_DEPRECATED_API_USE_END + diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp new file mode 100644 index 0000000000..0ce6ebd62e --- /dev/null +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -0,0 +1,344 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ble/Gap.h" + +namespace { + +ble_error_t convert_address_type( + Gap::PeerAddressType_t input_type, + const BLEProtocol::AddressBytes_t address, + BLEProtocol::AddressType_t& output_type +) { + typedef Gap::RandomAddressType_t RandomAddressType_t; + typedef Gap::PeerAddressType_t PeerAddressType_t; + typedef BLEProtocol::AddressType LegacyAddressType_t; + + // best effort; peerAddrTypeIn should not be used when privacy is on. + switch(input_type.value()) { + case PeerAddressType_t::PUBLIC: + case PeerAddressType_t::PUBLIC_IDENTITY: + output_type = LegacyAddressType_t::PUBLIC; + break; + case PeerAddressType_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = Gap::getRandomAddressType(address, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + output_type = LegacyAddressType_t::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + output_type = LegacyAddressType_t::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + output_type = LegacyAddressType_t::RANDOM_PRIVATE_RESOLVABLE; + break; + } + break; + } + case PeerAddressType_t::RANDOM_STATIC_IDENTITY: + output_type = LegacyAddressType_t::RANDOM_STATIC; + break; + } + + return BLE_ERROR_NONE; +} + +Gap::PeerAddressType_t convert_legacy_address_type( + BLEProtocol::AddressType_t legacy_address +) { + if (legacy_address == BLEProtocol::AddressType::PUBLIC) { + return Gap::PeerAddressType_t::PUBLIC; + } else { + return Gap::PeerAddressType_t::RANDOM; + } +} + +} + +const Gap::PeripheralPrivacyConfiguration_t Gap::default_peripheral_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE +}; + +const Gap::CentralPrivacyConfiguration_t Gap::default_central_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ CentralPrivacyConfiguration_t::DO_NOT_RESOLVE +}; + +void Gap::processConnectionEvent( + Handle_t handle, + Role_t role, + PeerAddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr +) { + /* Update Gap state */ + state.advertising = 0; + state.connected = 1; + ++connectionCount; + + ConnectionCallbackParams_t callbackParams( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams, + peerResolvableAddr, + localResolvableAddr + ); + + connectionCallChain.call(&callbackParams); +} + +void Gap::processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + PeerAddressType_t addressType +) { + AdvertisementCallbackParams_t params; + + memcpy(params.peerAddr, peerAddr, ADDR_LEN); + params.rssi = rssi; + params.isScanResponse = isScanResponse; + params.type = type; + params.advertisingDataLen = advertisingDataLen; + params.advertisingData = advertisingData; + params.peerAddrType = addressType; + + convert_address_type( + addressType, + peerAddr, + params.addressType + ); + + onAdvertisementReport.call(¶ms); +} + + +#if defined(__GNUC__) && !defined(__CC_ARM) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__CC_ARM) +#pragma push +#pragma diag_suppress 1361 +#endif + +Gap::AdvertisementCallbackParams_t::AdvertisementCallbackParams_t() : + peerAddr(), + rssi(), + isScanResponse(), + type(), + advertisingDataLen(0), + advertisingData(NULL), + addressType(), + peerAddrType(PeerAddressType_t::PUBLIC) +{ +} + +ble_error_t Gap::getRandomAddressType( + const BLEProtocol::AddressBytes_t address, + RandomAddressType_t* type +) { + // see section Device address in Bluetooth Link Layer specification + // (Vol 6 - Part B) + switch (address[5] >> 6) { + case 0x03: + *type = RandomAddressType_t::STATIC; + return BLE_ERROR_NONE; + case 0x00: + *type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE; + return BLE_ERROR_NONE; + case 0x01: + *type = RandomAddressType_t::RESOLVABLE_PRIVATE; + return BLE_ERROR_NONE; + default: + return BLE_ERROR_INVALID_PARAM; + } +} + +Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + BLEProtocol::AddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) : handle(handleIn), + role(roleIn), + peerAddrType(peerAddrTypeIn), + peerAddr(), + ownAddrType(ownAddrTypeIn), + ownAddr(), + connectionParams(connectionParamsIn), + peerResolvableAddr(), + localResolvableAddr(), + peerAddressType(convert_legacy_address_type(peerAddrTypeIn)) +{ + constructor_helper( + peerAddrIn, + ownAddrIn, + peerResolvableAddrIn, + localResolvableAddrIn + ); +} + +Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + PeerAddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) : handle(handleIn), + role(roleIn), + peerAddrType(), + peerAddr(), + ownAddrType(ownAddrTypeIn), + ownAddr(), + connectionParams(connectionParamsIn), + peerResolvableAddr(), + localResolvableAddr(), + peerAddressType(peerAddrTypeIn) +{ + constructor_helper( + peerAddrIn, + ownAddrIn, + peerResolvableAddrIn, + localResolvableAddrIn + ); + + convert_address_type(peerAddrTypeIn, peerAddrIn, peerAddrType); +} + +void Gap::ConnectionCallbackParams_t::constructor_helper( + const uint8_t *peerAddrIn, + const uint8_t *ownAddrIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) { + memcpy(peerAddr, peerAddrIn, ADDR_LEN); + + if (ownAddrIn) { + memcpy(ownAddr, ownAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } + + if (peerResolvableAddrIn) { + memcpy(peerResolvableAddr, peerResolvableAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } + + if (localResolvableAddrIn) { + memcpy(localResolvableAddr, localResolvableAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } +} + +ble_error_t Gap::connect( + const BLEProtocol::AddressBytes_t peerAddr, + DeprecatedAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams +) { + return connect( + peerAddr, + (BLEProtocol::AddressType_t) peerAddrType, + connectionParams, + scanParams + ); +} + +void Gap::processConnectionEvent( + Handle_t handle, + Role_t role, + BLEProtocol::AddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr +) { + /* Update Gap state */ + state.advertising = 0; + state.connected = 1; + ++connectionCount; + + ConnectionCallbackParams_t callbackParams( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams, + peerResolvableAddr, + localResolvableAddr + ); + + connectionCallChain.call(&callbackParams); +} + +void Gap::processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + BLEProtocol::AddressType_t addressType +) { + AdvertisementCallbackParams_t params; + memcpy(params.peerAddr, peerAddr, ADDR_LEN); + params.rssi = rssi; + params.isScanResponse = isScanResponse; + params.type = type; + params.advertisingDataLen = advertisingDataLen; + params.advertisingData = advertisingData; + params.addressType = addressType; + + params.peerAddrType = convert_legacy_address_type(addressType); + onAdvertisementReport.call(¶ms); +} + +#if defined(__GNUC__) && !defined(__CC_ARM) +#pragma GCC diagnostic pop +#elif defined(__CC_ARM) +#pragma pop +#endif diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp new file mode 100644 index 0000000000..f8d1bfb6c9 --- /dev/null +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -0,0 +1,394 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FileSecurityDb.h" + +namespace ble { +namespace generic { + +const uint16_t DB_VERSION = 1; + +#define DB_STORE_OFFSET_FLAGS (0) +#define DB_STORE_OFFSET_LOCAL_KEYS (DB_STORE_OFFSET_FLAGS + sizeof(SecurityDistributionFlags_t)) +#define DB_STORE_OFFSET_PEER_KEYS (DB_STORE_OFFSET_LOCAL_KEYS + sizeof(SecurityEntryKeys_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY (DB_STORE_OFFSET_PEER_KEYS + sizeof(SecurityEntryKeys_t)) +#define DB_STORE_OFFSET_PEER_SIGNING (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(SecurityEntryIdentity_t)) + +#define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS) +#define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t)) +#define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t)) + +#define DB_STORE_OFFSET_PEER_KEYS_LTK (DB_STORE_OFFSET_PEER_KEYS) +#define DB_STORE_OFFSET_PEER_KEYS_EDIV (DB_STORE_OFFSET_PEER_KEYS_LTK + sizeof(ltk_t)) +#define DB_STORE_OFFSET_PEER_KEYS_RAND (DB_STORE_OFFSET_PEER_KEYS_EDIV + sizeof(ediv_t)) + +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY) +#define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t)) + +#define DB_STORE_OFFSET_PEER_SIGNING_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(csrk_t)) + +/* make size multiple of 4 */ +#define PAD4(value) ((((value - 1) / 4) * 4) + 4) + +#define DB_SIZE_STORE \ + PAD4( \ + sizeof(SecurityDistributionFlags_t) + \ + sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryIdentity_t) + \ + sizeof(SecurityEntrySigning_t) \ + ) + +#define DB_SIZE_STORES \ + (FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE) + +#define DB_OFFSET_VERSION (0) +#define DB_OFFSET_RESTORE (DB_OFFSET_VERSION + sizeof(DB_VERSION)) +#define DB_OFFSET_LOCAL_IDENTITY (DB_OFFSET_RESTORE + sizeof(bool)) +#define DB_OFFSET_LOCAL_CSRK (DB_OFFSET_LOCAL_IDENTITY + sizeof(SecurityEntryIdentity_t)) +#define DB_OFFSET_LOCAL_SIGN_COUNT (DB_OFFSET_LOCAL_CSRK + sizeof(csrk_t)) +#define DB_OFFSET_STORES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t)) +#define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES) +#define DB_SIZE PAD4(DB_OFFSET_MAX) + +typedef SecurityDb::entry_handle_t entry_handle_t; + +FileSecurityDb::FileSecurityDb(FILE *db_file) + : SecurityDb(), + _db_file(db_file) { + /* init the offset in entries so they point to file positions */ + for (size_t i = 0; i < get_entry_count(); i++) { + _entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE; + } +} + +FileSecurityDb::~FileSecurityDb() { + fclose(_db_file); +} + +FILE* FileSecurityDb::open_db_file(const char *db_path) { + if (!db_path) { + return NULL; + } + + /* try to open an existing file */ + FILE *db_file = fopen(db_path, "rb+"); + + if (!db_file) { + /* file doesn't exist, create it */ + db_file = fopen(db_path, "wb+"); + } + + if (!db_file) { + /* failed to create a file, abort */ + return NULL; + } + + /* we will check the db file and if the version or size doesn't match + * what we expect we will blank it */ + bool init = false; + uint16_t version; + + fseek(db_file, DB_OFFSET_VERSION, SEEK_SET); + + if ((fread(&version, sizeof(version), 1, db_file) == 1) && + (version == DB_VERSION)) { + /* if file size differs from database size init the file */ + fseek(db_file, 0, SEEK_END); + if (ftell(db_file) != DB_SIZE) { + init = true; + } + } else { + init = true; + } + + if (init) { + return erase_db_file(db_file); + } + + return db_file; +} + +FILE* FileSecurityDb::erase_db_file(FILE* db_file) { + fseek(db_file, 0, SEEK_SET); + + /* zero the file */ + const uint32_t zero = 0; + size_t count = DB_SIZE / 4; + while (count--) { + if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { + fclose(db_file); + return NULL; + } + } + + if (fflush(db_file)) { + fclose(db_file); + return NULL; + } + + return db_file; +} + +SecurityDistributionFlags_t* FileSecurityDb::get_distribution_flags( + entry_handle_t db_handle +) { + return reinterpret_cast(db_handle); +} + +/* local keys */ + +/* set */ +void FileSecurityDb::set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + entry->flags.ltk_sent = true; + + db_write(<k, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK); +} + +void FileSecurityDb::set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV); + db_write(&rand, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND); +} + +/* peer's keys */ + +/* set */ + +void FileSecurityDb::set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + entry->flags.ltk_stored = true; + + db_write(<k, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK); +} + +void FileSecurityDb::set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV); + db_write(&rand, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND); +} + +void FileSecurityDb::set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + entry->flags.irk_stored = true; + + db_write(&irk, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK); +} + +void FileSecurityDb::set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + db_write(&peer_address, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS); + db_write(&address_is_public, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC); +} + +void FileSecurityDb::set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + entry->flags.csrk_stored = true; + + db_write(&csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); +} + +void FileSecurityDb::set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter +) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_sign_counter = sign_counter; + } +} + +/* saving and loading from nvm */ + +void FileSecurityDb::restore() { + /* restore if requested */ + bool restore_toggle = false; + db_read(&restore_toggle, DB_OFFSET_RESTORE); + + if (!restore_toggle) { + erase_db_file(_db_file); + + db_write(&DB_VERSION, DB_OFFSET_VERSION); + return; + } + + db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY); + db_read(&_local_csrk, DB_OFFSET_LOCAL_CSRK); + db_read(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT); + + /* read flags and sign counters */ + for (size_t i = 0; i < get_entry_count(); i++) { + db_read(&_entries[i].flags, _entries[i].file_offset + DB_STORE_OFFSET_FLAGS); + db_read(&_entries[i].peer_sign_counter, _entries[i].file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); + } + +} + +void FileSecurityDb::sync(entry_handle_t db_handle) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); + db_write(&entry->flags, entry->file_offset + DB_STORE_OFFSET_FLAGS); +} + +void FileSecurityDb::set_restore(bool reload) { + db_write(&reload, DB_OFFSET_RESTORE); +} + +/* helper functions */ + +uint8_t FileSecurityDb::get_entry_count() { + return MAX_ENTRIES; +} + +SecurityDistributionFlags_t* FileSecurityDb::get_entry_handle_by_index(uint8_t index) { + if (index < MAX_ENTRIES) { + return &_entries[index].flags; + } else { + return NULL; + } +} + +void FileSecurityDb::reset_entry(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset, SEEK_SET); + const uint32_t zero = 0; + size_t count = DB_SIZE_STORE / 4; + while (count--) { + fwrite(&zero, sizeof(zero), 1, _db_file); + } + + entry->flags = SecurityDistributionFlags_t(); + entry->peer_sign_counter = 0; +} + +SecurityEntryIdentity_t* FileSecurityDb::read_in_entry_peer_identity(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + + SecurityEntryIdentity_t* identity = reinterpret_cast(_buffer); + db_read(identity, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY); + + return identity; +}; + +SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + + SecurityEntryKeys_t* keys = reinterpret_cast(_buffer); + db_read(keys, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS); + + return keys; +}; + +SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + + SecurityEntryKeys_t* keys = reinterpret_cast(_buffer); + db_read(keys, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS); + + return keys; +}; + +SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + + /* only read in the csrk */ + csrk_t* csrk = reinterpret_cast(_buffer); + db_read(csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); + + + /* use the counter held in memory */ + SecurityEntrySigning_t* signing = reinterpret_cast(_buffer); + signing->counter = entry->peer_sign_counter; + + return signing; +}; + +} /* namespace pal */ +} /* namespace ble */ diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 877564bb23..dc7e8c058a 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -17,6 +17,7 @@ #include #include +#include "ble/BLEInstanceBase.h" #include "ble/BLEProtocol.h" #include "ble/Gap.h" #include "ble/pal/PalGap.h" @@ -30,6 +31,10 @@ namespace ble { namespace generic { +using pal::connection_peer_address_type_t; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; +typedef BLEProtocol::AddressType LegacyAddressType; + namespace { // Constants @@ -228,8 +233,8 @@ static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address) */ static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) { - // top two msb bits shall be equal to 1. - if ((address[5] >> 6) != 0x03) { + // top two msb bits shall be equal to 0b11. + if ((address[5] & 0xC0) != 0xC0) { return false; } @@ -242,8 +247,8 @@ static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) static bool is_random_private_non_resolvable_address( const BLEProtocol::AddressBytes_t address ) { - // top two msb bits shall be equal to 0. - if ((address[5] >> 6) != 0x00) { + // top two msb bits shall be equal to 0b00. + if ((address[5] & 0xC0) != 0x00) { return false; } @@ -256,8 +261,8 @@ static bool is_random_private_non_resolvable_address( static bool is_random_private_resolvable_address( const BLEProtocol::AddressBytes_t address ) { - // top two msb bits shall be equal to 01. - if ((address[5] >> 6) != 0x01) { + // top two msb bits shall be equal to 0b01. + if ((address[5] & 0xC0) != 0x40) { return false; } @@ -314,7 +319,9 @@ static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist) for (size_t i = 0; i < whitelist.size; ++i) { const BLEProtocol::Address_t& address = whitelist.addresses[i]; - if (address.type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (address.type != BLEProtocol::AddressType::PUBLIC && + address.type != BLEProtocol::AddressType::RANDOM_STATIC + ) { return false; } @@ -350,14 +357,26 @@ static bool is_in_whitelist( /* * Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t. */ -static pal::whitelist_address_type_t to_device_address_type( +static pal::whitelist_address_type_t to_whitelist_address_type( BLEProtocol::AddressType_t address_type ) { return (address_type == BLEProtocol::AddressType::PUBLIC) ? - pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : - pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; + pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : + pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; } +/* + * Convert a BLEProtocol::AddressType_t into a pal::peer_address_type + */ +static peer_address_type_t to_peer_address_type( + LegacyAddressType_t address_type +) { + return (address_type == LegacyAddressType::PUBLIC) ? + peer_address_type_t::PUBLIC : + peer_address_type_t::RANDOM; +} + + /* * Return true if the advertising parameters are valid. */ @@ -379,15 +398,21 @@ static bool is_advertising_params_valid(const GapAdvertisingParams& params) GenericGap::GenericGap( pal::EventQueue& event_queue, pal::Gap& pal_gap, - pal::GenericAccessService& generic_access_service + pal::GenericAccessService& generic_access_service, + pal::SecurityManager& pal_sm ) : _event_queue(event_queue), _pal_gap(pal_gap), _gap_service(generic_access_service), - _address_type(BLEProtocol::AddressType::PUBLIC), + _pal_sm(pal_sm), + _address_type(LegacyAddressType::PUBLIC), _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER), _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), _whitelist(), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), + _random_address_rotating(false), _advertising_timeout(), _scan_timeout(), _connection_event_handler(NULL) @@ -395,6 +420,9 @@ GenericGap::GenericGap( _pal_gap.when_gap_event_received( mbed::callback(this, &GenericGap::on_gap_event_received) ); + + // Recover static random identity + _random_static_identity_address = _pal_gap.get_random_address(); } GenericGap::~GenericGap() @@ -402,16 +430,16 @@ GenericGap::~GenericGap() } ble_error_t GenericGap::setAddress( - BLEProtocol::AddressType_t type, - const BLEProtocol::AddressBytes_t address + LegacyAddressType_t type, + const Address_t address ) { switch (type) { - case BLEProtocol::AddressType::PUBLIC: + case LegacyAddressType::PUBLIC: // The public address cannot be set, just set the type to public _address_type = type; return BLE_ERROR_NONE; - case BLEProtocol::AddressType::RANDOM_STATIC: { + case LegacyAddressType::RANDOM_STATIC: { if (is_random_static_address(address) == false) { return BLE_ERROR_INVALID_PARAM; } @@ -425,30 +453,29 @@ ble_error_t GenericGap::setAddress( _address_type = type; _address = ble::address_t(address); + _random_static_identity_address = ble::address_t(address); return BLE_ERROR_NONE; } - case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: - // TODO: Fix with the privacy/security rework - return BLE_ERROR_NOT_IMPLEMENTED; - - case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: - // TODO: add process to set the random private non resolvable - // address (privacy/security work) - return BLE_ERROR_NOT_IMPLEMENTED; + case LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE: + case LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + // Note: it is not allowed to set directly these addresses + // privacy management handled it for users. + return BLE_ERROR_INVALID_PARAM; default: - return BLE_ERROR_PARAM_OUT_OF_RANGE; + return BLE_ERROR_INVALID_PARAM; } } ble_error_t GenericGap::getAddress( - BLEProtocol::AddressType_t *type, - BLEProtocol::AddressBytes_t address + LegacyAddressType_t *type, + Address_t address ) { *type = _address_type; ble::address_t address_value; - if (_address_type == BLEProtocol::AddressType::PUBLIC) { + + if (_address_type == LegacyAddressType::PUBLIC) { address_value = _pal_gap.get_device_address(); } else { address_value = _pal_gap.get_random_address(); @@ -481,6 +508,10 @@ ble_error_t GenericGap::stopAdvertising() } _advertising_timeout.detach(); state.advertising = false; + + // Stop address rotation if required + set_random_address_rotation(false); + return BLE_ERROR_NONE; } @@ -491,15 +522,18 @@ ble_error_t GenericGap::stopScan() return err; } + // Stop address rotation if required + set_random_address_rotation(false); + _scan_timeout.detach(); return BLE_ERROR_NONE; } ble_error_t GenericGap::connect( - const BLEProtocol::AddressBytes_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t* connectionParams, - const GapScanningParams* scanParams + const Address_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams ) { if (connectionParams == NULL) { connectionParams = &default_connection_params; @@ -517,8 +551,6 @@ ble_error_t GenericGap::connect( return BLE_ERROR_PARAM_OUT_OF_RANGE; } - // TODO fix upper layer API, address type factorization is incorrect. - // Force scan stop before initiating the scan used for connection stopScan(); @@ -526,9 +558,9 @@ ble_error_t GenericGap::connect( scanParams->getInterval(), scanParams->getWindow(), _initiator_policy_mode, - (pal::connection_peer_address_type_t::type) peerAddrType, + (pal::connection_peer_address_type_t::type) peerAddrType.value(), ble::address_t(peerAddr), - (pal::own_address_type_t::type) _address_type, + get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */), connectionParams->minConnectionInterval, connectionParams->maxConnectionInterval, connectionParams->slaveLatency, @@ -538,6 +570,21 @@ ble_error_t GenericGap::connect( ); } + +ble_error_t GenericGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams +) { + return connect( + peerAddr, + to_peer_address_type(peerAddrType), + connectionParams, + scanParams + ); +} + ble_error_t GenericGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) { if (is_disconnection_reason_valid(reason) == false) { @@ -688,7 +735,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { ble_error_t err = _pal_gap.remove_device_from_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); @@ -699,7 +746,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -715,7 +762,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, _whitelist) == false) { ble_error_t err = _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); @@ -727,7 +774,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, _whitelist) == false) { _pal_gap.remove_device_from_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -739,7 +786,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -816,11 +863,19 @@ ble_error_t GenericGap::startRadioScan(const GapScanningParams &scanningParams) return BLE_ERROR_INVALID_STATE; } + pal::own_address_type_t own_address_type = get_own_address_type(CENTRAL_SCAN /* central, can use non resolvable address for scan requests */); + + if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) + { + // Use non-resolvable static random address + set_random_address_rotation(true); + } + ble_error_t err = _pal_gap.set_scan_parameters( scanningParams.getActiveScanning(), scanningParams.getInterval(), scanningParams.getWindow(), - get_own_address_type(), + own_address_type, _scanning_filter_policy ); @@ -851,6 +906,66 @@ ble_error_t GenericGap::initRadioNotification(void) return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t GenericGap::enablePrivacy(bool enable) +{ + if(enable == _privacy_enabled) { + // No change + return BLE_ERROR_NONE; + } + + if(enable && !_pal_gap.is_privacy_supported()) + { + // Privacy is not supported by the implementation + return BLE_ERROR_NOT_IMPLEMENTED; + } + + _privacy_enabled = enable; + + update_address_resolution_setting(); + + return BLE_ERROR_NONE; +} + +ble_error_t GenericGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) +{ + _peripheral_privacy_configuration = *configuration; + + update_address_resolution_setting(); + + return BLE_ERROR_NONE; +} + +ble_error_t GenericGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) +{ + *configuration = _peripheral_privacy_configuration; + + return BLE_ERROR_NONE; +} + +ble_error_t GenericGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) +{ + _central_privacy_configuration = *configuration; + + update_address_resolution_setting(); + + return BLE_ERROR_NONE; +} + +ble_error_t GenericGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) +{ + *configuration = _central_privacy_configuration; + + return BLE_ERROR_NONE; +} + ble_error_t GenericGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) { ble_error_t err = _pal_gap.set_advertising_data( @@ -873,6 +988,21 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) return BLE_ERROR_INVALID_PARAM; } + // We can only use non resolvable addresses if the device is non connectable + AddressUseType_t address_use_type = + ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) || + (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ? + PERIPHERAL_NON_CONNECTABLE : + PERIPHERAL_CONNECTABLE; + + pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); + + if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) + { + // Use non-resolvable static random address + set_random_address_rotation(true); + } + // TODO: fix the high level API to have a min/max range // Going against recommendations (The Advertising_Interval_Min and // Advertising_Interval_Max should not be the same value to enable the @@ -883,7 +1013,7 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) /* advertising_interval_min */ params.getIntervalInADVUnits(), /* advertising_interval_max */ params.getIntervalInADVUnits(), (pal::advertising_type_t::type) params.getAdvertisingType(), - get_own_address_type(), + own_address_type, pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, ble::address_t(), pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, @@ -925,11 +1055,13 @@ ble_error_t GenericGap::reset(void) void GenericGap::processConnectionEvent( Handle_t handle, Role_t role, - BLEProtocol::AddressType_t peerAddrType, + PeerAddressType_t peerAddrType, const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr ) { if (_connection_event_handler) { _connection_event_handler->on_connected( @@ -950,7 +1082,9 @@ void GenericGap::processConnectionEvent( peerAddr, ownAddrType, ownAddr, - connectionParams + connectionParams, + peerResolvableAddr, + localResolvableAddr ); } @@ -996,6 +1130,10 @@ void GenericGap::process_advertising_timeout() if (err) { // TODO: define the mechanism signaling the error } + + // Stop address rotation if required + set_random_address_rotation(false); + processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); } @@ -1036,6 +1174,21 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) for (size_t i = 0; i < e.size(); ++i) { pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; + // Check if the address hasn't been resolved + if(_privacy_enabled && + _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER && + advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS && + is_random_private_resolvable_address(advertising.address.data()) + ) { + // Filter it out + continue; + } + + // note 1-to-1 conversion between connection_peer_address_type_t and + // peer_address_type_t + peer_address_type_t peer_address_type = + static_cast(advertising.address_type.value()); + processAdvertisementReport( advertising.address.data(), advertising.rssi, @@ -1043,51 +1196,105 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(), advertising.data.size(), advertising.data.data(), - (BLEProtocol::AddressType_t) advertising.address_type.value() + peer_address_type ); } } void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e) { - // TODO: deprecate ownAddrType and ownAddr, those are not specified - // from the Bluetooth perspective - if (e.status == pal::hci_error_code_t::SUCCESS) { - if (e.role.value() == e.role.SLAVE) { - _advertising_timeout.detach(); - _pal_gap.advertising_enable(false); - } - - // using these parameters if stupid, there is no range for the - // connection interval when the connection is established - ConnectionParams_t connection_params = { - /* minConnectionInterval */ e.connection_interval, - /* maxConnectionInterval */ e.connection_interval, - e.connection_latency, - e.supervision_timeout - }; - ble::address_t address; - if (_address_type == BLEProtocol::AddressType::PUBLIC) { - address = _pal_gap.get_device_address(); - } else { - address = _pal_gap.get_random_address(); - } - - processConnectionEvent( - e.connection_handle, - e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, - (BLEProtocol::AddressType_t) e.peer_address_type.value(), - e.peer_address.data(), - _address_type, - address.data(), - &connection_params - ); - } else { + if (e.status != pal::hci_error_code_t::SUCCESS) { // for now notify user that the connection failled by issuing a timeout // event // TODO: Define events in case of connection faillure processTimeoutEvent(Gap::TIMEOUT_SRC_CONN); + return; + } + + bool needs_pairing = false; + bool needs_authentication = false; + + if (_privacy_enabled && + e.role.value() == e.role.SLAVE && + e.peer_address_type == peer_address_type_t::RANDOM + ) { + // Apply privacy policy if in peripheral mode for non-resolved addresses + RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); + ble_error_t err = getRandomAddressType(e.peer_address.data(), &random_address_type); + if (err) { + // FIXME: return for now; needs to report the error ? + return; + } + + if (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE) { + switch(_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: + // Reject connection request - the user will get notified through a callback + _pal_gap.disconnect( + e.connection_handle, + pal::disconnection_reason_t::AUTHENTICATION_FAILLURE + ); + return; + + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + needs_pairing = true; + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + needs_authentication = true; + break; + + default: + break; + } + } + } + + if (e.role.value() == e.role.SLAVE) { + _advertising_timeout.detach(); + _pal_gap.advertising_enable(false); + + // Stop address rotation if required + set_random_address_rotation(false); + } + + // using these parameters if stupid, there is no range for the + // connection interval when the connection is established + ConnectionParams_t connection_params = { + /* minConnectionInterval */ e.connection_interval, + /* maxConnectionInterval */ e.connection_interval, + e.connection_latency, + e.supervision_timeout + }; + + ble::address_t address; + if (_address_type == LegacyAddressType::PUBLIC) { + address = _pal_gap.get_device_address(); + } else { + address = _pal_gap.get_random_address(); + } + + processConnectionEvent( + e.connection_handle, + e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, + e.peer_address_type, + e.peer_address.data(), + _address_type, + address.data(), + &connection_params, + e.local_resolvable_private_address.data(), + e.peer_resolvable_private_address.data() + ); + + // Now starts pairing or authentication procedures if required + if(needs_pairing) { + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + // Request authentication to start pairing procedure + sm.requestAuthentication(e.connection_handle); + } else if(needs_authentication) { + // TODO: GAP Authentication != Security Manager authentication + // Needs to be implemented } } @@ -1130,19 +1337,34 @@ void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) // has been updated. } -pal::own_address_type_t GenericGap::get_own_address_type() +pal::own_address_type_t GenericGap::get_own_address_type(AddressUseType_t address_use_type) { + if(_privacy_enabled) { + bool use_non_resolvable_address = false; + if(address_use_type == CENTRAL_SCAN) { + use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; + } else if (address_use_type == PERIPHERAL_NON_CONNECTABLE) { + use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; + } + + // An non resolvable private address should be generated + if(use_non_resolvable_address) { + return pal::own_address_type_t::RANDOM_ADDRESS; + } + + switch (_address_type) { + case BLEProtocol::AddressType::PUBLIC: + return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; + default: + return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK; + } + } + switch (_address_type) { case BLEProtocol::AddressType::PUBLIC: return pal::own_address_type_t::PUBLIC_ADDRESS; - case BLEProtocol::AddressType::RANDOM_STATIC: - case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: - return pal::own_address_type_t::RANDOM_ADDRESS; - case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: - return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; default: - // not reachable - return pal::own_address_type_t::PUBLIC_ADDRESS; + return pal::own_address_type_t::RANDOM_ADDRESS; } } @@ -1169,6 +1391,104 @@ bool GenericGap::initialize_whitelist() const return true; } +ble_error_t GenericGap::update_address_resolution_setting() +{ + // Only disable if privacy is disabled or resolution is not requested in either central or peripheral mode + bool enable = true; + + if(!_privacy_enabled) { + enable = false; + } + else if( (_peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) + && (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) ) { + enable = false; + } + + return _pal_gap.set_address_resolution(enable); +} + +void GenericGap::set_random_address_rotation(bool enable) +{ + if(enable == _random_address_rotating) { + return; + } + + _random_address_rotating = enable; + + if(enable) { + // Set first address + update_random_address(); + + // Schedule rotations every 15 minutes as recomended by the spec + _address_rotation_ticker.attach_us( + mbed::callback(this, &GenericGap::on_address_rotation_timeout), + 15 * 60 * 1000000U + ); + } + else { + // Stop ticker + _address_rotation_ticker.detach(); + + // Set static random identity address + _pal_gap.set_random_address( + _random_static_identity_address + ); + } +} + +void GenericGap::update_random_address() +{ + if(!_random_address_rotating) + { + // This event might have been queued before we disabled address rotation + return; + } + + ble::address_t address; + + do { + byte_array_t<8> random_data; + + ble_error_t ret = _pal_sm.get_random_data(random_data); + if (ret != BLE_ERROR_NONE) { + // Abort + return; + } + + // Build a non-resolvable private address as specified in the Core 4.2 spec, Vol 6, Part B, 1.3.2.2 + // Mask out two MSbs + random_data[5] &= 0x3F; + + // Copy to address - will copy first 6 bytes + address = ble::address_t(random_data.data()); + + if(!is_random_private_non_resolvable_address(address.data())) + { + // If address is invalid, which is unlikely (all 0s or all 1s), try again + // If implementation is faulty, we'll get stuck here + continue; + } + + // Address is valid + break; + } while(true); + + ble_error_t err = _pal_gap.set_random_address( + address + ); + if (err) { + return; + } + + _address_type = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + _address = address; +} + +void GenericGap::on_address_rotation_timeout() +{ + _event_queue.post(mbed::callback(this, &GenericGap::update_random_address)); +} + void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) { _connection_event_handler = connection_event_handler; diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index a121952f12..193f9071d6 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -21,6 +21,8 @@ #include #include "ble/generic/GenericGattClient.h" #include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" +#include "ble/generic/GenericSecurityManager.h" #include using ble::pal::AttServerMessage; @@ -38,6 +40,11 @@ using ble::pal::AttHandleValueIndication; using ble::pal::AttHandleValueNotification; using ble::pal::AttFindInformationResponse; +#define PREPARE_WRITE_HEADER_LENGTH 5 +#define WRITE_HEADER_LENGTH 3 +#define CMAC_LENGTH 8 +#define MAC_COUNTER_LENGTH 4 + namespace ble { namespace generic { @@ -930,6 +937,7 @@ struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureCont GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : _pal_client(pal_client), _termination_callback(), + _signing_event_handler(NULL), control_blocks(NULL), _is_reseting(false) { _pal_client->when_server_message_received( @@ -1075,67 +1083,94 @@ ble_error_t GenericGattClient::write( return BLE_ERROR_INVALID_STATE; } - uint16_t mtu = get_mtu(connection_handle); + uint16_t mtu = get_mtu(connection_handle); - if (cmd == GattClient::GATT_OP_WRITE_CMD) { - if (length > (uint16_t)(mtu - 3)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - return _pal_client->write_without_response( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } else { - uint8_t* data = NULL; + /* if link is encrypted signed writes should be normal writes */ + if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + ble_error_t status = sm.getLinkEncryption(connection_handle, &encryption); + if (status == BLE_ERROR_NONE && + (encryption == link_encryption_t::ENCRYPTED || + encryption == link_encryption_t::ENCRYPTED_WITH_MITM || + encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) + ) { + cmd = GattClient::GATT_OP_WRITE_CMD; + } + } - if (length > (uint16_t)(mtu - 3)) { - data = (uint8_t*) malloc(length); - if (data == NULL) { - return BLE_ERROR_NO_MEM; - } - memcpy(data, value, length); - } + if (cmd == GattClient::GATT_OP_WRITE_CMD) { + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + ble_error_t status = _pal_client->signed_write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + if (_signing_event_handler && (status == BLE_ERROR_NONE)) { + _signing_event_handler->on_signed_write(); + } + return status; + } else { + uint8_t* data = NULL; - WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock( - connection_handle, - attribute_handle, - data, - length - ); + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } - if (write_pcb == NULL) { - free(data); - return BLE_ERROR_NO_MEM; - } + WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock( + connection_handle, + attribute_handle, + data, + length + ); - insert_control_block(write_pcb); + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } - ble_error_t err = BLE_ERROR_UNSPECIFIED; - if (data) { - err = _pal_client->queue_prepare_write( - connection_handle, - attribute_handle, - make_const_ArrayView(value, mtu - 5), - /* offset */ 0 - ); - } else { - err = _pal_client->write_attribute( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } + insert_control_block(write_pcb); - if (err) { - remove_control_block(write_pcb); - delete write_pcb; - } + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (data) { + err = _pal_client->queue_prepare_write( + connection_handle, + attribute_handle, + make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), + /* offset */0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } - return err; - } + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } - return BLE_ERROR_NOT_IMPLEMENTED; + return err; + } + + return BLE_ERROR_NOT_IMPLEMENTED; } void GenericGattClient::onServiceDiscoveryTermination( @@ -1238,6 +1273,12 @@ ble_error_t GenericGattClient::reset(void) { return BLE_ERROR_NONE; } +void GenericGattClient::set_signing_event_handler( + EventHandler *signing_event_handler +) { + _signing_event_handler = signing_event_handler; +} + void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { if (_termination_callback) { _termination_callback(connection_handle); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 1568f11fb2..7a12d12fa6 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -17,9 +17,8 @@ #include "ble/SecurityManager.h" #include "ble/pal/PalSecurityManager.h" #include "ble/generic/GenericSecurityManager.h" -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif +#include "ble/generic/MemorySecurityDb.h" +#include "ble/generic/FileSecurityDb.h" using ble::pal::advertising_peer_address_type_t; using ble::pal::AuthenticationMask; @@ -40,9 +39,21 @@ ble_error_t GenericSecurityManager::init( bool mitm, SecurityIOCapabilities_t iocaps, const Passkey_t passkey, - bool signing + bool signing, + const char* db_path ) { - _db.restore(); + ble_error_t result = _pal.initialize(); + + if (result != BLE_ERROR_NONE) { + return result; + } + + result = init_database(db_path); + + if (result != BLE_ERROR_NONE) { + return result; + } + _pal.set_io_capability((io_capability_t::type) iocaps); if (passkey) { @@ -61,7 +72,8 @@ ble_error_t GenericSecurityManager::init( _default_authentication.set_secure_connections(secure_connections); _default_authentication.set_keypress_notification(true); - _default_key_distribution.set_link(secure_connections); + // FIXME: depends on BR/EDR support + _default_key_distribution.set_link(false); _default_key_distribution.set_signing(signing); if (signing) { @@ -69,23 +81,51 @@ ble_error_t GenericSecurityManager::init( } _connection_monitor.set_connection_event_handler(this); + _signing_monitor.set_signing_event_handler(this); _pal.set_event_handler(this); - _pal.generate_public_key(); + result = init_resolving_list(); + + if (result != BLE_ERROR_NONE) { + delete _db; + return result; + } + + return BLE_ERROR_NONE; +} + +ble_error_t GenericSecurityManager::setDatabaseFilepath( + const char *db_path +) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + /* operation only allowed with no connections active */ + for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { + if (_control_blocks[i].connected) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + } + + ble_error_t result = init_database(db_path); + if (result != BLE_ERROR_NONE) { + return result; + } + + init_resolving_list(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::reset(void) { - _db.sync(); - _public_keys_generated = false; + _pal.reset(); SecurityManager::reset(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { - _db.set_restore(enabled); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + _db->set_restore(enabled); return BLE_ERROR_NONE; } @@ -94,13 +134,15 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { // ble_error_t GenericSecurityManager::purgeAllBondingState(void) { - _db.clear_entries(); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + _db->clear_entries(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (eventHandler) { - _db.generate_whitelist_from_bond_table( + _db->generate_whitelist_from_bond_table( mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable), whitelist ); @@ -113,6 +155,7 @@ ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelis // ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -133,7 +176,14 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio /* by default the initiator doesn't send any keys other then identity */ KeyDistribution initiator_distribution( - KeyDistribution::KEY_DISTRIBUTION_IDENTITY | _default_key_distribution.get_link() + KeyDistribution::KEY_DISTRIBUTION_IDENTITY | + _default_key_distribution.get_link() + ); + + initiator_distribution.set_signing( + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() ); /* if requested the initiator may send all the default keys for later @@ -142,14 +192,6 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio initiator_distribution = _default_key_distribution; } - /* override default if requested */ - if (cb->signing_override_default) { - initiator_distribution.set_signing(cb->signing_requested); - } else { - /* because _master_sends_keys might be false so we need to set this */ - initiator_distribution.set_signing(_default_key_distribution.get_signing()); - } - KeyDistribution responder_distribution(_default_key_distribution); if (cb->signing_override_default) { @@ -166,6 +208,7 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio } ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -180,16 +223,23 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con KeyDistribution initiator_distribution = cb->get_initiator_key_distribution(); + bool master_signing = initiator_distribution.get_signing(); + if (_master_sends_keys) { initiator_distribution &= _default_key_distribution; } else { - initiator_distribution &= KeyDistribution(KeyDistribution::KEY_DISTRIBUTION_IDENTITY | KeyDistribution::KEY_DISTRIBUTION_LINK); + initiator_distribution &= KeyDistribution( + KeyDistribution::KEY_DISTRIBUTION_IDENTITY | + KeyDistribution::KEY_DISTRIBUTION_LINK + ); } /* signing has to be offered and enabled on the link */ - if (initiator_distribution.get_signing()) { + if (master_signing) { initiator_distribution.set_signing( - cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing() + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() ); } @@ -200,7 +250,9 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con /* signing has to be requested and enabled on the link */ if (responder_distribution.get_signing()) { responder_distribution.set_signing( - cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing() + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() ); } @@ -214,10 +266,12 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con } ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON); } ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _pairing_authorisation_required = required; return BLE_ERROR_NONE; } @@ -240,10 +294,12 @@ ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) { // ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_io_capability((io_capability_t::type) iocaps); } ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_display_passkey(PasskeyAscii::to_num(passkey)); } @@ -251,6 +307,7 @@ ble_error_t GenericSecurityManager::setAuthenticationTimeout( connection_handle_t connection, uint32_t timeout_in_ms ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_authentication_timeout(connection, timeout_in_ms / 10); } @@ -258,6 +315,7 @@ ble_error_t GenericSecurityManager::getAuthenticationTimeout( connection_handle_t connection, uint32_t *timeout_in_ms ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; uint16_t timeout_in_10ms; ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms); *timeout_in_ms = 10 * timeout_in_10ms; @@ -268,6 +326,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity( connection_handle_t connection, SecurityMode_t securityMode ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -299,6 +358,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity( } ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _default_authentication.set_keypress_notification(enabled); return BLE_ERROR_NONE; } @@ -307,24 +367,38 @@ ble_error_t GenericSecurityManager::enableSigning( connection_handle_t connection, bool enabled ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } - cb->signing_requested = enabled; - cb->signing_override_default = false; - - if (cb->encrypted) { - return BLE_ERROR_INVALID_STATE; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; } - if (!cb->csrk_stored && cb->signing_requested) { - init_signing(); - if (cb->is_master) { - return requestPairing(connection); + + cb->signing_override_default = true; + + if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { + cb->signing_requested = true; + if (flags->csrk_stored) { + /* used the stored ones when available */ + _db->get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); } else { - return slave_security_request(connection); + /* create keys if needed and exchange them */ + init_signing(); + if (cb->is_master) { + return requestPairing(connection); + } else { + return slave_security_request(connection); + } } + } else { + cb->signing_requested = enabled; } return BLE_ERROR_NONE; @@ -343,15 +417,24 @@ ble_error_t GenericSecurityManager::getLinkEncryption( connection_handle_t connection, link_encryption_t *encryption ) { - + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + if (cb->encrypted) { - if (cb->ltk_mitm_protected || cb->mitm_performed) { - *encryption = link_encryption_t::ENCRYPTED_WITH_MITM; + if (flags->ltk_mitm_protected || cb->mitm_performed) { + if (flags->secure_connections_paired) { + *encryption = link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM; + } else { + *encryption = link_encryption_t::ENCRYPTED_WITH_MITM; + } } else { *encryption = link_encryption_t::ENCRYPTED; } @@ -368,11 +451,17 @@ ble_error_t GenericSecurityManager::setLinkEncryption( connection_handle_t connection, link_encryption_t encryption ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED); getLinkEncryption(connection, ¤t_encryption); @@ -385,20 +474,34 @@ ble_error_t GenericSecurityManager::setLinkEncryption( /* ignore if the link is already at required state*/ } else if (encryption == link_encryption_t::NOT_ENCRYPTED) { - - /* ignore if we are requesting an open link on an already encrypted link */ - + // Fail as it is not permitted to turn down encryption + return BLE_ERROR_OPERATION_NOT_PERMITTED; } else if (encryption == link_encryption_t::ENCRYPTED) { /* only change if we're not already encrypted with mitm */ - if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM) { + if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM || + current_encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { cb->encryption_requested = true; return enable_encryption(connection); } } else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) { - if (cb->ltk_mitm_protected && !cb->encrypted) { + if (flags->ltk_mitm_protected && !cb->encrypted) { + cb->encryption_requested = true; + return enable_encryption(connection); + } else { + cb->encryption_requested = true; + return requestAuthentication(connection); + } + + } else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + + if (flags->ltk_mitm_protected && + flags->secure_connections_paired && + !cb->encrypted + ) { cb->encryption_requested = true; return enable_encryption(connection); } else { @@ -419,19 +522,26 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize( connection_handle_t connection, uint8_t *size ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); - if (cb) { - *size = cb->encryption_key_size; - return BLE_ERROR_NONE; - } else { + if (!cb) { return BLE_ERROR_INVALID_PARAM; } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + *size = flags->encryption_key_size; + return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( uint8_t minimumByteSize, uint8_t maximumByteSize ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize); } @@ -440,15 +550,21 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( // ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } - if (cb->csrk_stored && (cb->csrk_mitm_protected || !authenticated)) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + if (flags->csrk_stored && (flags->csrk_mitm_protected || !authenticated)) { /* we have a key that is either authenticated or we don't care if it is * so retrieve it from the db now */ - _db.get_entry_peer_csrk( + _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::return_csrk_cb), cb->db_entry ); @@ -472,6 +588,7 @@ ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection // ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_private_address_timeout(timeout_in_seconds); } @@ -480,12 +597,18 @@ ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in // ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } - if (cb->ltk_mitm_protected) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + if (flags->ltk_mitm_protected) { if (cb->authenticated) { return BLE_ERROR_NONE; } else { @@ -506,11 +629,50 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co // MITM // +ble_error_t GenericSecurityManager::generateOOB( + const address_t *address +) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + /* legacy pairing */ + ble_error_t status = get_random_data(_oob_temporary_key.data(), 16); + + if (status == BLE_ERROR_NONE) { + _oob_temporary_key_creator_address = *address; + + eventHandler->legacyPairingOobGenerated( + &_oob_temporary_key_creator_address, + &_oob_temporary_key + ); + } else { + return status; + } + + /* Secure connections. Avoid generating if we're already waiting for it. + * If a local random is set to 0 it means we're already calculating. */ + if (!is_all_zeros(_oob_local_random)) { + status = _pal.generate_secure_connections_oob(); + + if (status == BLE_ERROR_NONE) { + _oob_local_address = *address; + /* this will be updated when calculation completes, + * a value of all zeros is an invalid random value */ + set_all_zeros(_oob_local_random); + } else if (status != BLE_ERROR_NOT_IMPLEMENTED) { + return status; + } + } else { + return BLE_STACK_BUSY; + } + + return BLE_ERROR_NONE; +} + ble_error_t GenericSecurityManager::setOOBDataUsage( connection_handle_t connection, bool useOOB, bool OOBProvidesMITM ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -519,19 +681,18 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; -#if defined(MBEDTLS_CMAC_C) - if (_public_keys_generated) { - generate_secure_connections_oob(connection); + if (useOOB) { + return generateOOB(&cb->local_address); + } else { + return BLE_ERROR_NONE; } -#endif - - return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::confirmationEntered( connection_handle_t connection, bool confirmation ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.confirmation_entered(connection, confirmation); } @@ -539,6 +700,7 @@ ble_error_t GenericSecurityManager::passkeyEntered( connection_handle_t connection, Passkey_t passkey ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.passkey_request_reply( connection, PasskeyAscii::to_num(passkey) @@ -549,6 +711,7 @@ ble_error_t GenericSecurityManager::sendKeypressNotification( connection_handle_t connection, Keypress_t keypress ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.send_keypress_notification(connection, keypress); } @@ -556,13 +719,32 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( const address_t *address, const oob_tk_t *tk ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (address && tk) { ControlBlock_t *cb = get_control_block(*address); if (!cb) { return BLE_ERROR_INVALID_PARAM; } - return _pal.legacy_pairing_oob_data_request_reply(cb->connection, *tk); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + _oob_temporary_key = *tk; + _oob_temporary_key_creator_address = *address; + + if (flags->peer_address == _oob_temporary_key_creator_address) { + cb->attempt_oob = true; + } + + if (cb->legacy_pairing_oob_request_pending) { + on_legacy_pairing_oob_request(cb->connection); + /* legacy_pairing_oob_request_pending stops us from + * going into a loop of asking the user for oob + * so this reset needs to happen after the call above */ + cb->legacy_pairing_oob_request_pending = false; + } } return BLE_ERROR_NONE; } @@ -572,10 +754,11 @@ ble_error_t GenericSecurityManager::oobReceived( const oob_lesc_value_t *random, const oob_confirm_t *confirm ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (address && random && confirm) { - _peer_sc_oob_address = *address; - _peer_sc_oob_random = *random; - _peer_sc_oob_confirm = *confirm; + _oob_peer_address = *address; + _oob_peer_random = *random; + _oob_peer_confirm = *confirm; return BLE_ERROR_NONE; } @@ -586,20 +769,72 @@ ble_error_t GenericSecurityManager::oobReceived( // Helper functions // +ble_error_t GenericSecurityManager::init_database( + const char *db_path +) { + delete _db; + + FILE* db_file = FileSecurityDb::open_db_file(db_path); + + if (db_file) { + _db = new (std::nothrow) FileSecurityDb(db_file); + } else { + _db = new (std::nothrow) MemorySecurityDb(); + } + + if (!_db) { + return BLE_ERROR_NO_MEM; + } + + _db->restore(); + + return BLE_ERROR_NONE; +} + +ble_error_t GenericSecurityManager::init_resolving_list() { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + /* match the resolving list to the currently stored set of IRKs */ + uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity(); + SecurityEntryIdentity_t* identity_list_p = + new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity]; + + if (identity_list_p) { + ArrayView identity_list( + identity_list_p, + resolving_list_capacity + ); + + _db->get_identity_list( + mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), + identity_list + ); + } else { + return BLE_ERROR_NO_MEM; + } + + return BLE_ERROR_NONE; +} + ble_error_t GenericSecurityManager::init_signing() { - const csrk_t *pcsrk = _db.get_local_csrk(); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + const csrk_t *pcsrk = _db->get_local_csrk(); + sign_count_t local_sign_counter = _db->get_local_sign_counter(); + if (!pcsrk) { csrk_t csrk; - ble_error_t ret = get_random_data(csrk.buffer(), csrk.size()); + ble_error_t ret = get_random_data(csrk.data(), csrk.size()); if (ret != BLE_ERROR_NONE) { return ret; } pcsrk = &csrk; - _db.set_local_csrk(csrk); + _db->set_local_csrk(csrk); + _db->set_local_sign_counter(local_sign_counter); } - return _pal.set_csrk(*pcsrk); + + return _pal.set_csrk(*pcsrk, local_sign_counter); } ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) { @@ -613,7 +848,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size if (ret != BLE_ERROR_NONE) { return ret; } - memcpy(buffer, random_data.buffer(), copy_size); + memcpy(buffer, random_data.data(), copy_size); size -= copy_size; buffer += copy_size; } @@ -622,6 +857,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size } ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -632,13 +868,20 @@ ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t c } ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + if (cb->is_master) { - if (cb->ltk_stored) { - _db.get_entry_peer_keys( + if (flags->ltk_stored) { + _db->get_entry_peer_keys( mbed::callback(this, &GenericSecurityManager::enable_encryption_cb), cb->db_entry ); @@ -652,172 +895,177 @@ ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connec } void GenericSecurityManager::enable_encryption_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } - if (cb && entryKeys) { - if (cb->secure_connections_paired) { - _pal.enable_encryption(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (entryKeys) { + if (flags->secure_connections_paired) { + _pal.enable_encryption(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected); } else { - _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, cb->ltk_mitm_protected); + _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, flags->ltk_mitm_protected); } } } void GenericSecurityManager::set_ltk_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } - if (cb) { - if (entryKeys) { - _pal.set_ltk(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected, cb->secure_connections_paired); - } else { - _pal.set_ltk_not_found(cb->connection); - } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (entryKeys) { + _pal.set_ltk( + cb->connection, + entryKeys->ltk, + flags->ltk_mitm_protected, + flags->secure_connections_paired + ); + } else { + _pal.set_ltk_not_found(cb->connection); } } -void GenericSecurityManager::return_csrk_cb( - pal::SecurityDb::entry_handle_t db_entry, - const csrk_t *csrk +void GenericSecurityManager::set_peer_csrk_cb( + SecurityDb::entry_handle_t db_entry, + const SecurityEntrySigning_t* signing ) { ControlBlock_t *cb = get_control_block(db_entry); - if (!cb) { + if (!cb || !signing) { + return; + } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + _pal.set_peer_csrk( + cb->connection, + signing->csrk, + flags->csrk_mitm_protected, + signing->counter + ); +} + +void GenericSecurityManager::return_csrk_cb( + SecurityDb::entry_handle_t db_entry, + const SecurityEntrySigning_t *signing +) { + MBED_ASSERT(_db); + ControlBlock_t *cb = get_control_block(db_entry); + if (!cb || !signing) { + return; + } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { return; } eventHandler->signingKey( cb->connection, - csrk, - cb->csrk_mitm_protected + &signing->csrk, + flags->csrk_mitm_protected ); } -#if defined(MBEDTLS_CMAC_C) -void GenericSecurityManager::generate_secure_connections_oob( - connection_handle_t connection -) { - oob_confirm_t confirm; - oob_lesc_value_t random; - - ControlBlock_t *cb = get_control_block(connection); - if (!cb) { - return; - } - - ble_error_t ret = get_random_data(random.buffer(), random.size()); - if (ret != BLE_ERROR_NONE) { - return; - } - - crypto_toolbox_f4( - _db.get_public_key_x(), - _db.get_public_key_y(), - random, - confirm - ); - - eventHandler->oobGenerated( - &cb->local_address, - &random, - &confirm - ); - - _local_sc_oob_random = random; -} -#endif - void GenericSecurityManager::update_oob_presence(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - /* only update the oob state if we support secure connections, - * otherwise follow the user set preference for providing legacy - * pairing oob data */ - cb->oob_present = cb->attempt_oob; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + /* if we support secure connection we only care about secure connections oob data */ if (_default_authentication.get_secure_connections()) { - cb->oob_present = false; -#if defined(MBEDTLS_CMAC_C) - if (cb->peer_address == _peer_sc_oob_address) { + cb->oob_present = (flags->peer_address == _oob_peer_address); + } else { + /* otherwise for legacy pairing we first set the oob based on set preference */ + cb->oob_present = cb->attempt_oob; + + /* and also turn it on if we have oob data for legacy pairing */ + if (flags->peer_address == _oob_temporary_key_creator_address + || cb->local_address == _oob_temporary_key_creator_address) { cb->oob_present = true; } -#endif } } -#if defined(MBEDTLS_CMAC_C) -bool GenericSecurityManager::crypto_toolbox_f4( - const public_key_coord_t& U, - const public_key_coord_t& V, - const oob_lesc_value_t& X, - oob_confirm_t& confirm -) { - - mbedtls_cipher_context_t context; - const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); - const unsigned char Z = 0; - bool success = false; - - mbedtls_cipher_init(&context); - - /* it's either this chaining or a goto */ - if (mbedtls_cipher_setup(&context, info) == 0 - && mbedtls_cipher_cmac_starts(&context, X.data(), 128) == 0 - && mbedtls_cipher_cmac_update(&context, U.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, V.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, &Z, 1) == 0 - && mbedtls_cipher_cmac_finish(&context, &confirm[0]) == 0) { - success = true; - } - - mbedtls_cipher_free(&context); - return success; -} -#endif - void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) { ControlBlock_t *cb = get_control_block(connection); if (cb) { cb->mitm_performed = enable; + /* whenever we reset mitm performed we also reset pending requests + * as this happens whenever a new pairing attempt happens */ + if (!enable) { + cb->legacy_pairing_oob_request_pending = false; + } } } void GenericSecurityManager::on_connected( connection_handle_t connection, Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, const Gap::ConnectionParams_t *connection_params ) { + MBED_ASSERT(_db); ControlBlock_t *cb = acquire_control_block(connection); if (!cb) { return; } // setup the control block - cb->peer_address = peer_address; cb->local_address = local_address; - cb->peer_address_is_public = - (peer_address_type == BLEProtocol::AddressType::PUBLIC); cb->is_master = (role == Gap::CENTRAL); // get the associated db handle and the distribution flags if any - cb->db_entry = _db.open_entry(peer_address_type, peer_address); + cb->db_entry = _db->open_entry(peer_address_type, peer_address); - const pal::SecurityDistributionFlags_t* dist_flags = - _db.get_distribution_flags(cb->db_entry); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); - if (dist_flags) { - *static_cast(cb) = *dist_flags; + flags->peer_address = peer_address; + flags->peer_address_is_public = + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY); + + const bool signing = cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing(); + + if (signing && flags->csrk_stored) { + _db->get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); } } @@ -825,17 +1073,58 @@ void GenericSecurityManager::on_disconnected( connection_handle_t connection, Gap::DisconnectionReason_t reason ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.close_entry(cb->db_entry); - release_control_block(cb); + _pal.remove_peer_csrk(connection); - _db.sync(); + _db->close_entry(cb->db_entry); + release_control_block(cb); } +void GenericSecurityManager::on_security_entry_retrieved( + SecurityDb::entry_handle_t entry, + const SecurityEntryIdentity_t* identity +) { + if (!identity) { + return; + } + + typedef advertising_peer_address_type_t address_type_t; + + _pal.add_device_to_resolving_list( + identity->identity_address_is_public ? + address_type_t::PUBLIC_ADDRESS : + address_type_t::RANDOM_ADDRESS, + identity->identity_address, + identity->irk + ); +} + +void GenericSecurityManager::on_identity_list_retrieved( + ble::ArrayView& identity_list, + size_t count +) { + typedef advertising_peer_address_type_t address_type_t; + + _pal.clear_resolving_list(); + for (size_t i = 0; i < count; ++i) { + _pal.add_device_to_resolving_list( + identity_list[i].identity_address_is_public ? + address_type_t::PUBLIC_ADDRESS : + address_type_t::RANDOM_ADDRESS, + identity_list[i].identity_address, + identity_list[i].irk + ); + } + + delete [] identity_list.data(); +} + + /* Implements ble::pal::SecurityManagerEventHandler */ //////////////////////////////////////////////////////////////////////////// @@ -903,10 +1192,13 @@ void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection } void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (cb) { - // set the distribution flags in the db - _db.set_distribution_flags(cb->db_entry, *cb); + _db->get_entry_identity( + mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved), + cb->db_entry + ); } eventHandler->pairingResult( @@ -923,25 +1215,80 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } -void GenericSecurityManager::on_slave_security_request( +void GenericSecurityManager::on_signed_write_received( connection_handle_t connection, - AuthenticationMask authentication + sign_count_t sign_counter +) { + MBED_ASSERT(_db); + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + _db->set_entry_peer_sign_counter(cb->db_entry, sign_counter); +} + +void GenericSecurityManager::on_signed_write_verification_failure( + connection_handle_t connection ) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - if (authentication.get_secure_connections() - && _default_authentication.get_secure_connections() - && !cb->secure_connections_paired) { - requestPairing(connection); + const bool signing = cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing(); + + if (signing) { + cb->csrk_failures++; + if (cb->csrk_failures == 3) { + cb->csrk_failures = 0; + if (cb->is_master) { + requestPairing(connection); + } else { + slave_security_request(connection); + } + } + } +} + +void GenericSecurityManager::on_signed_write() { + MBED_ASSERT(_db); + _db->set_local_sign_counter(_db->get_local_sign_counter() + 1); +} + +void GenericSecurityManager::on_slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication +) { + MBED_ASSERT(_db); + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; } - if (authentication.get_mitm() - && !cb->ltk_mitm_protected) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + bool pairing_required = false; + + if (authentication.get_secure_connections() && !flags->secure_connections_paired + && _default_authentication.get_secure_connections()) { + pairing_required = true; + } + + if (authentication.get_mitm() && !flags->ltk_mitm_protected) { + pairing_required = true; cb->mitm_requested = true; + } + + if (pairing_required) { requestPairing(connection); + } else if (!cb->encryption_requested) { + /* this will refresh keys if encryption is already present */ + enable_encryption(connection); } } @@ -965,7 +1312,10 @@ void GenericSecurityManager::on_link_encryption_result( cb->encryption_failed = false; cb->encrypted = true; - } else if (result == link_encryption_t::ENCRYPTED_WITH_MITM) { + } else if ( + result == link_encryption_t::ENCRYPTED_WITH_MITM || + result == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { cb->encryption_requested = false; cb->encryption_failed = false; @@ -1026,74 +1376,110 @@ void GenericSecurityManager::on_confirmation_request(connection_handle_t connect eventHandler->confirmationRequest(connection); } -void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { +void GenericSecurityManager::on_secure_connections_oob_request(connection_handle_t connection) { set_mitm_performed(connection); - eventHandler->legacyPairingOobRequest(connection); + + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (flags->peer_address == _oob_peer_address) { + _pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm); + /* do not re-use peer OOB */ + set_all_zeros(_oob_peer_address); + } else { + _pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE); + } } -void GenericSecurityManager::on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y -) { -#if defined(MBEDTLS_CMAC_C) +void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); - - oob_confirm_t confirm_verify; - - crypto_toolbox_f4( - peer_public_key_x, - peer_public_key_y, - _peer_sc_oob_random, - confirm_verify - ); - - if (cb && (cb->peer_address == _peer_sc_oob_address) - && (confirm_verify == _peer_sc_oob_confirm)) { - _pal.oob_data_verified(connection, _local_sc_oob_random, _peer_sc_oob_random); - } else { - _pal.cancel_pairing(connection, pairing_failure_t::CONFIRM_VALUE_FAILED); + if (!cb) { + return; } -#endif + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (flags->peer_address == _oob_temporary_key_creator_address + || cb->local_address == _oob_temporary_key_creator_address) { + + set_mitm_performed(connection); + _pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key); + + /* do not re-use peer OOB */ + if (flags->peer_address == _oob_temporary_key_creator_address) { + set_all_zeros(_oob_temporary_key_creator_address); + } + + } else if (!cb->legacy_pairing_oob_request_pending) { + + cb->legacy_pairing_oob_request_pending = true; + eventHandler->legacyPairingOobRequest(connection); + + } +} + +void GenericSecurityManager::on_secure_connections_oob_generated( + const oob_lesc_value_t &random, + const oob_confirm_t &confirm +) { + eventHandler->oobGenerated(&_oob_local_address, &random, &confirm); + _oob_local_random = random; } //////////////////////////////////////////////////////////////////////////// // Keys // -void GenericSecurityManager::on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y -) { - _db.set_public_key(public_key_x, public_key_y); - _public_keys_generated = true; -} - void GenericSecurityManager::on_secure_connections_ltk_generated( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - cb->ltk_mitm_protected = cb->mitm_performed; - cb->secure_connections_paired = true; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } - _db.set_entry_peer_ltk(cb->db_entry, ltk); + flags->ltk_mitm_protected = cb->mitm_performed; + flags->secure_connections_paired = true; + + _db->set_entry_peer_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_ltk( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - cb->ltk_mitm_protected = cb->mitm_performed; - _db.set_entry_peer_ltk(cb->db_entry, ltk); + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->ltk_mitm_protected = cb->mitm_performed; + + _db->set_entry_peer_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_ediv_rand( @@ -1101,24 +1487,31 @@ void GenericSecurityManager::on_keys_distributed_ediv_rand( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.set_entry_peer_ediv_rand(cb->db_entry, ediv, rand); + _db->set_entry_peer_ediv_rand(cb->db_entry, ediv, rand); } void GenericSecurityManager::on_keys_distributed_local_ltk( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.set_entry_local_ltk(cb->db_entry, ltk); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + _db->set_entry_local_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_local_ediv_rand( @@ -1126,24 +1519,31 @@ void GenericSecurityManager::on_keys_distributed_local_ediv_rand( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.set_entry_local_ediv_rand(cb->db_entry, ediv, rand); + _db->set_entry_local_ediv_rand(cb->db_entry, ediv, rand); } void GenericSecurityManager::on_keys_distributed_irk( connection_handle_t connection, const irk_t &irk ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.set_entry_peer_irk(cb->db_entry, irk); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + _db->set_entry_peer_irk(cb->db_entry, irk); } void GenericSecurityManager::on_keys_distributed_bdaddr( @@ -1151,12 +1551,13 @@ void GenericSecurityManager::on_keys_distributed_bdaddr( advertising_peer_address_type_t peer_address_type, const address_t &peer_identity_address ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.set_entry_peer_bdaddr( + _db->set_entry_peer_bdaddr( cb->db_entry, (peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS), peer_identity_address @@ -1167,19 +1568,24 @@ void GenericSecurityManager::on_keys_distributed_csrk( connection_handle_t connection, const csrk_t &csrk ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - cb->csrk_mitm_protected = cb->mitm_performed; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } - _db.set_entry_peer_csrk(cb->db_entry, csrk); + flags->csrk_mitm_protected = cb->mitm_performed; + _db->set_entry_peer_csrk(cb->db_entry, csrk); eventHandler->signingKey( connection, &csrk, - cb->csrk_mitm_protected + flags->csrk_mitm_protected ); } @@ -1188,12 +1594,18 @@ void GenericSecurityManager::on_ltk_request( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.get_entry_local_keys( + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + _db->get_entry_local_keys( mbed::callback(this, &GenericSecurityManager::set_ltk_cb), cb->db_entry, ediv, @@ -1204,7 +1616,6 @@ void GenericSecurityManager::on_ltk_request( /* control blocks list management */ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : - pal::SecurityDistributionFlags_t(), connection(0), db_entry(0), local_address(), @@ -1220,16 +1631,19 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : mitm_performed(false), attempt_oob(false), oob_mitm_protection(false), - oob_present(false) { } + oob_present(false), + legacy_pairing_oob_request_pending(false), + csrk_failures(0) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; } - _db.get_entry_local_keys( + _db->get_entry_local_keys( mbed::callback(this, &GenericSecurityManager::set_ltk_cb), cb->db_entry ); @@ -1267,18 +1681,21 @@ GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_bloc GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block( const address_t &peer_address ) { + MBED_ASSERT(_db); for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { - if (!_control_blocks[i].connected) { - continue; - } else if (peer_address == _control_blocks[i].peer_address) { - return &_control_blocks[i]; + ControlBlock_t *cb = &_control_blocks[i]; + if (cb->connected) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (flags && (flags->peer_address == peer_address)) { + return cb; + } } } return NULL; } GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block( - pal::SecurityDb::entry_handle_t db_entry + SecurityDb::entry_handle_t db_entry ) { for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { if (!_control_blocks[i].connected) { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index b74486f1e6..e4eeafba1d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -30,7 +30,6 @@ #include "CordioPalGenericAccessService.h" #include "ble/generic/GenericGap.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/MemorySecurityDb.h" #include "ble/pal/SimpleEventQueue.h" namespace ble { @@ -85,12 +84,12 @@ public: /** * @see BLEInstanceBase::getGap */ - virtual ::Gap& getGap(); + virtual generic::GenericGap& getGap(); /** * @see BLEInstanceBase::getGap */ - virtual const ::Gap& getGap() const; + virtual const generic::GenericGap& getGap() const; /** * @see BLEInstanceBase::getGattServer @@ -105,7 +104,7 @@ public: /** * @see BLEInstanceBase::getGattClient */ - virtual ::GattClient &getGattClient(); + virtual generic::GenericGattClient &getGattClient(); /** * @see BLEInstanceBase::getSecurityManager @@ -154,6 +153,17 @@ private: ::BLE::InstanceID_t instanceID; mutable pal::SimpleEventQueue _event_queue; + + class SigningEventMonitorProxy : public pal::SigningEventMonitor { + public: + SigningEventMonitorProxy(BLE &ble) : _ble(ble) { } + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *handler) { + _ble.getGattClient().set_signing_event_handler(handler); + _ble.getGattServer().set_signing_event_handler(handler); + } + private: + BLE &_ble; + }; }; } // namespace cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index 26dc08a78e..f882fa98ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -20,22 +20,42 @@ #include #include "ble/blecommon.h" #include "ble/GattServer.h" +#include "ble/pal/SigningEventMonitor.h" #include "ble/Gap.h" #include "wsf_types.h" #include "att_api.h" +/*! Maximum count of characteristics that can be stored for authorisation purposes */ +#define MAX_CHARACTERISTIC_AUTHORIZATION_CNT 20 + /*! client characteristic configuration descriptors settings */ -#define MAX_CCC_CNT 20 +#define MAX_CCCD_CNT 20 namespace ble { + +// fwd declaration of CordioAttClient and BLE +namespace pal { namespace vendor { namespace cordio { +class CordioAttClient; +} +} +} + +namespace vendor { +namespace cordio { + +class BLE; /** * Cordio implementation of ::GattServer */ -class GattServer : public ::GattServer +class GattServer : public ::GattServer, + public pal::SigningEventMonitor { + friend ble::vendor::cordio::BLE; + friend ble::pal::vendor::cordio::CordioAttClient; + public: /** * Return the singleton of the Cordio implementation of ::GattServer. @@ -147,35 +167,84 @@ public: */ virtual ble_error_t reset(void); + /** + * @see pal::SigningEventMonitor::set_signing_event_handler + */ + virtual void set_signing_event_handler( + pal::SigningEventMonitor::EventHandler *signing_event_handler + ) { + _signing_event_handler = signing_event_handler; + } + private: - static void cccCback(attsCccEvt_t *pEvt); - static void attCback(attEvt_t *pEvt); - static uint8_t attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); - static uint8_t attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + static uint16_t compute_attributes_count(GattService& service); + + void insert_service_attribute( + GattService& service, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_characteristic( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + bool is_characteristic_valid(GattCharacteristic *characteristic); + + void insert_characteristic_declaration_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_characteristic_value_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_descriptor( + GattCharacteristic *characteristic, + GattAttribute* descriptor, + attsAttr_t *&attribute_it, + bool& cccd_created + ); + + ble_error_t insert_cccd( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + static void cccd_cb(attsCccEvt_t *pEvt); + static void att_cb(const attEvt_t *pEvt); + static uint8_t atts_read_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); + static uint8_t atts_write_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + static uint8_t atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle); void add_generic_access_service(); void add_generic_attribute_service(); void* alloc_block(size_t block_size); + GattCharacteristic* get_auth_char(uint16_t value_handle); + bool get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const; + bool has_cccd(GattAttribute::Handle_t char_handle) const; + bool is_update_authorized(Gap::Handle_t connection, GattAttribute::Handle_t value_handle); struct alloc_block_t { alloc_block_t* next; uint8_t data[1]; }; - struct internal_char_t { - uint16_t descLen; - }; - struct internal_service_t { - uint16_t uuidLen; - internal_char_t *chars; - attsGroup_t *attGroup; + attsGroup_t attGroup; internal_service_t *next; }; - attsCccSet_t cccSet[MAX_CCC_CNT]; - uint16_t cccValues[MAX_CCC_CNT]; - uint16_t cccHandles[MAX_CCC_CNT]; - uint8_t cccCnt; + pal::SigningEventMonitor::EventHandler *_signing_event_handler; + + attsCccSet_t cccds[MAX_CCCD_CNT]; + uint16_t cccd_values[MAX_CCCD_CNT]; + uint16_t cccd_handles[MAX_CCCD_CNT]; + uint8_t cccd_cnt; + + GattCharacteristic *_auth_char[MAX_CHARACTERISTIC_AUTHORIZATION_CNT]; + uint8_t _auth_char_count; struct { attsGroup_t service; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 401cffa8b8..cff00fceea 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -17,6 +17,7 @@ #ifndef CORDIO_PAL_ATT_CLIENT_ #define CORDIO_PAL_ATT_CLIENT_ +#include "CordioGattServer.h" #include "ble/pal/AttClient.h" #include "ble/pal/SimpleAttServerMessage.h" #include "att_api.h" @@ -30,7 +31,8 @@ namespace cordio { class CordioAttClient : public ::ble::pal::AttClient { public: - CordioAttClient() : ::ble::pal::AttClient() { } + CordioAttClient() : ::ble::pal::AttClient(), _local_sign_counter(0) { } + virtual ~CordioAttClient() { } /** @@ -216,13 +218,26 @@ public: AttcSignedWriteCmd( connection_handle, attribute_handle, - /* sign counter from flash or AttsGetSignCounter() ? */ 0, + _local_sign_counter, value.size(), const_cast(value.data()) ); + _local_sign_counter++; return BLE_ERROR_NONE; } + /** + * Initialises the counter used to sign messages. Counter will be incremented every + * time a message is signed. + * + * @param sign_counter initialise the signing counter to this value + */ + virtual void set_sign_counter( + sign_count_t sign_counter + ) { + _local_sign_counter = sign_counter; + } + /** * @see ble::pal::AttClient::prepare_write_request */ @@ -335,6 +350,9 @@ public: return; } } + + // pass events not handled to the server side + ble::vendor::cordio::GattServer::getInstance().att_cb(event); } private: @@ -612,6 +630,8 @@ private: ); } }; +private: + sign_count_t _local_sign_counter; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 69ca5e9848..52fae1eed3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -308,6 +308,18 @@ public: 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 ble_error_t set_address_resolution( + bool enable + ) { + DmPrivSetAddrResEnable(enable); + return BLE_ERROR_NONE; + } + // singleton of the ARM Cordio client static Gap& get_gap() { static Gap _gap; @@ -381,11 +393,13 @@ private: // note the usage of the stack handle, not the HCI handle conn_evt->hdr.param, (connection_role_t::type) conn_evt->role, - (advertising_peer_address_type_t::type) conn_evt->addrType, + (peer_address_type_t::type) conn_evt->addrType, conn_evt->peerAddr, conn_evt->connInterval, conn_evt->connLatency, - conn_evt->supTimeout + conn_evt->supTimeout, + conn_evt->localRpa, + conn_evt->peerRpa ); } }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 10b0a0922b..1092275b73 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -20,6 +20,9 @@ #include "ble/pal/PalSecurityManager.h" #include "wsf_types.h" #include "wsf_os.h" +#include "sec_api.h" +#include "smp_defs.h" +#include "cfg_stack.h" namespace ble { namespace pal { @@ -83,16 +86,42 @@ public: virtual ble_error_t clear_resolving_list(); //////////////////////////////////////////////////////////////////////////// - // Feature support + // Pairing // /** - * @see ::ble::pal::SecurityManager::set_secure_connections_support + * @see ::ble::pal::SecurityManager::send_pairing_request */ - virtual ble_error_t set_secure_connections_support( - bool enabled, bool secure_connections_only = false + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist ); + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + /** * @see ::ble::pal::SecurityManager::get_secure_connections_support */ @@ -100,6 +129,11 @@ public: bool &enabled ); + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + //////////////////////////////////////////////////////////////////////////// // Security settings // @@ -118,6 +152,17 @@ public: connection_handle_t, uint16_t &timeout_in_10ms ); + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ virtual ble_error_t slave_security_request( connection_handle_t connection, AuthenticationMask authentication @@ -193,68 +238,27 @@ public: /** * @see ::ble::pal::SecurityManager::set_csrk */ - virtual ble_error_t set_csrk(const csrk_t &csrk); - - /** - * @see ::ble::pal::SecurityManager::generate_public_key - */ - virtual ble_error_t generate_public_key(); - - //////////////////////////////////////////////////////////////////////////// - // Global parameters - // - - /** - * @see ::ble::pal::SecurityManager::set_display_passkey - */ - virtual ble_error_t set_display_passkey(passkey_num_t passkey); - - /** - * @see ::ble::pal::SecurityManager::set_io_capability - */ - virtual ble_error_t set_io_capability(io_capability_t io_capability); - - /** - * @see ::ble::pal::SecurityManager::set_encryption_key_requirements - */ - virtual ble_error_t set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size + virtual ble_error_t set_csrk( + const csrk_t &csrk, + sign_count_t sign_counter ); + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ); + + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); + //////////////////////////////////////////////////////////////////////////// // Authentication // - /** - * @see ::ble::pal::SecurityManager::send_pairing_request - */ - virtual ble_error_t send_pairing_request( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::send_pairing_response - */ - virtual ble_error_t send_pairing_response( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::cancel_pairing - */ - virtual ble_error_t cancel_pairing( - connection_handle_t connection, pairing_failure_t reason - ); - /** * @see ::ble::pal::SecurityManager::get_random_data */ @@ -264,6 +268,11 @@ public: // MITM // + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + /** * @see ::ble::pal::SecurityManager::passkey_request_reply */ @@ -273,9 +282,19 @@ public: ); /** - * @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + + /** + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply + */ + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ); @@ -295,13 +314,9 @@ public: ); /** - * @see ::ble::pal::SecurityManager::oob_data_verified + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random - ); + virtual ble_error_t generate_secure_connections_oob(); // singleton of the ARM Cordio Security Manager static CordioSecurityManager &get_security_manager(); @@ -310,8 +325,49 @@ public: static bool sm_handler(const wsfMsgHdr_t* msg); private: + struct PrivacyControlBlock; + struct PrivacyClearResListControlBlock; + struct PrivacyAddDevToResListControlBlock; + struct PrivacyRemoveDevFromResListControlBlock; + + // Queue control block to add device to resolving list + void queue_add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ); + + // Queue control block to remove device from resolving list + void queue_remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ); + + // Queue control block to clear resolving list + void queue_clear_resolving_list(); + + // Clear all control blocks + void clear_privacy_control_blocks(); + + // Queue a control block + void queue_privacy_control_block(PrivacyControlBlock* block); + + // Try to dequeue and process the next control block + // cb_completed is set when the previous block has completed + void process_privacy_control_blocks(bool cb_completed); + + void cleanup_peer_csrks(); + bool _use_default_passkey; passkey_num_t _default_passkey; + bool _lesc_keys_generated; + uint8_t _public_key_x[SEC_ECC_KEY_LEN]; + + PrivacyControlBlock* _pending_privacy_control_blocks; + bool _processing_privacy_control_block; + irk_t _irk; + csrk_t _csrk; + csrk_t* _peer_csrks[DM_CONN_MAX]; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 93a5327012..085a7cebb6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -164,31 +164,25 @@ const char* BLE::getVersion() return version; } -::Gap& BLE::getGap() +generic::GenericGap& BLE::getGap() { - typedef ::Gap& return_type; - const BLE* self = this; - return const_cast(self->getGap()); -} - -const ::Gap& BLE::getGap() const -{ - return getGenericGap(); -}; - -const generic::GenericGap& BLE::getGenericGap() const -{ - static pal::vendor::cordio::Gap& cordio_pal_gap = - pal::vendor::cordio::Gap::get_gap(); static pal::vendor::cordio::GenericAccessService cordio_gap_service; static ble::generic::GenericGap gap( _event_queue, - cordio_pal_gap, - cordio_gap_service + pal::vendor::cordio::Gap::get_gap(), + cordio_gap_service, + pal::vendor::cordio::CordioSecurityManager::get_security_manager() ); + return gap; } +const generic::GenericGap& BLE::getGap() const +{ + BLE &self = const_cast(*this); + return const_cast(self.getGap()); +}; + GattServer& BLE::getGattServer() { return cordio::GattServer::getInstance(); @@ -199,7 +193,7 @@ const GattServer& BLE::getGattServer() const return cordio::GattServer::getInstance(); } -::GattClient& BLE::getGattClient() +generic::GenericGattClient& BLE::getGattClient() { static pal::AttClientToGattClientAdapter pal_client( pal::vendor::cordio::CordioAttClient::get_client() @@ -211,21 +205,20 @@ const GattServer& BLE::getGattServer() const SecurityManager& BLE::getSecurityManager() { - const BLE* self = this; - return const_cast(self->getSecurityManager()); + static SigningEventMonitorProxy signing_event_monitor(*this); + static generic::GenericSecurityManager m_instance( + pal::vendor::cordio::CordioSecurityManager::get_security_manager(), + getGap(), + signing_event_monitor + ); + + return m_instance; } const SecurityManager& BLE::getSecurityManager() const { - static pal::MemorySecurityDb m_db; - pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); - static generic::GenericSecurityManager m_instance( - m_pal, - m_db, - const_cast(getGenericGap()) - ); - - return m_instance; + const BLE &self = const_cast(*this); + return const_cast(self.getSecurityManager()); } void BLE::waitForEvent() @@ -361,7 +354,10 @@ void BLE::stack_setup() AttHandlerInit(handlerId); AttsInit(); AttsIndInit(); + AttsSignInit(); + AttsAuthorRegister(GattServer::atts_auth_cb); AttcInit(); + AttcSignInit(); handlerId = WsfOsSetNextHandler(SmpHandler); SmpHandlerInit(handlerId); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 79173e39c9..41568ab5f3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -15,18 +15,47 @@ */ #include +#include "CordioBLE.h" #include "CordioGattServer.h" #include "mbed.h" #include "wsf_types.h" #include "att_api.h" -static UUID cccUUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); -static const uint16_t cccSize = sizeof(uint16_t); - namespace ble { namespace vendor { namespace cordio { +namespace { + +static UUID CCCD_UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); +static const uint16_t CCCD_SIZE = sizeof(uint16_t); + +static const unsigned int READ_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; +static const unsigned int WRITE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE; +static const unsigned int WRITE_WITHOUT_RESPONSE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE; +static const unsigned int SIGNED_WRITE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; +static const unsigned int NOTIFY_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY; +static const unsigned int INDICATE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE; + +static const uint8_t WRITABLE_PROPERTIES = + WRITE_PROPERTY | + WRITE_WITHOUT_RESPONSE_PROPERTY | + SIGNED_WRITE_PROPERTY; + +static const uint8_t UPDATE_PROPERTIES = + NOTIFY_PROPERTY | + INDICATE_PROPERTY; + +static const uint16_t CONNECTION_ID_LIMIT = 0x100; + +} // end of anonymous namespace + GattServer &GattServer::getInstance() { static GattServer m_instance; @@ -35,384 +64,651 @@ GattServer &GattServer::getInstance() void GattServer::initialize() { + AttsAuthorRegister(atts_auth_cb); add_generic_access_service(); add_generic_attribute_service(); } ble_error_t GattServer::addService(GattService &service) { - ++currentHandle; - uint16_t startHandle = currentHandle; - - internal_service_t *internal_service = new internal_service_t; - - if (registered_service) { - internal_service->next = registered_service; - } else { - internal_service->next = NULL; - } - - registered_service = internal_service; - - // Create cordio attribute group - internal_service->attGroup = new attsGroup_t; + // create and fill the service structure + internal_service_t *att_service = new internal_service_t; + att_service->attGroup.pNext = NULL; + att_service->attGroup.readCback = atts_read_cb; + att_service->attGroup.writeCback = atts_write_cb; // Determine the attribute list length - unsigned int attListLen = 1; - for (int i = 0; i < service.getCharacteristicCount(); i++) { - attListLen += 2; - GattCharacteristic *p_char = service.getCharacteristic(i); - - attListLen += p_char->getDescriptorCount(); - if (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) { - // add a CCCD - attListLen++; - } - } + uint16_t attributes_count = compute_attributes_count(service); // Create cordio attribute list - internal_service->attGroup->pAttr = (attsAttr_t*)alloc_block(attListLen * sizeof(attsAttr_t)); - if (internal_service->attGroup->pAttr == NULL) { + att_service->attGroup.pAttr = + (attsAttr_t*) alloc_block(attributes_count * sizeof(attsAttr_t)); + if (att_service->attGroup.pAttr == NULL) { + delete att_service; return BLE_ERROR_BUFFER_OVERFLOW; } - // Create characteristics - internal_service->chars = new internal_char_t [service.getCharacteristicCount()]; - - attsAttr_t *currAtt = internal_service->attGroup->pAttr; + // insert every element in the iterator + attsAttr_t *attribute_it = att_service->attGroup.pAttr; /* Service */ - currAtt->pUuid = attPrimSvcUuid; - if (service.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - internal_service->uuidLen = UUID::LENGTH_OF_LONG_UUID; - } else { - internal_service->uuidLen = sizeof(UUID::ShortUUIDBytes_t); - } - currAtt->pValue = (uint8_t*)alloc_block(internal_service->uuidLen); - memcpy(currAtt->pValue, service.getUUID().getBaseUUID(), internal_service->uuidLen); - currAtt->maxLen = internal_service->uuidLen; - currAtt->pLen = &internal_service->uuidLen; - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ; - - currAtt++; + insert_service_attribute(service, attribute_it); + att_service->attGroup.startHandle = currentHandle; + service.setHandle(currentHandle); /* Add characteristics to the service */ for (int i = 0; i < service.getCharacteristicCount(); i++) { + ble_error_t err = insert_characteristic( + service.getCharacteristic(i), + attribute_it + ); + if (err) { + // FIXME: proper cleanup of data structure: + // - att_service->attGroup.pAttr + // - blocks allocated for characteristics value + // NOTE: those are rightfully released when reset() is called. + delete att_service; + return err; + } + } + att_service->attGroup.endHandle = currentHandle; + + // add the service to the list of registered services + if (registered_service) { + att_service->next = registered_service; + } else { + att_service->next = NULL; + } + + registered_service = att_service; + + // register services and update cccds + AttsAddGroup(&att_service->attGroup); + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); + return BLE_ERROR_NONE; +} + +uint16_t GattServer::compute_attributes_count(GattService& service) +{ + // start at 1, one attribute is required for the service itself + uint16_t attributes_count = 1; + for (int i = 0; i < service.getCharacteristicCount(); i++) { + attributes_count += 2; GattCharacteristic *p_char = service.getCharacteristic(i); + attributes_count += p_char->getDescriptorCount(); + if (p_char->getProperties() & UPDATE_PROPERTIES) { + // add a CCCD + ++attributes_count; - /* Skip any incompletely defined, read-only characteristics. */ - if ((p_char->getValueAttribute().getValuePtr() == NULL) && - (p_char->getValueAttribute().getLength() == 0) && - (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { - continue; - } - - // Create Characteristic Attribute - currentHandle += 2; - currAtt->pUuid = attChUuid; - - p_char->getValueAttribute().setHandle(currentHandle); - internal_service->chars[i].descLen = 1 + sizeof(currentHandle) + p_char->getValueAttribute().getUUID().getLen(); - currAtt->pValue = (uint8_t*) alloc_block(internal_service->chars[i].descLen); - uint8_t *pValue = currAtt->pValue; - *pValue++ = p_char->getProperties(); - memcpy(pValue, ¤tHandle, sizeof(currentHandle)); - pValue += sizeof(currentHandle); - memcpy(pValue, p_char->getValueAttribute().getUUID().getBaseUUID(), p_char->getValueAttribute().getUUID().getLen()); - - currAtt->pLen = &internal_service->chars[i].descLen; - currAtt->maxLen = internal_service->chars[i].descLen; - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ; - currAtt++; - - // Create Value Attribute - currAtt->pUuid = p_char->getValueAttribute().getUUID().getBaseUUID(); - currAtt->maxLen = p_char->getValueAttribute().getMaxLength(); - currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); - *currAtt->pLen = p_char->getValueAttribute().getLength(); - currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); - memcpy(currAtt->pValue, p_char->getValueAttribute().getValuePtr(), *currAtt->pLen); - memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); - - currAtt->settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK; - if (p_char->getValueAttribute().getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - currAtt->settings |= ATTS_SET_UUID_128; - } - if (p_char->getValueAttribute().hasVariableLength()) { - currAtt->settings |= ATTS_SET_VARIABLE_LEN; - } - - currAtt->permissions = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { currAtt->permissions |= ATTS_PERMIT_READ; } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) { currAtt->permissions |= ATTS_PERMIT_WRITE; } - currAtt++; - - bool cccCreated = false; - - for (int i = 0; i < p_char->getDescriptorCount(); i++) { - GattAttribute *p_att = p_char->getDescriptor(i); - - currentHandle++; - - p_att->setHandle(currentHandle); - - currAtt->pUuid = p_att->getUUID().getBaseUUID(); - currAtt->maxLen = p_att->getMaxLength(); - currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); - *currAtt->pLen = p_att->getLength(); - currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); - memcpy(currAtt->pValue, p_att->getValuePtr(), *currAtt->pLen); - memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); - - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ | ATTS_PERMIT_WRITE; - if (p_att->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - currAtt->settings |= ATTS_SET_UUID_128; - } - if (p_att->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { - cccCreated = true; - currAtt->settings |= ATTS_SET_CCC; - currAtt->permissions |= ATTS_PERMIT_READ; - currAtt->permissions |= ATTS_PERMIT_WRITE; - - if (cccCnt < MAX_CCC_CNT) { - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; - } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; - } - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); - cccCnt++; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; + // verify that it hasn't been counted twice + for (size_t j = 0; j < p_char->getDescriptorCount(); ++j) { + if (p_char->getDescriptor(j)->getUUID() == + UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) + ) { + --attributes_count; + break; } } - if (p_att->hasVariableLength()) { - currAtt->settings |= ATTS_SET_VARIABLE_LEN; - } - currAtt++; - } - - if (!cccCreated && (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) { - /* There was not a CCCD included in the descriptors, but this - * characteristic is notifiable and/or indicatable. A CCCD is - * required so create one now. - */ - if (cccCnt >= MAX_CCC_CNT) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - currentHandle++; - - currAtt->pUuid = cccUUID.getBaseUUID(); - currAtt->pValue = (uint8_t*)&cccValues[cccCnt]; - currAtt->pLen = (uint16_t*)&cccSize; - currAtt->maxLen = sizeof(uint16_t); - currAtt->settings = ATTS_SET_CCC; - currAtt->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); - - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; - } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; - } - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); - - cccCnt++; - currAtt++; } } - internal_service->attGroup->pNext = NULL; - internal_service->attGroup->readCback = attsReadCback; - internal_service->attGroup->writeCback = attsWriteCback; - internal_service->attGroup->startHandle = startHandle; - internal_service->attGroup->endHandle = currentHandle; - AttsAddGroup(internal_service->attGroup); - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + return attributes_count; +} - service.setHandle(startHandle); +void GattServer::insert_service_attribute( + GattService& service, + attsAttr_t *&attribute_it +) { + ++currentHandle; + const UUID& service_uuid = service.getUUID(); + + attribute_it->pUuid = attPrimSvcUuid; + if (service_uuid.shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->maxLen = UUID::LENGTH_OF_LONG_UUID; + } else { + attribute_it->maxLen = sizeof(UUID::ShortUUIDBytes_t); + } + attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen); + memcpy(attribute_it->pValue, service_uuid.getBaseUUID(), attribute_it->maxLen); + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->settings = 0; + attribute_it->permissions = ATTS_PERMIT_READ; + + ++attribute_it; +} + +ble_error_t GattServer::insert_characteristic( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + bool valid = is_characteristic_valid(characteristic); + if (!valid) { + return BLE_ERROR_INVALID_PARAM; + } + + uint8_t properties = characteristic->getProperties(); + + // Create Characteristic Declaration Attribute + insert_characteristic_declaration_attribute(characteristic, attribute_it); + insert_characteristic_value_attribute(characteristic, attribute_it); + + // insert descriptors + bool cccd_created = false; + for (size_t i = 0; i < characteristic->getDescriptorCount(); i++) { + insert_descriptor( + characteristic, + characteristic->getDescriptor(i), + attribute_it, + cccd_created + ); + } + + // insert implicit CCCD + if ((properties & UPDATE_PROPERTIES) && (cccd_created == false)) { + insert_cccd(characteristic, attribute_it); + } return BLE_ERROR_NONE; } -ble_error_t GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t * lengthP) -{ - uint16_t attribute_length = 0; - uint8_t* attribute_value = NULL; +bool GattServer::is_characteristic_valid(GattCharacteristic *characteristic) { + uint8_t properties = characteristic->getProperties(); - if (AttsGetAttr(attributeHandle, &attribute_length, &attribute_value) != ATT_SUCCESS) { + // nothing to read while the characteristic is flagged as readable + if ((characteristic->getValueAttribute().getValuePtr() == NULL) && + (characteristic->getValueAttribute().getMaxLength() == 0) && + (properties == READ_PROPERTY) && + (characteristic->isReadAuthorizationEnabled() == false) + ) { + return false; + } + + // nothing to write while the characteristic is flagged as writable + if ((characteristic->getValueAttribute().getValuePtr() == NULL) && + (characteristic->getValueAttribute().getMaxLength() == 0) && + (properties & WRITABLE_PROPERTIES) && + (characteristic->isWriteAuthorizationEnabled() == false) + ) { + return false; + } + + // check for invalid permissions + if ((properties == SIGNED_WRITE_PROPERTY) && + (characteristic->getWriteSecurityRequirement() == att_security_requirement_t::NONE || + characteristic->getWriteSecurityRequirement() == att_security_requirement_t::SC_AUTHENTICATED) + ) { + return false; + } + + return true; +} + +void GattServer::insert_characteristic_declaration_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + const UUID& value_uuid = characteristic->getValueAttribute().getUUID(); + + // move the current handle to point to the value handle + currentHandle += 2; + characteristic->getValueAttribute().setHandle(currentHandle); + + // fill the cordio attribute + attribute_it->pUuid = attChUuid; + attribute_it->maxLen = 1 + sizeof(currentHandle) + value_uuid.getLen(); + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen); + attribute_it->settings = 0; + attribute_it->permissions = ATTS_PERMIT_READ; + + // set the attribute value + uint8_t *value_it = attribute_it->pValue; + *value_it++ = characteristic->getProperties(); + memcpy(value_it, ¤tHandle, sizeof(currentHandle)); + value_it += sizeof(currentHandle); + memcpy(value_it, value_uuid.getBaseUUID(), value_uuid.getLen()); + + ++attribute_it; +} + +ble_error_t GattServer::insert_characteristic_value_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + GattAttribute &value_attribute = characteristic->getValueAttribute(); + uint8_t properties = characteristic->getProperties(); + + // note: currentHandle has been already moved to the correct value + + // Create Value Attribute + attribute_it->pUuid = value_attribute.getUUID().getBaseUUID(); + attribute_it->maxLen = characteristic->getValueAttribute().getMaxLength(); + attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t)); + *attribute_it->pLen = value_attribute.getLength(); + attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1); + memcpy(attribute_it->pValue, value_attribute.getValuePtr(), *attribute_it->pLen); + memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen); + + // Set value attribute settings + if (properties & READ_PROPERTY) { + attribute_it->settings = ATTS_SET_READ_CBACK; + } + if (properties & WRITABLE_PROPERTIES) { + attribute_it->settings = ATTS_SET_WRITE_CBACK; + } + if (value_attribute.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->settings |= ATTS_SET_UUID_128; + } + if (value_attribute.hasVariableLength()) { + attribute_it->settings |= ATTS_SET_VARIABLE_LEN; + } + if (properties & SIGNED_WRITE_PROPERTY) { + attribute_it->settings |= ATTS_SET_ALLOW_SIGNED; + } + + // setup permissions + attribute_it->permissions = 0; + + // configure read permission + if (properties & READ_PROPERTY) { + attribute_it->permissions |= ATTS_PERMIT_READ; + switch (characteristic->getReadSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_READ_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH | + ATTS_PERMIT_READ_AUTHORIZ; + break; + } + } + + // configure write permission + if (properties & WRITABLE_PROPERTIES) { + attribute_it->permissions |= ATTS_PERMIT_WRITE; + switch (characteristic->getWriteSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH | + ATTS_PERMIT_WRITE_AUTHORIZ; + break; + } + } + + // Register characteristic in authorisation list + // Note: ATTS_PERMIT_*_AUTHORIZ is uniquely used to check if security + // requirements are met according to the security requirements set in the + // characteristic. + // User defined security authorisation does not impact this flag + if ((attribute_it->permissions & (ATTS_PERMIT_READ_AUTHORIZ | ATTS_PERMIT_WRITE_AUTHORIZ)) || + (attribute_it->permissions & UPDATE_PROPERTIES) || + characteristic->isReadAuthorizationEnabled() || + characteristic->isWriteAuthorizationEnabled() + ) { + if ( _auth_char_count >= MAX_CHARACTERISTIC_AUTHORIZATION_CNT) { + return BLE_ERROR_NO_MEM; + } + _auth_char[_auth_char_count] = characteristic; + ++_auth_char_count; + } + + ++attribute_it; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::insert_descriptor( + GattCharacteristic *characteristic, + GattAttribute* descriptor, + attsAttr_t *&attribute_it, + bool& cccd_created +) { + uint8_t properties = characteristic->getProperties(); + + currentHandle++; + + descriptor->setHandle(currentHandle); + + attribute_it->pUuid = descriptor->getUUID().getBaseUUID(); + attribute_it->maxLen = descriptor->getMaxLength(); + attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t)); + *attribute_it->pLen = descriptor->getLength(); + attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1); + memcpy(attribute_it->pValue, descriptor->getValuePtr(), *attribute_it->pLen); + memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen); + + attribute_it->settings = 0; + + if (descriptor->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->settings |= ATTS_SET_UUID_128; + } + + // handle the special case of a CCCD + if (descriptor->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { + if (cccd_cnt >= MAX_CCCD_CNT) { + return BLE_ERROR_NO_MEM; + } + + if (descriptor->isReadAllowed() == false || + descriptor->getReadSecurityRequirement() != att_security_requirement_t::NONE + ) { + return BLE_ERROR_INVALID_PARAM; + } + + cccd_created = true; + attribute_it->settings |= ATTS_SET_CCC; + + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = 0; + if (properties & NOTIFY_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (properties & INDICATE_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle(); + cccd_cnt++; + } + + if (descriptor->hasVariableLength()) { + attribute_it->settings |= ATTS_SET_VARIABLE_LEN; + } + + // setup permissions + attribute_it->permissions = 0; + + // configure read permission + if (descriptor->isReadAllowed()) { + attribute_it->permissions |= ATTS_PERMIT_READ; + switch (descriptor->getReadSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_READ_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH | + ATTS_PERMIT_READ_AUTHORIZ; + break; + } + } + + // configure write permission + if (descriptor->isReadAllowed()) { + attribute_it->permissions |= ATTS_PERMIT_WRITE; + switch (descriptor->getWriteSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH | + ATTS_PERMIT_WRITE_AUTHORIZ; + break; + } + } + + attribute_it++; + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::insert_cccd( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + if (cccd_cnt >= MAX_CCCD_CNT) { + return BLE_ERROR_NO_MEM; + } + + uint8_t properties = characteristic->getProperties(); + + currentHandle++; + + attribute_it->pUuid = CCCD_UUID.getBaseUUID(); + attribute_it->pValue = (uint8_t*) &cccd_values[cccd_cnt]; + attribute_it->maxLen = CCCD_SIZE; + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->settings = ATTS_SET_CCC; + attribute_it->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = 0; + if (properties & NOTIFY_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (properties & INDICATE_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccds[cccd_cnt].secLevel = characteristic->getUpdateSecurityRequirement().value(); + cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle(); + + cccd_cnt++; + attribute_it++; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read( + GattAttribute::Handle_t att_handle, + uint8_t buffer[], + uint16_t * buffer_length +) { + uint16_t att_length = 0; + uint8_t* att_value = NULL; + + if (AttsGetAttr(att_handle, &att_length, &att_value) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } if (buffer) { - memcpy(buffer, attribute_value, std::min(*lengthP, attribute_length)); + memcpy(buffer, att_value, std::min(*buffer_length, att_length)); } - *lengthP = attribute_length; + *buffer_length = att_length; return BLE_ERROR_NONE; } -ble_error_t GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) -{ +ble_error_t GattServer::read( + Gap::Handle_t connection, + GattAttribute::Handle_t att_handle, + uint8_t buffer[], + uint16_t *buffer_length +) { // Check to see if this is a CCCD - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - if (connectionHandle == DM_CONN_ID_NONE) { // CCCDs are always 16 bits - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - *((uint16_t*)buffer) = AttsCccGet(connectionHandle, idx); - *lengthP = 2; // CCCDs are always 16 bits - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if (connection == DM_CONN_ID_NONE) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; } + uint16_t cccd_value = AttsCccGet(connection, cccd_index); + uint16_t cccd_length = sizeof(cccd_value); + + if (buffer) { + memcpy(buffer, &cccd_value, std::min(*buffer_length, cccd_length)); + } + + *buffer_length = cccd_length; + return BLE_ERROR_NONE; } // This is not a CCCD. Use the non-connection specific update method. - return read(attributeHandle, buffer, lengthP); + return read(att_handle, buffer, buffer_length); } -ble_error_t GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ +ble_error_t GattServer::write( + GattAttribute::Handle_t att_handle, + const uint8_t buffer[], + uint16_t len, + bool local_only +) { // Check to see if this is a CCCD, if it is the case update the value for all // connections - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { - if (DmConnInUse(conn_id) == true) { - ++conn_found; - } else { - continue; - } - - AttsCccSet(conn_id, idx, *((uint16_t*)buffer)); - } - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if (len != sizeof(uint16_t)) { + return BLE_ERROR_INVALID_PARAM; } + + uint16_t cccd_value; + memcpy(&cccd_value, buffer, sizeof(cccd_value)); + + uint16_t conn_id = 0; + uint16_t conn_found = 0; + while ((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { + if (DmConnInUse(conn_id) == true) { + ++conn_found; + AttsCccSet(conn_id, cccd_index, cccd_value); + } + ++conn_id; + } + + return BLE_ERROR_NONE; } // write the value to the attribute handle - if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } // return if the update does not have to be propagated to peers - if (localOnly) { + if (local_only || !has_cccd(att_handle)) { return BLE_ERROR_NONE; } - // Check to see if this characteristic has a CCCD attribute - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccHandles[idx]) { - break; - } - } - - // exit if the characteristic has no CCCD attribute - if (idx >= cccCnt) { - return BLE_ERROR_NONE; - } - - // This characteristic has a CCCD attribute. Handle notifications and indications. - // for all connections - - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { + // This characteristic has a CCCD attribute. Handle notifications and + // indications for all active connections if the authentication is + // successful + uint16_t conn_id = 0; + uint16_t conn_found = 0; + while((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { if (DmConnInUse(conn_id) == true) { ++conn_found; - } else { - uint16_t cccEnabled = AttsCccEnabled(conn_id, idx); - if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { - AttsHandleValueNtf(conn_id, attributeHandle, len, (uint8_t*)buffer); - } - if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { - AttsHandleValueInd(conn_id, attributeHandle, len, (uint8_t*)buffer); + if (is_update_authorized(conn_id, att_handle)) { + uint16_t cccd_config = AttsCccEnabled(conn_id, cccd_index); + if (cccd_config & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(conn_id, att_handle, len, (uint8_t*)buffer); + } + if (cccd_config & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(conn_id, att_handle, len, (uint8_t*)buffer); + } } } - - AttsCccSet(conn_id, idx, *((uint16_t*)buffer)); + ++conn_id; } return BLE_ERROR_NONE; } -ble_error_t GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ +ble_error_t GattServer::write( + Gap::Handle_t connection, + GattAttribute::Handle_t att_handle, + const uint8_t buffer[], + uint16_t len, + bool local_only +) { // Check to see if this is a CCCD - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - if ((connectionHandle == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - AttsCccSet(connectionHandle, idx, *((uint16_t*)buffer)); - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if ((connection == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; } + + uint16_t cccd_value; + memcpy(&cccd_value, buffer, sizeof(cccd_value)); + AttsCccSet(connection, cccd_index, cccd_value); + return BLE_ERROR_NONE; } // write the value to the attribute handle - if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } // return if the update does not have to be propagated to peers - if (localOnly) { - return BLE_ERROR_NONE; - } - - // Check to see if this characteristic has a CCCD attribute - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccHandles[idx]) { - break; - } - } - - // exit if the characteristic has no CCCD attribute - if (idx >= cccCnt) { + if (local_only || !has_cccd(att_handle)) { return BLE_ERROR_NONE; } // This characteristic has a CCCD attribute. Handle notifications and indications. - uint16_t cccEnabled = AttsCccEnabled(connectionHandle, idx); - if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { - AttsHandleValueNtf(connectionHandle, attributeHandle, len, (uint8_t*)buffer); - } - if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { - AttsHandleValueInd(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + if (is_update_authorized(connection, att_handle)) { + uint16_t cccEnabled = AttsCccEnabled(connection, cccd_index); + if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(connection, att_handle, len, (uint8_t*)buffer); + } + if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(connection, att_handle, len, (uint8_t*)buffer); + } } return BLE_ERROR_NONE; } -ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) -{ - for (size_t idx = 0; idx < cccCnt; idx++) { - if (characteristic.getValueHandle() == cccHandles[idx]) { - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { +ble_error_t GattServer::areUpdatesEnabled( + const GattCharacteristic &characteristic, + bool *enabled +) { + for (size_t idx = 0; idx < cccd_cnt; idx++) { + if (characteristic.getValueHandle() == cccd_handles[idx]) { + uint16_t conn_id = 0; + uint16_t conn_found = 0; + + while ((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { if (DmConnInUse(conn_id) == true) { ++conn_found; - } else { - continue; - } + uint16_t cccd_value = AttsCccGet(conn_id, idx); + if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + *enabled = true; + return BLE_ERROR_NONE; + } - uint16_t cccValue = AttsCccGet(conn_id, idx); - if ((cccValue & ATT_CLIENT_CFG_NOTIFY) || (cccValue & ATT_CLIENT_CFG_INDICATE)) { - *enabledP = true; - return BLE_ERROR_NONE; } + ++conn_id; } - *enabledP = false; + *enabled = false; return BLE_ERROR_NONE; } } @@ -420,23 +716,26 @@ ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characterist return BLE_ERROR_PARAM_OUT_OF_RANGE; } -ble_error_t GattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) -{ - if (connectionHandle != DM_CONN_ID_NONE) { - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (characteristic.getValueHandle() == cccHandles[idx]) { - uint16_t cccValue = AttsCccGet(connectionHandle, idx); - if (cccValue & ATT_CLIENT_CFG_NOTIFY || (cccValue & ATT_CLIENT_CFG_INDICATE)) { - *enabledP = true; - } else { - *enabledP = false; - } - return BLE_ERROR_NONE; - } - } +ble_error_t GattServer::areUpdatesEnabled( + Gap::Handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabled +) { + if (connectionHandle == DM_CONN_ID_NONE) { + return BLE_ERROR_INVALID_PARAM; } + for (uint8_t idx = 0; idx < cccd_cnt; idx++) { + if (characteristic.getValueHandle() == cccd_handles[idx]) { + uint16_t cccd_value = AttsCccGet(connectionHandle, idx); + if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + *enabled = true; + } else { + *enabled = false; + } + return BLE_ERROR_NONE; + } + } return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -511,9 +810,7 @@ ble_error_t GattServer::reset(void) while (registered_service) { internal_service_t* s = registered_service; registered_service = s->next; - AttsRemoveGroup(s->attGroup->startHandle); - delete s->attGroup; - delete[] s->chars; + AttsRemoveGroup(s->attGroup.startHandle); delete s; } @@ -528,33 +825,60 @@ ble_error_t GattServer::reset(void) free(generic_access_service.device_name_value()); currentHandle = 0; - cccCnt = 0; + cccd_cnt = 0; - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + _auth_char_count = 0; + + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); return BLE_ERROR_NONE; } -void GattServer::cccCback(attsCccEvt_t *pEvt) +void GattServer::cccd_cb(attsCccEvt_t *evt) { - if (pEvt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, pEvt->handle); - } else { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, pEvt->handle); + GattServerEvents::gattEvent_t evt_type = + evt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE) ? + GattServerEvents::GATT_EVENT_UPDATES_ENABLED : + GattServerEvents::GATT_EVENT_UPDATES_DISABLED; + + getInstance().handleEvent(evt_type, evt->handle); +} + +void GattServer::att_cb(const attEvt_t *evt) +{ + if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATTS_HANDLE_VALUE_CNF) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, evt->handle); } } -void GattServer::attCback(attEvt_t *pEvt) -{ - // TODO enable again - if (pEvt->hdr.status == ATT_SUCCESS) { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, pEvt->handle); - } -} +uint8_t GattServer::atts_read_cb( + dmConnId_t connId, + uint16_t handle, + uint8_t operation, + uint16_t offset, + attsAttr_t *pAttr +) { + GattCharacteristic* auth_char = getInstance().get_auth_char(handle); + if (auth_char && auth_char->isReadAuthorizationEnabled()) { + GattReadAuthCallbackParams read_auth_params = { + connId, + handle, + offset, + /* len */ 0, + /* data */ NULL, + AUTH_CALLBACK_REPLY_SUCCESS + }; -uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) -{ - GattReadCallbackParams cbParams = { + GattAuthCallbackReply_t ret = auth_char->authorizeRead(&read_auth_params); + if (ret != AUTH_CALLBACK_REPLY_SUCCESS) { + return ret & 0xFF; + } + + pAttr->pValue = read_auth_params.data; + *pAttr->pLen = read_auth_params.len; + } + + GattReadCallbackParams read_params = { connId, handle, offset, @@ -562,13 +886,20 @@ uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t op pAttr->pValue, /* status */ BLE_ERROR_NONE, }; - getInstance().handleDataReadEvent(&cbParams); + getInstance().handleDataReadEvent(&read_params); return ATT_SUCCESS; } -uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr) -{ +uint8_t GattServer::atts_write_cb( + dmConnId_t connId, + uint16_t handle, + uint8_t operation, + uint16_t offset, + uint16_t len, + uint8_t *pValue, + attsAttr_t *pAttr +) { uint8_t err; /* TODO: offset is not handled properly */ @@ -585,6 +916,12 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o writeOp = GattWriteCallbackParams::OP_WRITE_CMD; break; case ATT_PDU_SIGNED_WRITE_CMD: + if (getInstance()._signing_event_handler) { + getInstance()._signing_event_handler->on_signed_write_received( + connId, + AttsGetSignCounter(connId) + ); + } writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD; break; case ATT_PDU_PREP_WRITE_REQ: @@ -598,7 +935,24 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o break; } - GattWriteCallbackParams cbParams = { + GattCharacteristic* auth_char = getInstance().get_auth_char(handle); + if (auth_char && auth_char->isWriteAuthorizationEnabled()) { + GattWriteAuthCallbackParams write_auth_params = { + connId, + handle, + offset, + len, + pValue, + AUTH_CALLBACK_REPLY_SUCCESS + }; + + GattAuthCallbackReply_t ret = auth_char->authorizeWrite(&write_auth_params); + if (ret!= AUTH_CALLBACK_REPLY_SUCCESS) { + return ret & 0xFF; + } + } + + GattWriteCallbackParams write_params = { connId, handle, writeOp, @@ -606,7 +960,26 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o len, pValue }; - getInstance().handleDataWrittenEvent(&cbParams); + getInstance().handleDataWrittenEvent(&write_params); + + return ATT_SUCCESS; +} + +uint8_t GattServer::atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle) +{ + // this CB is triggered when read or write of an attribute (either a value + // handle or a descriptor) requires secure connection security. + SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager(); + + link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED); + ble_error_t err = security_manager.getLinkEncryption(connId, &encryption); + if (err) { + return ATT_ERR_AUTH; + } + + if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + return ATT_ERR_AUTH; + } return ATT_SUCCESS; } @@ -616,8 +989,8 @@ void GattServer::add_generic_access_service() ++currentHandle; generic_access_service.service.pNext = NULL; generic_access_service.service.startHandle = currentHandle; - generic_access_service.service.readCback = attsReadCback; - generic_access_service.service.writeCback = attsWriteCback; + generic_access_service.service.readCback = atts_read_cb; + generic_access_service.service.writeCback = atts_write_cb; // bind attributes to the service generic_access_service.service.pAttr = generic_access_service.attributes; @@ -732,8 +1105,8 @@ void GattServer::add_generic_attribute_service() ++currentHandle; generic_attribute_service.service.pNext = NULL; generic_attribute_service.service.startHandle = currentHandle; - generic_attribute_service.service.readCback = attsReadCback; - generic_attribute_service.service.writeCback = attsWriteCback; + generic_attribute_service.service.readCback = atts_read_cb; + generic_attribute_service.service.writeCback = atts_write_cb; // bind attributes to the service generic_attribute_service.service.pAttr = generic_attribute_service.attributes; @@ -778,21 +1151,21 @@ void GattServer::add_generic_attribute_service() // CCCD ++current_attribute; current_attribute->pUuid = attCliChCfgUuid; - current_attribute->pValue = (uint8_t*)&cccValues[cccCnt]; + current_attribute->pValue = (uint8_t*)&cccd_values[cccd_cnt]; current_attribute->maxLen = 2; current_attribute->pLen = ¤t_attribute->maxLen; current_attribute->settings = ATTS_SET_CCC; current_attribute->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = ATT_CLIENT_CFG_INDICATE; - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = currentHandle - 1; - cccCnt++; + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = ATT_CLIENT_CFG_INDICATE; + cccds[cccd_cnt].secLevel = DM_SEC_LEVEL_NONE; + cccd_handles[cccd_cnt] = currentHandle - 1; + cccd_cnt++; generic_attribute_service.service.endHandle = currentHandle; AttsAddGroup(&generic_attribute_service.service); - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); } void* GattServer::alloc_block(size_t block_size) { @@ -812,10 +1185,96 @@ void* GattServer::alloc_block(size_t block_size) { return block->data; } +GattCharacteristic* GattServer::get_auth_char(uint16_t value_handle) +{ + for (size_t i = 0; i < _auth_char_count; ++i) { + if (_auth_char[i]->getValueHandle() == value_handle) { + return _auth_char[i]; + } + } + return NULL; +} + +bool GattServer::get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const +{ + for (idx = 0; idx < cccd_cnt; idx++) { + if (cccd_handle == cccds[idx].handle) { + return true; + } + } + return false; +} + +bool GattServer::has_cccd(GattAttribute::Handle_t char_handle) const +{ + for (uint8_t cccd_index = 0; cccd_index < cccd_cnt; ++cccd_index) { + if (char_handle == cccd_handles[cccd_index]) { + return true; + } + } + return false; +} + +bool GattServer::is_update_authorized( + Gap::Handle_t connection, + GattAttribute::Handle_t value_handle +) { + GattCharacteristic* auth_char = get_auth_char(value_handle); + if (!auth_char) { + return true; + } + + att_security_requirement_t sec_req = + auth_char->getUpdateSecurityRequirement(); + + if (sec_req == att_security_requirement_t::NONE) { + return true; + } + + SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager(); + link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED); + ble_error_t err = security_manager.getLinkEncryption(connection, &encryption); + if (err) { + return false; + } + + switch (sec_req.value()) { + case att_security_requirement_t::UNAUTHENTICATED: + if (encryption < link_encryption_t::ENCRYPTED) { + return false; + } + return true; + + case att_security_requirement_t::AUTHENTICATED: + if (encryption < link_encryption_t::ENCRYPTED_WITH_MITM) { + return false; + } + return true; + + case att_security_requirement_t::SC_AUTHENTICATED: + if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + return false; + } + return true; + + default: + return false; + } +} + GattServer::GattServer() : - ::GattServer(), cccSet(), cccValues(), cccHandles(), cccCnt(0), - generic_access_service(), generic_attribute_service(), - registered_service(NULL), allocated_blocks(NULL), + ::GattServer(), + _signing_event_handler(NULL), + cccds(), + cccd_values(), + cccd_handles(), + cccd_cnt(0), + _auth_char(), + _auth_char_count(0), + generic_access_service(), + generic_attribute_service(), + registered_service(NULL), + allocated_blocks(NULL), currentHandle(0) { } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index a682561335..3c1bc36a94 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -14,10 +14,15 @@ * limitations under the License. */ +#include + #include "CordioPalSecurityManager.h" +#include "CordioBLE.h" #include "dm_api.h" +#include "att_api.h" #include "smp_api.h" #include "wsf_os.h" +#include "hci_core.h" namespace ble { namespace pal { @@ -27,14 +32,19 @@ namespace cordio { CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), - _default_passkey(0) + _default_passkey(0), + _lesc_keys_generated(false), + _public_key_x(), + _pending_privacy_control_blocks(NULL), + _processing_privacy_control_block(false), + _peer_csrks() { } CordioSecurityManager::~CordioSecurityManager() { - + clear_privacy_control_blocks(); } //////////////////////////////////////////////////////////////////////////// @@ -43,16 +53,31 @@ CordioSecurityManager::~CordioSecurityManager() ble_error_t CordioSecurityManager::initialize() { + // reset local state + _use_default_passkey = false; + _default_passkey = 0; + _lesc_keys_generated = false; + memset(_peer_csrks, 0, sizeof(_peer_csrks)); + +#if 0 + // FIXME: need help from the stack or local calculation + // generate a new set of keys + DmSecGenerateEccKeyReq(); +#endif + return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::terminate() { + cleanup_peer_csrks(); return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::reset() { + cleanup_peer_csrks(); + initialize(); return BLE_ERROR_NONE; } @@ -62,37 +87,65 @@ ble_error_t CordioSecurityManager::reset() uint8_t CordioSecurityManager::read_resolving_list_capacity() { - // FIXME: Implement with privacy support. - return 0; + // The Cordio stack requests this from the controller during initialization + return hciCoreCb.resListSize; } +// As the Cordio stack can only handle one of these methods at a time, we need to create a list of control blocks +// that are dequeued one after the other on completion of the previous one ble_error_t CordioSecurityManager::add_device_to_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address, const irk_t &peer_irk ) { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_add_device_to_resolving_list(peer_identity_address_type, peer_identity_address, peer_irk); + + return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t& peer_identity_address ) { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_remove_device_from_resolving_list(peer_identity_address_type, peer_identity_address); + + return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::clear_resolving_list() { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_clear_resolving_list(); + + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// // Feature support // +// FIXME: Enable when new function available in the pal. +#if 0 ble_error_t CordioSecurityManager::set_secure_connections_support( bool enabled, bool secure_connections_only ) { @@ -104,6 +157,7 @@ ble_error_t CordioSecurityManager::set_secure_connections_support( } return BLE_ERROR_NONE; } +#endif ble_error_t CordioSecurityManager::get_secure_connections_support( bool &enabled @@ -243,20 +297,64 @@ ble_error_t CordioSecurityManager::set_ltk_not_found( ble_error_t CordioSecurityManager::set_irk(const irk_t& irk) { - DmSecSetLocalIrk(const_cast(irk.data())); + _irk = irk; + DmSecSetLocalIrk(_irk.data()); return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) -{ - DmSecSetLocalCsrk(const_cast(csrk.data())); +ble_error_t CordioSecurityManager::set_csrk( + const csrk_t& csrk, + sign_count_t sign_counter +) { + _csrk = csrk; + DmSecSetLocalCsrk(_csrk.data()); + // extra set the sign counter used by the client + CordioAttClient::get_client().set_sign_counter(sign_counter); + return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::generate_public_key() +ble_error_t CordioSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter +) { + if (connection == 0 || connection > DM_CONN_MAX) { + return BLE_ERROR_INVALID_PARAM; + } + + size_t connection_index = connection - 1; + + if (_peer_csrks[connection_index]) { + *_peer_csrks[connection_index] = csrk; + } else { + _peer_csrks[connection_index] = new (std::nothrow) csrk_t(csrk); + if (_peer_csrks[connection_index] == NULL) { + return BLE_ERROR_NO_MEM; + } + } + + AttsSetCsrk(connection, _peer_csrks[connection_index]->data(), authenticated); + AttsSetSignCounter(connection, sign_counter); + return BLE_ERROR_NONE; +} + +ble_error_t CordioSecurityManager::remove_peer_csrk(connection_handle_t connection) { - // FIXME - return BLE_ERROR_NOT_IMPLEMENTED; + if (connection == 0 || connection > DM_CONN_MAX) { + return BLE_ERROR_INVALID_PARAM; + } + + size_t connection_index = connection - 1; + + if (_peer_csrks[connection_index]) { + delete _peer_csrks[connection_index]; + _peer_csrks[connection_index] = NULL; + } + + AttsSetCsrk(connection, NULL, false); + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// @@ -344,7 +442,7 @@ ble_error_t CordioSecurityManager::cancel_pairing( ble_error_t CordioSecurityManager::get_random_data(byte_array_t<8> &random_data) { - SecRand(random_data.buffer(), random_data.size()); + SecRand(random_data.data(), random_data.size()); return BLE_ERROR_NOT_IMPLEMENTED; } @@ -364,7 +462,7 @@ ble_error_t CordioSecurityManager::passkey_request_reply( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::legacy_pairing_oob_data_request_reply( +ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) { @@ -380,8 +478,8 @@ ble_error_t CordioSecurityManager::legacy_pairing_oob_data_request_reply( ble_error_t CordioSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { - // FIXME: - return BLE_ERROR_NOT_IMPLEMENTED; + DmSecCompareRsp(connection, confirmation); + return BLE_ERROR_NONE; } // FIXME: remove when declaration from the stack is available @@ -394,13 +492,32 @@ ble_error_t CordioSecurityManager::send_keypress_notification( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::oob_data_verified( + +ble_error_t CordioSecurityManager::generate_secure_connections_oob() { + uint8_t oobLocalRandom[SMP_RAND_LEN]; + SecRand(oobLocalRandom, SMP_RAND_LEN); + DmSecCalcOobReq(oobLocalRandom, _public_key_x); + return BLE_ERROR_NONE; +} + +ble_error_t CordioSecurityManager::secure_connections_oob_request_reply( connection_handle_t connection, const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm ) { + dmSecLescOobCfg_t oob_config = { 0 }; + + memcpy(oob_config.localRandom, local_random.data(), local_random.size()); // FIXME: - return BLE_ERROR_NOT_IMPLEMENTED; + // memcpy(oob_config.localConfirm, ?, ?); + memcpy(oob_config.peerRandom, peer_random.data(), peer_random.size()); + memcpy(oob_config.peerConfirm, peer_confirm.data(), peer_confirm.size()); + + DmSecSetOob(connection, &oob_config); + DmSecAuthRsp(connection, 0, NULL); + + return BLE_ERROR_NONE; } CordioSecurityManager& CordioSecurityManager::get_security_manager() @@ -410,8 +527,8 @@ CordioSecurityManager& CordioSecurityManager::get_security_manager() } bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { - SecurityManager::EventHandler* handler = - get_security_manager().get_event_handler(); + CordioSecurityManager& self = get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); if ((msg == NULL) || (handler == NULL)) { return false; @@ -473,6 +590,11 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { connection_handle_t connection = evt->hdr.param; if (evt->oob) { + // FIXME: Nothing in the API indicates if smp or sc OOB are + // requested. + // To set secure connection OOB: + // - DmSecSetOob(connection, oob_data) + // - DmSecAuthRsp(connection, 0, NULL) handler->on_legacy_pairing_oob_request(connection); } else if (evt->display) { if (get_security_manager()._use_default_passkey) { @@ -596,18 +718,35 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { return true; } - case DM_SEC_CALC_OOB_IND: + case DM_SEC_CALC_OOB_IND: { + dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg; + handler->on_secure_connections_oob_generated( + evt->random, + evt->confirm + ); return true; + } - case DM_SEC_ECC_KEY_IND: + case DM_SEC_ECC_KEY_IND: { + secEccMsg_t* evt = (secEccMsg_t*) msg; + DmSecSetEccKey(&evt->data.key); + memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(_public_key_x)); + self._lesc_keys_generated = true; return true; + } - case DM_SEC_COMPARE_IND: + case DM_SEC_COMPARE_IND: { + dmSecCnfIndEvt_t* evt = (dmSecCnfIndEvt_t*) msg; + handler->on_passkey_display( + /* connection */ evt->hdr.param, + DmSecGetCompareValue(evt->confirm) + ); + handler->on_confirmation_request(/* connection */ evt->hdr.param); return true; + } case DM_SEC_KEYPRESS_IND: { dmSecKeypressIndEvt_t* evt = (dmSecKeypressIndEvt_t*) msg; - handler->on_keypress_notification( /* connection */ evt->hdr.param, (Keypress_t) evt->notificationType @@ -615,11 +754,209 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { return true; } + // Privacy + case DM_PRIV_ADD_DEV_TO_RES_LIST_IND: // Device added to resolving list + case DM_PRIV_REM_DEV_FROM_RES_LIST_IND: // Device removed from resolving list + case DM_PRIV_CLEAR_RES_LIST_IND: // Resolving list cleared + { + // Previous command completed, we can move to the next control block + self.process_privacy_control_blocks(true); + return true; + } default: return false; } } +struct CordioSecurityManager::PrivacyControlBlock +{ + PrivacyControlBlock() : _next(NULL) {} + + virtual ~PrivacyControlBlock() {} + + virtual void execute() = 0; + + void set_next(PrivacyControlBlock* next) { + _next = next; + } + + PrivacyControlBlock* next() const { + return _next; + } + +private: + PrivacyControlBlock* _next; +}; + +struct CordioSecurityManager::PrivacyClearResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyClearResListControlBlock() : PrivacyControlBlock() + {} + + virtual ~PrivacyClearResListControlBlock() {} + + virtual void execute() { + // Execute command + DmPrivClearResList(); + } +}; + +struct CordioSecurityManager::PrivacyAddDevToResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyAddDevToResListControlBlock( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ) : PrivacyControlBlock(), + _peer_identity_address_type(peer_identity_address_type), + _peer_identity_address(peer_identity_address), + _peer_irk(peer_irk) + {} + + virtual ~PrivacyAddDevToResListControlBlock() {} + + virtual void execute() { + // Execute command + DmPrivAddDevToResList(_peer_identity_address_type.value(), _peer_identity_address.data(), _peer_irk.data(), DmSecGetLocalIrk(), false, 0); + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; + irk_t _peer_irk; +}; + +struct CordioSecurityManager::PrivacyRemoveDevFromResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyRemoveDevFromResListControlBlock( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ) : PrivacyControlBlock(), + _peer_identity_address_type(peer_identity_address_type), + _peer_identity_address(peer_identity_address) + { + + } + + virtual ~PrivacyRemoveDevFromResListControlBlock() {} + + virtual void execute() { + // Execute command + DmPrivRemDevFromResList(_peer_identity_address_type.value(), _peer_identity_address.data(), 0); + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; +}; + +// Helper functions for privacy +void CordioSecurityManager::queue_add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk +) +{ + PrivacyAddDevToResListControlBlock* cb = + new (std::nothrow) PrivacyAddDevToResListControlBlock(peer_identity_address_type, peer_identity_address, peer_irk); + if( cb == NULL ) + { + // Cannot go further + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::queue_remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) +{ + PrivacyRemoveDevFromResListControlBlock* cb = + new (std::nothrow) PrivacyRemoveDevFromResListControlBlock(peer_identity_address_type, peer_identity_address); + if( cb == NULL ) + { + // Cannot go further + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::queue_clear_resolving_list() { + // Remove any pending control blocks, there's no point executing them as we're about to queue the list + clear_privacy_control_blocks(); + + PrivacyClearResListControlBlock* cb = + new (std::nothrow) PrivacyClearResListControlBlock(); + if( cb == NULL ) + { + // Cannot go further + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::clear_privacy_control_blocks() { + while(_pending_privacy_control_blocks != NULL) + { + PrivacyControlBlock* next = _pending_privacy_control_blocks->next(); + delete _pending_privacy_control_blocks; + _pending_privacy_control_blocks = next; + } +} + +void CordioSecurityManager::queue_privacy_control_block(PrivacyControlBlock* block) +{ + if( _pending_privacy_control_blocks == NULL ) { + _pending_privacy_control_blocks = block; + } + else { + PrivacyControlBlock* node = _pending_privacy_control_blocks; + while(node->next() != NULL) { + node = node->next(); + } + node->set_next(block); + } + + process_privacy_control_blocks(false); +} + +// If cb_completed is set to true, it means the previous control block has completed +void CordioSecurityManager::process_privacy_control_blocks(bool cb_completed) +{ + if( (_processing_privacy_control_block == true) && !cb_completed ) + { + // Busy, cannot process next control block for now + return; + } + + PrivacyControlBlock* cb = _pending_privacy_control_blocks; + if(cb == NULL) { + // All control blocks processed + _processing_privacy_control_block = false; + return; + } + + // Process next block and free it + _processing_privacy_control_block = true; + + PrivacyControlBlock* next = cb->next(); + cb->execute(); + delete cb; + _pending_privacy_control_blocks = next; +} + +void CordioSecurityManager::cleanup_peer_csrks() { + for (size_t i = 0; i < DM_CONN_MAX; ++i) { + if (_peer_csrks[i]) { + delete _peer_csrks[i]; + _peer_csrks[i] = NULL; + } + } +} } // cordio } // vendor diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h index ba81dd509d..2ead0ed962 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h @@ -565,7 +565,7 @@ uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); * \return None. */ /*************************************************************************************************/ -void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk); +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authenticated); /*************************************************************************************************/ /*! diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar index e49d6c553d..1597a2b37d 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar index 96af76a1f1..908338594d 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar index fd5276440e..3eeaf263be 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar index aeb550373b..5825027100 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a index 050038521c..07307fafa1 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a index faf8486eb4..85bd5a33fa 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a index 6e634a35a5..a3dba57788 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 7d9dd41ab4..82ae3644ec 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a index bb26c368af..716da5554e 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a index 8268984670..8551f1904c 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a index 044939a91d..3f77c0f0a6 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a index c5d1011599..3352eafc41 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar index 876dd0f4e7..419d5c51b5 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar index 9f64cd94d8..b05b1ab381 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar index 5785677375..7e524be4f7 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 62588a6418..dfa0edbdf1 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a index 8befd91f7b..41afc866dd 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a index 95cda1314c..f4a56abbbc 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a index 48e9f8761e..2c68aa94e0 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 673172faae..8a6ac10f04 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a index 60c856f5b4..2e55364a77 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a index 43349bd81e..3bd78bfb7d 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a index f443f75a1e..414d03b69e 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a index 8fd30c8584..197618e7d2 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar index ee6513e0a1..37bf058e0e 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar index b4c2a8f945..a64af691dc 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar index ced1d82ea3..c123c98a53 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 8072742428..f1a2fd0f5c 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a index 9a6e4d821c..4ea97f8da9 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a index b81d8bef0d..bb039d0b26 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a index a66d8dbde0..2dec68ea33 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a index cdcebb2892..0a91f5596b 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a index 8897bb0754..1e3e37600c 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a index f5ce4defd1..764388437c 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a index 30d94fc49d..b52ccf7c5e 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a index bb308cedaf..dff3a7bb94 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar index 0d0432c2cc..89f559614f 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar index fc3e70f00e..a2d3f7edca 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar index 367ea52db6..8055705de5 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 2ae4f4981f..b1db9dd65a 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a index 9341376a92..d526058a61 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a index 0df5f1f46f..88452c4e73 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a index c784d8cf8a..7572fa316a 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 2799065352..a115a3aa91 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a index 50309c95e4..56b4f40a1c 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a index 619acf074c..6aed31880d 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a index 4a762ad709..50087f708d 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a index 07c823837a..403021767e 100644 Binary files a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a and b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a differ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle.cpp index 0873336a44..ee361f3011 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle.cpp @@ -38,11 +38,9 @@ extern "C" { #if (IS_LEGACY_DEVICE_MANAGER_ENABLED) #include "pstorage.h" - #include "device_manager.h" #else #include "fstorage.h" #include "fds.h" - #include "peer_manager.h" #include "ble_conn_state.h" #endif @@ -52,8 +50,8 @@ extern "C" { #include "nrf_ble_hci.h" -#include "nRF5XPalGattClient.h" - +#include "nRF5xPalGattClient.h" +#include "nRF5xPalSecurityManager.h" bool isEventsSignaled = false; @@ -63,7 +61,7 @@ void app_error_handler(uint32_t error_code, uint32_t line_num, const extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector. -static void btle_handler(ble_evt_t *p_ble_evt); +void btle_handler(ble_evt_t *p_ble_evt); static void sys_evt_dispatch(uint32_t sys_evt) { @@ -145,9 +143,6 @@ error_t btle_init(void) return ERROR_INVALID_PARAM; } - // Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp) - pm_init(); - #if (NRF_SD_BLE_API_VERSION <= 2) ble_gap_addr_t addr; if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) { @@ -157,9 +152,7 @@ error_t btle_init(void) return ERROR_INVALID_PARAM; } #else - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - pm_privacy_set(&privacy_params); + #endif ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler)); @@ -168,9 +161,10 @@ error_t btle_init(void) return btle_gap_init(); } -static void btle_handler(ble_evt_t *p_ble_evt) +void btle_handler(ble_evt_t *p_ble_evt) { - using ble::pal::vendor::nordic::nRF5XGattClient; + using ble::pal::vendor::nordic::nRF5xGattClient; + using ble::pal::vendor::nordic::nRF5xSecurityManager; /* Library service handlers */ #if SDK_CONN_PARAMS_MODULE_ENABLE @@ -178,59 +172,29 @@ static void btle_handler(ble_evt_t *p_ble_evt) #endif #if (IS_LEGACY_DEVICE_MANAGER_ENABLED) - dm_ble_evt_handler(p_ble_evt); #else // Forward BLE events to the Connection State module. // This must be called before any event handler that uses this module. ble_conn_state_on_ble_evt(p_ble_evt); - - // Forward BLE events to the Peer Manager - pm_on_ble_evt(p_ble_evt); #endif #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) - nRF5XGattClient::handle_events(p_ble_evt); + nRF5xGattClient::handle_events(p_ble_evt); #endif nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); nRF5xGap &gap = (nRF5xGap &) ble.getGap(); nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer(); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager(); /* Custom event handler */ switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; -#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110) - /* Only peripheral role is supported by S110 */ - Gap::Role_t role = Gap::PERIPHERAL; -#else - Gap::Role_t role = static_cast(p_ble_evt->evt.gap_evt.params.connected.role); -#endif - gap.setConnectionHandle(handle); - const Gap::ConnectionParams_t *params = reinterpret_cast(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); - const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; -#if (NRF_SD_BLE_API_VERSION <= 2) - const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - static_cast(own->addr_type), own->addr, - params); -#else - Gap::AddressType_t addr_type; - Gap::Address_t own_address; - gap.getAddress(&addr_type, own_address); - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - addr_type, own_address, - params); -#endif + case BLE_GAP_EVT_CONNECTED: + gap.on_connection( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.connected + ); break; - } case BLE_GAP_EVT_DISCONNECTED: { Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; @@ -258,17 +222,13 @@ static void btle_handler(ble_evt_t *p_ble_evt) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) // Close all pending discoveries for this connection - nRF5XGattClient::handle_connection_termination(handle); + nRF5xGattClient::handle_connection_termination(handle); #endif gap.processDisconnectionEvent(handle, reason); break; } - case BLE_GAP_EVT_PASSKEY_DISPLAY: - securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); - break; - case BLE_GAP_EVT_TIMEOUT: gap.processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); break; @@ -280,22 +240,17 @@ static void btle_handler(ble_evt_t *p_ble_evt) // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; - case BLE_GAP_EVT_ADV_REPORT: { - const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - gap.processAdvertisementReport(advReport->peer_addr.addr, - advReport->rssi, - advReport->scan_rsp, - static_cast(advReport->type), - advReport->dlen, - advReport->data, - static_cast(advReport->peer_addr.addr_type)); + case BLE_GAP_EVT_ADV_REPORT: + gap.on_advertising_packet(p_ble_evt->evt.gap_evt.params.adv_report); break; - } default: break; } + // Process security manager events + securityManager.sm_handler(p_ble_evt); + gattServer.hwCallback(p_ble_evt); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.cpp deleted file mode 100644 index 389c9b5c4c..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* 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. - */ -#if defined(S110) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "pstorage.h" -#include "device_manager.h" -#include "id_manager.h" -} - -#include "btle_security.h" - -static dm_application_instance_t applicationInstance; -static bool initialized = false; -static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result); - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 1, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - if (pstorage_init() != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - dm_init_param_t dm_init_param = { - .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */ - }; - if (dm_init(&dm_init_param) != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - const dm_application_param_t dm_param = { - .evt_handler = dm_handler, - .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID, - .sec_param = securityParameters - }; - - if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - dm_handle_t dmHandle = { - .appl_id = applicationInstance, - }; - if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) { - if (rc == NRF_ERROR_NOT_FOUND) { - return BLE_ERROR_INVALID_PARAM; - } else { - return BLE_ERROR_UNSPECIFIED; - } - } - - if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast(securityStatusP))) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ble_gap_sec_params_t params = securityParameters; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - uint32_t result = sd_ble_gap_authenticate(connectionHandle, ¶ms); - - if (result == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_UNSPECIFIED; - } -} - -ret_code_t -dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - - switch (p_event->event_id) { - case DM_EVT_SECURITY_SETUP: /* started */ { - const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - break; - } - case DM_EVT_SECURITY_SETUP_COMPLETE: - securityManager. - processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, - (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); - break; - case DM_EVT_LINK_SECURED: { - unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm; - unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv; - SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - switch (securityMode) { - case 1: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); - break; - } - case DM_EVT_DEVICE_CONTEXT_STORED: - securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); - break; - default: - break; - } - - return NRF_SUCCESS; -} - -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} - - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} -#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.h deleted file mode 100644 index a1354a36ee..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security.h +++ /dev/null @@ -1,146 +0,0 @@ -/* 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 _BTLE_SECURITY_H_ -#define _BTLE_SECURITY_H_ - -#include "ble/Gap.h" -#include "ble/SecurityManager.h" - -/** - * Function to test whether the SecurityManager has been initialized. - * Possible by a call to @ref btle_initializeSecurity(). - * - * @return True if the SecurityManager was previously initialized, false - * otherwise. - */ -bool btle_hasInitializedSecurity(void); - -/** - * Enable Nordic's Device Manager, which brings in functionality from the - * stack's Security Manager. The Security Manager implements the actual - * cryptographic algorithms and protocol exchanges that allow two devices to - * securely exchange data and privately detect each other. - * - * @param[in] enableBonding Allow for bonding. - * @param[in] requireMITM Require protection for man-in-the-middle attacks. - * @param[in] iocaps To specify IO capabilities of this peripheral, - * such as availability of a display or keyboard to - * support out-of-band exchanges of security data. - * @param[in] passkey To specify a static passkey. - * - * @return BLE_ERROR_NONE on success. - */ -ble_error_t btle_initializeSecurity(bool enableBonding = true, - bool requireMITM = true, - SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE, - const SecurityManager::Passkey_t passkey = NULL); - -/** - * Get the security status of a link. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[out] securityStatusP - * security status. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP); - -/** - * Set the security mode on a connection. Useful for elevating the security mode - * once certain conditions are met, e.g., a particular service is found. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[in] securityMode - * security mode. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode); - -/** - * Function for deleting all peer device context and all related bonding - * information from the database. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. - * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or - * application registration. - */ -ble_error_t btle_purgeAllBondingState(void); - -#if (NRF_SD_BLE_API_VERSION <= 2) -/** - * Query the SoftDevice bond table to extract a whitelist containing the BLE - * addresses and IRKs of bonded devices. - * - * @param[in/out] p_whitelist - * (on input) p_whitelist->addr_count and - * p_whitelist->irk_count specify the maximum number of - * addresses and IRKs added to the whitelist structure. - * (on output) *p_whitelist is a whitelist containing the - * addresses and IRKs of the bonded devices. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist); -#endif - -/** - * Function to test whether a BLE address is generated using an IRK. - * - * @param[in] p_addr - * Pointer to a BLE address. - * @param[in] p_irk - * Pointer to an IRK. - * - * @return True if p_addr can be generated using p_irk, false otherwise. - */ -bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - -/** - * Function to generate a private resolvable BLE address. - * - * @param[out] p_addr - * The output address. - * @param[in] p_irk - * A reference to a IRK. - * - * @note This function does not generate a secure address since the prand number in the - * resolvable address is not truly random. Therefore, the output of this function - * is only meant to be used by the application internally but never exported. - */ -void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address); - -#if (NRF_SD_BLE_API_VERSION >= 3) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList); -#endif - -#endif /* _BTLE_SECURITY_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security_pm.cpp deleted file mode 100644 index 6042b71753..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/btle_security_pm.cpp +++ /dev/null @@ -1,486 +0,0 @@ -/* 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. - */ - -#if defined(S130) || defined(S132) || defined(S140) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "peer_manager.h" -#include "id_manager.h" -#include "fds.h" -} - -#include "btle_security.h" - -static bool initialized = false; - -static void pm_handler(pm_evt_t const *p_event); -static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing. -volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API. - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - if (enableBonding) { - securityParameters.kdist_own.enc = 1; - securityParameters.kdist_own.id = 1; - } else { - securityParameters.kdist_own.enc = 0; - securityParameters.kdist_own.id = 0; - } - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_register(pm_handler); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } - - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - - async_ret_code = NRF_ERROR_BUSY; - - rc = pm_peers_delete(); // it is asynhronous API - - if (rc == NRF_SUCCESS) - { - // waiting for respond from pm_handler - while (async_ret_code == NRF_ERROR_BUSY) { - // busy-loop - } - - rc = async_ret_code; - } - - switch (rc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - pm_conn_sec_status_t conn_sec_status; - - rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status); - - if (rc == NRF_SUCCESS) - { - if (conn_sec_status.encrypted) { - *securityStatusP = SecurityManager::ENCRYPTED; - } - else if (conn_sec_status.connected) { - if (_enc_in_progress) { - *securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS; - } - else { - *securityStatusP = SecurityManager::NOT_ENCRYPTED; - } - } - - return BLE_ERROR_NONE; - } - - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - return BLE_ERROR_INVALID_PARAM; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ret_code_t rc; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 0; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 1; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_conn_secure(connectionHandle, false); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - - -void pm_handler(pm_evt_t const *p_event) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - ret_code_t err_code; - SecurityManager::SecurityMode_t resolvedSecurityMode; - - switch (p_event->evt_id) { - case PM_EVT_CONN_SEC_START: /* started */ { - const ble_gap_sec_params_t *peerParams = &securityParameters; - securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - _enc_in_progress = true; - break; - } - case PM_EVT_CONN_SEC_SUCCEEDED: - // Update the rank of the peer. - if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) - { - err_code = pm_peer_rank_highest(p_event->peer_id); - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, - SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t - - ble_gap_conn_sec_t conn_sec; - sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec); - - resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - - switch (conn_sec.sec_mode.sm) { - case 1: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode); - - _enc_in_progress = false; - break; - - case PM_EVT_CONN_SEC_FAILED: - SecurityManager::SecurityCompletionStatus_t securityCompletionStatus; - - if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) { - securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED; - } else { - securityCompletionStatus = - (SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error; - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus); - - _enc_in_progress = false; - break; - - case PM_EVT_BONDED_PEER_CONNECTED: - pm_peer_rank_highest(p_event->peer_id); - break; - - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - securityManager.processSecurityContextStoredEvent(p_event->conn_handle); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - break; - - case PM_EVT_PEERS_DELETE_SUCCEEDED: - async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_PEERS_DELETE_FAILED: - async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_STORAGE_FULL: - // Run garbage collection on the flash. - err_code = fds_gc(); - if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) - { - // Retry. - } - else - { - APP_ERROR_CHECK(err_code); - } - break;//PM_EVT_STORAGE_FULL - - case PM_EVT_CONN_SEC_CONFIG_REQ:{ - // A connected peer (central) is trying to pair, but the Peer Manager already has a bond - // for that peer. Setting allow_repairing to false rejects the pairing request. - // If this event is ignored (pm_conn_sec_config_reply is not called in the event - // handler), the Peer Manager assumes allow_repairing to be false. - pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; - pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config); - } - break;//PM_EVT_CONN_SEC_CONFIG_REQ - - default: - break; - } -} - -#if (NRF_SD_BLE_API_VERSION <= 2) -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} -#endif - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} - - -#if (NRF_SD_BLE_API_VERSION >= 3) -ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) -{ - pm_peer_id_t peer_id; - ret_code_t ret; - pm_peer_data_bonding_t bond_data; - - addrList.size = 0; - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - /** - * Fill addresses list: - * Copy addresses from bond table, or - * for every private resolvable address in the bond table generate the resolvable address. - */ - while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - btle_generateResolvableAddress(bond_data.peer_ble_id.id_info, - (ble_gap_addr_t &) addrList.addresses[addrList.size].address); - } else { - memcpy(&addrList.addresses[addrList.size].address, - &bond_data.peer_ble_id.id_addr_info.addr, - sizeof(addrList.addresses[0].address)); - } - - addrList.addresses[addrList.size].type = static_cast (bond_data.peer_ble_id.id_addr_info.addr_type); - - addrList.size++; - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - return BLE_ERROR_NONE; -} -#endif - -#endif // defined(S130) || defined(S132) || defined(S140) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.cpp index bc46d3d58d..6a85387330 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.cpp @@ -30,6 +30,34 @@ typedef struct { static unsigned uuidTableEntries = 0; /* current usage of the table */ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES]; +namespace { + +static void set_perm(ble_gap_conn_sec_mode_t& dest, GattAttribute::Security_t src) { + switch (src.value()) { + case GattAttribute::Security_t::NONE: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dest); + break; + + case GattAttribute::Security_t::UNAUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dest); + break; + + case GattAttribute::Security_t::AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&dest); + break; + + case GattAttribute::Security_t::SC_AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dest); + break; + + default: + break; + } +} + +} + + void custom_reset_128bits_uuid_table() { uuidTableEntries = 0; } @@ -203,7 +231,9 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -226,8 +256,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Notification requires cccd */ memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); cccd_md.vloc = BLE_GATTS_VLOC_STACK; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + set_perm(cccd_md.read_perm, GattAttribute::Security_t::NONE); + set_perm(cccd_md.write_perm, update_security); } ble_gatts_char_md_t char_md = {0}; @@ -256,49 +286,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Always set variable size */ attr_md.vlen = has_variable_len; - if (char_props.read || char_props.notify || char_props.indicate) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm); - break; - default: - break; - }; - } - - if (char_props.write || char_props.write_wo_resp) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm); - break; - default: - break; - }; - } + set_perm(attr_md.read_perm, read_security); + set_perm(attr_md.write_perm, write_security); ble_gatts_attr_t attr_char_value = {0}; @@ -342,7 +331,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle) + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security) { /* Descriptor metadata */ ble_gatts_attr_md_t desc_md = {0}; @@ -352,8 +343,8 @@ error_t custom_add_in_descriptor(uint16_t char_handle, desc_md.vlen = has_variable_len; /* Make it readable and writable */ - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); + set_perm(desc_md.read_perm, read_security); + set_perm(desc_md.write_perm, write_security); ble_gatts_attr_t attr_desc = {0}; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.h index 93480b873b..88b8db48ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/btle/custom/custom_helper.h @@ -45,7 +45,9 @@ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid); error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -64,7 +66,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle); + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security); #ifdef __cplusplus } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp new file mode 100644 index 0000000000..e6ff14a21b --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp @@ -0,0 +1,194 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include +#include + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#endif + +#include "platform/NonCopyable.h" +#include "platform/CriticalSectionLock.h" +#include "ble/BLETypes.h" +#include "cmsis.h" +#include "nRF5xCrypto.h" +#include "platform/mbed_assert.h" +#include "nrf_soc.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +#if defined(MBEDTLS_ECDH_C) + +CryptoToolbox::CryptoToolbox() : _initialized(false) { + mbedtls_entropy_init(&_entropy_context); + mbedtls_ecp_group_init(&_group); + int err = mbedtls_ecp_group_load( + &_group, + MBEDTLS_ECP_DP_SECP256R1 + ); + _initialized = err ? false : true; +} + +CryptoToolbox::~CryptoToolbox() { + mbedtls_ecp_group_free(&_group); + mbedtls_entropy_free(&_entropy_context); +} + +bool CryptoToolbox::generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret +) { + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + int err = mbedtls_ecp_gen_keypair( + &_group, + &secret_key, + &public_keys, + mbedtls_entropy_func, + &_entropy_context + ); + + if (!err) { + store_mpi(secret, secret_key); + store_mpi(X, public_keys.X); + store_mpi(Y, public_keys.Y); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + + return err ? false : true; +} + +bool CryptoToolbox::generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret +) { + mbedtls_mpi result; + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&result); + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + load_mpi(secret_key, own_secret); + load_mpi(public_keys.X, peer_X); + load_mpi(public_keys.Y, peer_Y); + mbedtls_mpi_lset( &public_keys.Z, 1 ); + + int err = mbedtls_ecdh_compute_shared( + &_group, + &result, + &public_keys, + &secret_key, + /* rng function; optional */ NULL, + /* rng param */ NULL + ); + + if (!err) { + store_mpi(shared_secret, result); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + mbedtls_mpi_free(&result); + + return err ? false : true; +} + +#endif + +bool CryptoToolbox::ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash +) { + // Note copy then swap operation can be optimized. + + // Note: the encryption block works in big endian; go figure. + nrf_ecb_hal_data_t ecb_hal_data; + + memcpy(ecb_hal_data.key, irk.data(), irk.size()); + swap_endian(ecb_hal_data.key, sizeof(ecb_hal_data.key)); + + memcpy(ecb_hal_data.cleartext, prand.data(), prand.size()); + memset(ecb_hal_data.cleartext + prand.size(), 0, sizeof(ecb_hal_data.cleartext) - prand.size()); + swap_endian(ecb_hal_data.cleartext, sizeof(ecb_hal_data.cleartext)); + + uint32_t err = sd_ecb_block_encrypt(&ecb_hal_data); + + if (err) { + return false; + } + + swap_endian(ecb_hal_data.ciphertext, sizeof(ecb_hal_data.ciphertext)); + + memcpy(hash.data(), ecb_hal_data.ciphertext, hash.size()); + + return true; +} + +#if defined(MBEDTLS_ECDH_C) + +void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { + ble::public_key_coord_t src_be = src.data(); + swap_endian(src_be.data(), src_be.size()); + mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); +} + +void CryptoToolbox::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { + mbedtls_mpi_write_binary(&src, dest.data(), dest.size()); + swap_endian(dest.data(), dest.size()); +} + +#endif + +void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { + for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { + std::swap(buf[low], buf[high]); + } +} + +} // nordic +} // vendor +} // pal +} // ble diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h new file mode 100644 index 0000000000..123fac3564 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h @@ -0,0 +1,156 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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. + */ + +#ifndef NRF5X_CRYPTO_ +#define NRF5X_CRYPTO_ + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#endif + +#include "platform/NonCopyable.h" +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +/** + * Toolbox of cryptographic functions used in BLE. + */ +class CryptoToolbox : mbed::NonCopyable { + +public: + /** + * Size of the Key used in lesc crypto operations. + */ + static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; + + /** + * Size of an IRK. + */ + static const ptrdiff_t irk_size_ = irk_t::size_; + + /** + * Size of the hash generated by ah. + */ + static const ptrdiff_t hash_size_ = 3; + + /** + * Size of prand. + */ + static const ptrdiff_t prand_size_ = 3; + +#if defined(MBEDTLS_ECDH_C) + + /** + * Create a new CryptoToolbox. + */ + CryptoToolbox(); + + /** + * Destroy a CryptoTioolbox object. + */ + ~CryptoToolbox(); + + /** + * Generate lesc public and private keys. + * @param[out] X The component X of the public key. + * @param[out] Y The component Y of the public key. + * @param[out] secret The secret key. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret + ); + + /** + * Generate a shared secret from a peer public key and a local secret key. + * @param[in] peer_X The component X of the peer public key. + * @param[in] peer_Y The component Y of the peer public key. + * @param[in] own_secret The local secret key. + * @param[out] shared_secret The shared secret generated. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret + ); + +#endif + + /** + * Execute the function ah. This function can be used to generate private + * resolvable addresses and resolve them. + * + * @note all parameters passed and return by this fucntion are in little + * endian. + * + * @param[in] irk The key used to create hash. + * @param[in] prand The random part from which the hash will be generated. + * @param[out] hash The hash generated. + * + * @return true in case of success and false otherwise. + */ + static bool ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash + ); + +private: + +#if defined(MBEDTLS_ECDH_C) + void load_mpi(mbedtls_mpi& dest, const ArrayView& src); + + void store_mpi(ArrayView& dest, const mbedtls_mpi& src); +#endif + + static void swap_endian(uint8_t* buf, size_t len); + +#if defined(MBEDTLS_ECDH_C) + bool _initialized; + mbedtls_entropy_context _entropy_context; + mbedtls_ecp_group _group; +#endif + +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif // NRF5X_CRYPTO_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp index 56c9218fee..a80744df11 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp @@ -25,18 +25,90 @@ #include "common/common.h" #include "ble_advdata.h" #include "headers/nrf_ble_hci.h" +#include "ble/pal/ConnectionEventMonitor.h" +#include "nRF5xPalSecurityManager.h" -#if (NRF_SD_BLE_API_VERSION >= 3) - #include "peer_manager.h" - #include "peer_data_storage.h" -#endif +using ble::pal::vendor::nordic::nRF5xSecurityManager; +typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; +using ble::ArrayView; +using ble::pal::advertising_peer_address_type_t; +using ble::peer_address_type_t; +typedef BLEProtocol::AddressType LegacyAddressType; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; + +namespace { + +nRF5xSecurityManager& get_sm() { + return nRF5xSecurityManager::get_security_manager(); +} + +ble_error_t set_private_resolvable_address() { + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE }; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; +} + +ble_error_t set_private_non_resolvable_address() { + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; +} + +bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { + switch (params.getAdvertisingType()) { + case GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED: + case GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED: + return true; + default: + return false; + } +} + +bool is_identity_address(peer_address_type_t address_type) { + return address_type == peer_address_type_t::PUBLIC_IDENTITY || + address_type == peer_address_type_t::RANDOM_STATIC_IDENTITY; +} + +peer_address_type_t convert_nordic_address(uint8_t address) { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return peer_address_type_t::PUBLIC; + } else { + return peer_address_type_t::RANDOM; + } +} + +peer_address_type_t convert_identity_address(advertising_peer_address_type_t address) { + if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { + return peer_address_type_t::PUBLIC_IDENTITY; + } else { + return peer_address_type_t::RANDOM_STATIC_IDENTITY; + } +} + +} // namespace void radioNotificationStaticCallback(bool param) { nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); gap.processRadioNotificationEvent(param); } +nRF5xGap::nRF5xGap() : Gap(), + advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), + scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), + whitelistAddressesSize(0), + whitelistAddresses(), + radioNotificationCallbackParam(false), + radioNotificationTimeout(), + _connection_event_handler(NULL), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), + _non_private_address_type(LegacyAddressType::RANDOM_STATIC) +{ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; +} + /**************************************************************************/ /*! @brief Sets the advertising parameters and payload for the device @@ -143,7 +215,7 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) { uint32_t err; ble_gap_adv_params_t adv_para = {0}; - + /* Make sure we support the advertising type */ if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { /* ToDo: This requires a propery security implementation, etc. */ @@ -188,27 +260,45 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (advertisingPolicyMode != Gap::ADV_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; + whitelist.addr_count = whitelistAddressesSize; + + for (uint32_t i = 0; i < whitelistAddressesSize; ++i) { + whitelistAddressPtrs[i] = &whitelistAddresses[i]; + } + + if (_privacy_enabled) { + if (_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + } + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); } } - + adv_para.p_whitelist = &whitelist; #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + /* Start Advertising */ - - adv_para.type = params.getAdvertisingType(); adv_para.p_peer_addr = NULL; // Undirected advertisement adv_para.fp = advertisingPolicyMode; adv_para.interval = params.getIntervalInADVUnits(); // advertising interval (in units of 0.625 ms) adv_para.timeout = params.getTimeout(); - err = sd_ble_gap_adv_start(&adv_para); switch(err) { @@ -225,9 +315,8 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) { - ble_gap_scan_params_t scanParams; - + #if (NRF_SD_BLE_API_VERSION <= 2) /* Allocate the stack's whitelist statically */ ble_gap_whitelist_t whitelist; @@ -239,29 +328,50 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; + whitelist.addr_count = whitelistAddressesSize; + + for (uint32_t i = 0; i < whitelistAddressesSize; ++i) { + whitelistAddressPtrs[i] = &whitelistAddresses[i]; + } + + if (_privacy_enabled) { + if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; } } - + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + scanParams.use_whitelist = scanningPolicyMode; scanParams.adv_dir_report = 0; #endif - + scanParams.active = scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + if (_privacy_enabled) { + if (_central_privacy_configuration.use_non_resolvable_random_address) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } + if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -304,12 +414,77 @@ ble_error_t nRF5xGap::stopAdvertising(void) return BLE_ERROR_NONE; } -ble_error_t nRF5xGap::connect(const Address_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t *connectionParams, - const GapScanningParams *scanParamsIn) -{ +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + peer_address_type_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + // NOTE: Nordic address type is an closer to LegacyAddressType: resolved + // address are treaded either as PUBLIC or RANDOM STATIC adresses. + // The idea is to get the conversion done here and call the legacy function. + + LegacyAddressType_t legacy_address; + + switch (peerAddrType.value()) { + case peer_address_type_t::PUBLIC: + case peer_address_type_t::PUBLIC_IDENTITY: + legacy_address = LegacyAddressType::PUBLIC; + break; + case peer_address_type_t::RANDOM_STATIC_IDENTITY: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case peer_address_type_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = getRandomAddressType(peerAddr, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + break; + default: + return BLE_ERROR_UNSPECIFIED; + } + } break; + default: + return BLE_ERROR_INVALID_PARAM; + } + + bool identity = + peerAddrType == peer_address_type_t::PUBLIC_IDENTITY || + peerAddrType == peer_address_type_t::RANDOM_STATIC_IDENTITY; + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn, identity); +} + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + return connect(peerAddr, peerAddrType, connectionParams, scanParamsIn, /* identity */ false); +} + + + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn, + bool identity +) { ble_gap_addr_t addr; + ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); @@ -326,8 +501,8 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, connParams.conn_sup_timeout = 600; } - ble_gap_scan_params_t scanParams ={0}; - + ble_gap_scan_params_t scanParams = { 0 }; + #if (NRF_SD_BLE_API_VERSION <= 2) /* Allocate the stack's whitelist statically */ ble_gap_whitelist_t whitelist; @@ -339,25 +514,39 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; - } - } - scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ + + if (_privacy_enabled) { + if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + + if (identity) { + scanParams.selective = true; + addr_ptr = NULL; + } + } + + set_private_resolvable_address(); + } #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + scanParams.use_whitelist = (whitelistAddressesSize) ? 1 : 0; if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { /* If a device is using Resolvable Private Addresses Section 1.3.2.2 (Core spec v4.2 volume 6 part B), - it shall also have an Identity Address that is either a Public or Random Static address type.†+ it shall also have an Identity Address that is either a Public or Random Static address type. To establish a connection, a static address must be provided by the application to the SoftDevice. The SoftDevice resolves the address and connects to the right device if it is available. */ addr.addr_id_peer = 1; @@ -365,7 +554,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } else { addr.addr_id_peer = 0; } - + #endif if (scanParamsIn != NULL) { @@ -380,7 +569,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, scanParams.timeout = _scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ } - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams); if (rc == NRF_SUCCESS) { return BLE_ERROR_NONE; } @@ -492,7 +681,7 @@ ble_error_t nRF5xGap::reset(void) /* Clear the internal whitelist */ whitelistAddressesSize = 0; - + return BLE_ERROR_NONE; } @@ -533,61 +722,54 @@ uint16_t nRF5xGap::getConnectionHandle(void) @endcode */ /**************************************************************************/ -ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) +ble_error_t nRF5xGap::setAddress(LegacyAddressType_t type, const Address_t address) { -#if (NRF_SD_BLE_API_VERSION <= 2) - uint8_t cycle_mode; -#else - ble_gap_privacy_params_t privacy_params = {0}; -#endif + if (type != LegacyAddressType::PUBLIC && + type != LegacyAddressType::RANDOM_STATIC + ) { + return BLE_ERROR_INVALID_PARAM; + } + + if (_privacy_enabled) { + return BLE_ERROR_INVALID_STATE; + } - ble_gap_addr_t dev_addr; + memcpy(dev_addr.addr, address, ADDR_LEN); + if (type == LegacyAddressType::PUBLIC) { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + } else { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; + } - /* When using Public or Static addresses, the cycle mode must be None. - When using Random Private addresses, the cycle mode must be Auto. - In auto mode, the given address is ignored. - */ - if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) - { - memcpy(dev_addr.addr, address, ADDR_LEN); #if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr); #else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - dev_addr.addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - } - else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) - { -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; -#else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - privacy_params.private_addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - // address is ignored when in auto mode - } - else - { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - dev_addr.addr_type = type; - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + uint32_t err = sd_ble_gap_addr_set(&dev_addr); #endif - return BLE_ERROR_NONE; + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + default: + return BLE_ERROR_UNSPECIFIED; + } } ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) { + if (typeP == NULL || address == NULL) { + return BLE_ERROR_INVALID_PARAM; + } + ble_gap_addr_t dev_addr; #if (NRF_SD_BLE_API_VERSION <= 2) if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { @@ -597,12 +779,21 @@ ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) return BLE_ERROR_PARAM_OUT_OF_RANGE; } - if (typeP != NULL) { - *typeP = static_cast(dev_addr.addr_type); - } - if (address != NULL) { - memcpy(address, dev_addr.addr, ADDR_LEN); + switch (dev_addr.addr_type) { + case BLE_GAP_ADDR_TYPE_PUBLIC: + *typeP = LegacyAddressType::PUBLIC; + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + *typeP = LegacyAddressType::RANDOM_STATIC; + break; + + default: + return BLE_ERROR_INVALID_STATE; } + + memcpy(address, dev_addr.addr, ADDR_LEN); + return BLE_ERROR_NONE; } @@ -728,9 +919,7 @@ ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const uint32_t i; for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { memcpy( &whitelistOut.addresses[i].address, &whitelistAddresses[i].addr, sizeof(whitelistOut.addresses[0].address)); - whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); - - + whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); } whitelistOut.size = i; @@ -775,7 +964,9 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) /* Test for invalid parameters before we change the internal state */ for (uint32_t i = 0; i < whitelistIn.size; ++i) { - if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE || + whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE + ) { /* This is not allowed because it is completely meaningless */ return BLE_ERROR_INVALID_PARAM; } @@ -931,267 +1122,258 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } -#if (NRF_SD_BLE_API_VERSION <= 2) -/**************************************************************************/ -/*! - @brief Helper function used to populate the ble_gap_whitelist_t that - will be used by the SoftDevice for filtering requests. - - @returns \ref ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @retval BLE_ERROR_INVALID_STATE - The internal stack was not initialized correctly. - - @note Both the SecurityManager and Gap must initialize correctly for - this function to succeed. - - @note This function is needed because for the BLE API the whitelist - is just a collection of keys, but for the stack it also includes - the IRK table. - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) +ble_error_t nRF5xGap::enablePrivacy(bool enable_privacy) { - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[1]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - if (securityManager.hasInitialized()) { - /* We do not care about the addresses, set the count to 0 */ - whitelistFromBondTable.addr_count = 0; - /* The Nordic SDK will return a failure if we set pp_addr to NULL */ - whitelistFromBondTable.pp_addrs = addressPtr; - /* We want all the IRKs we can get because we do not know which ones match the addresses */ - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - /* Use the security manager to get the IRKs from the bond table */ - ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - return error; - } - } else { - /** - * If there is no security manager then we cannot access the bond table, - * so disable IRK matching - */ - whitelistFromBondTable.addr_count = 0; - whitelistFromBondTable.irk_count = 0; + if (enable_privacy == _privacy_enabled) { + return BLE_ERROR_NONE; } - /** - * For every private resolvable address in the local whitelist check if - * there is an IRK for said address in the bond table and add it to the - * local IRK list. - */ - whitelist.irk_count = 0; - whitelist.addr_count = 0; - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - /* Test if there is a matching IRK for this private resolvable address */ - for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { - /* Found the corresponding IRK, add it to our local whitelist */ - whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; - whitelist.irk_count++; - /* Make sure we do not look at this IRK again */ - if (j != whitelistFromBondTable.irk_count - 1) { - /** - * This is not the last IRK, so replace the pointer - * with the last pointer in the array - */ - whitelistFromBondTable.pp_irks[j] = - whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; - } - /** - * If the IRK is the last pointer in the array simply - * decrement the total IRK count - */ - whitelistFromBondTable.irk_count--; - break; - } - } - } else { - /* Include the address into the whitelist */ - whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; - whitelist.addr_count++; - } - } - - return BLE_ERROR_NONE; -} -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - -/** - * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. - * - * Gap::setWhitelist provides the base for preparation of these settings. - * This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table. - * Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice) - * are passed to the identities list (intended to be passed to the Softdevice). - * - * @param[out] gapAdrHelper Reference to the struct for storing settings. - */ - -ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - pm_peer_id_t peer_id; - - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - - uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE]; - - memset(irk_found, 0x00, sizeof(irk_found)); - - - gapAdrHelper.identities_cnt = 0; - - - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - /** - * Build identities list: - * For every private resolvable address in the bond table check if - * there is maching address in th provided whitelist. - */ - while (peer_id != PM_PEER_ID_INVALID) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - - //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info)) - { - // Copy data to the buffer. - memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - gapAdrHelper.identities_cnt++; - - irk_found[i] = 1; // don't look at this address again - } - } - } - } - } - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - gapAdrHelper.addrs_cnt = 0; - - /** - * Build whitelist from the rest of addresses (explicit addresses) - */ - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t)); - gapAdrHelper.addrs[i].addr_id_peer = 0; - gapAdrHelper.addrs_cnt++; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - uint32_t retc; - - if (gapAdrHelper.identities_cnt == 0) { - retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (enable_privacy == false) { + err = setAddress(_non_private_address_type, _non_private_address); } else { - ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i) - { - pp_identities[i] = &gapAdrHelper.identities[i]; - } - - retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); - } - - if (retc == NRF_SUCCESS) { - if (gapAdrHelper.addrs_cnt == 0) { - retc = sd_ble_gap_whitelist_set(NULL, 0); - } else { - ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i) - { - pp_addrs[i] = &gapAdrHelper.addrs[i]; - } - - retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); - } - } - - switch(retc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared. - case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared. - return BLE_ERROR_ALREADY_INITIALIZED; - - case NRF_ERROR_INVALID_ADDR: - case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied. - case NRF_ERROR_DATA_SIZE: - case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() -{ - GapWhiteAndIdentityList_t whiteAndIdentityList; - uint32_t err; - - err = getStackWhiteIdentityList(whiteAndIdentityList); - - if (err != BLE_ERROR_NONE) { - return (ble_error_t)err; + err = getAddress(&_non_private_address_type, _non_private_address); } - return applyWhiteIdentityList(whiteAndIdentityList); -} + if (err) { + return err; + } + +#if (NRF_SD_BLE_API_VERSION > 2) + ble_gap_privacy_params_t privacy_config = { 0 }; + if (sd_ble_gap_privacy_get(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.privacy_mode = enable_privacy ? + BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY : + BLE_GAP_PRIVACY_MODE_OFF; + if (sd_ble_gap_privacy_set(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } #endif + + _privacy_enabled = enable_privacy; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) { + _peripheral_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) { + *configuration = _peripheral_privacy_configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) { + _central_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) { + *configuration = _central_privacy_configuration; + return BLE_ERROR_NONE; +} + +void nRF5xGap::set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler +) { + _connection_event_handler = connection_event_handler; +} + +void nRF5xGap::processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason +) { + if (_connection_event_handler) { + _connection_event_handler->on_disconnected( + handle, + reason + ); + } + + ::Gap::processDisconnectionEvent( + handle, + reason + ); +} + +void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { + using BLEProtocol::AddressType; + + // set the new connection handle as the _default_ handle in gap + setConnectionHandle(handle); + + // deal with own address + LegacyAddressType_t own_addr_type; + Address_t own_address; + const uint8_t* own_resolvable_address = NULL; + +#if (NRF_SD_BLE_API_VERSION <= 2) + if (_privacy_enabled) { + own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + } else { + if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { + own_addr_type = LegacyAddressType::PUBLIC; + } else { + own_addr_type = LegacyAddressType::RANDOM_STATIC; + } + } + + // FIXME: is it the resolvable address or the identity address ? + memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); +#else + gap.getAddress(&addr_type, own_address); +#endif + + // deal with the peer address: If privacy is enabled then the softdevice + // indicates if the address has been resolved or not. If the address has + // been resolved then the identity address should be passed to the application. + // Depending on the privacy chosen by the application, connection request + // from privacy enabled peers may trigger a disconnection, the pairing procedure + // or the authentication procedure. + peer_address_type_t peer_addr_type(peer_address_type_t::PUBLIC); + const uint8_t* peer_address; + const uint8_t* peer_resolvable_address; + +#if (NRF_SD_BLE_API_VERSION <= 2) + bool private_peer_known = evt.irk_match; + + // thanks to softdevice consistencies; addresses are not resolved on the + // peripheral side ... + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE && + get_sm().resolve_address(evt.peer_addr.addr) != NULL + ) { + private_peer_known = true; + } +#else + bool private_peer_known = evt.peer_addr.addr_id_peer; +#endif + + if (private_peer_known) { + const resolving_list_entry_t* entry = get_sm().resolve_address( + evt.peer_addr.addr + ); + MBED_ASSERT(entry == NULL); + + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + peer_address = entry->peer_identity_address.data(); + peer_resolvable_address = evt.peer_addr.addr; + } else { + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + get_sm().get_resolving_list().size() > 0 + ) { + // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible + // with the softdevice ... + sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + return; + } + + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + peer_address = evt.peer_addr.addr; + peer_resolvable_address = NULL; + } + + // notify internal event handler before applying the resolution strategy + if (_connection_event_handler) { + _connection_event_handler->on_connected( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)) + ); + } + + // Apply authentication strategy before application notification + if (!private_peer_known && + _privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + ) { + switch (_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle); + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + // FIXME: lookup secure DB to know what to do. + break; + + default: + break; + } + } + + processConnectionEvent( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)), + peer_resolvable_address, + own_resolvable_address + ); +} + +void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { + peer_address_type_t peer_addr_type(peer_address_type_t::PUBLIC); + const uint8_t* peer_address = evt.peer_addr.addr; + + if (_privacy_enabled && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE + ) { + using ble::pal::vendor::nordic::nRF5xSecurityManager; + + const resolving_list_entry_t* entry = get_sm().resolve_address( + peer_address + ); + + if (entry) { + peer_address = entry->peer_identity_address.data(); + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + } else if (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD || + get_sm().get_resolving_list().size() == 0 + ) { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } else { + // filter out the packet. + return; + } + } else { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } + + processAdvertisementReport( + peer_address, + evt.rssi, + evt.scan_rsp, + static_cast(evt.type), + evt.dlen, + evt.data, + peer_addr_type + ); +} + + + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h index 922260954a..a1f2700218 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h @@ -44,6 +44,7 @@ #include "ble/GapAdvertisingData.h" #include "ble/Gap.h" #include "ble/GapScanningParams.h" +#include "ble/pal/ConnectionEventMonitor.h" #include "nrf_soc.h" @@ -52,8 +53,6 @@ extern "C" { #include "app_util_platform.h" } -#include "btle_security.h" - void radioNotificationStaticCallback(bool param); /**************************************************************************/ @@ -62,9 +61,12 @@ void radioNotificationStaticCallback(bool param); */ /**************************************************************************/ -class nRF5xGap : public Gap -{ +class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor { public: + nRF5xGap(); + + virtual ~nRF5xGap() { } + /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); @@ -76,7 +78,9 @@ public: virtual ble_error_t startAdvertising(const GapAdvertisingParams &); virtual ble_error_t stopAdvertising(void); + 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 disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); @@ -120,6 +124,24 @@ public: return BLE_ERROR_UNSPECIFIED; } + virtual ble_error_t enablePrivacy(bool enable); + + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); + /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); @@ -139,39 +161,6 @@ private: uint8_t whitelistAddressesSize; ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE]; -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * An internal function used to populate the ble_gap_whitelist_t that will be used by - * the SoftDevice for filtering requests. This function is needed because for the BLE - * API the whitelist is just a collection of keys, but for the stack it also includes - * the IRK table. - */ - ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist); -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - /* internal type for passing a whitelist and a identities list. */ - typedef struct - { - ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; - uint32_t addrs_cnt; - - ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - uint32_t identities_cnt; - } GapWhiteAndIdentityList_t; - - /* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/ - ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/ - ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice. - * - * This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */ - ble_error_t updateWhiteAndIdentityListInStack(void); -#endif - private: bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ Timeout radioNotificationTimeout; @@ -254,21 +243,43 @@ private: } friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */ +public: + /** @note Implements ConnectionEventMonitor. + * @copydoc ConnectionEventMonitor::set_connection_event_handler + */ + virtual void set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler + ); + + /** + * @copydoc ::Gap::processDisconnectionEvent + */ + void processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason + ); + private: + friend void btle_handler(ble_evt_t *p_ble_evt); + + void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt); + void on_advertising_packet(const ble_gap_evt_adv_report_t &evt); + uint16_t m_connectionHandle; + ConnectionEventMonitor::EventHandler* _connection_event_handler; + + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + AddressType_t _non_private_address_type; + Address_t _non_private_address; + /* * Allow instantiation from nRF5xn when required. */ friend class nRF5xn; - nRF5xGap() : - advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), - scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), - whitelistAddressesSize(0) { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; - } - nRF5xGap(nRF5xGap const &); void operator=(nRF5xGap const &); }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.cpp index 8bcdd7d07a..4963145059 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.cpp @@ -25,42 +25,43 @@ #include "btle/custom/custom_helper.h" #include "nRF5xn.h" +#include "nrf_ble_gap.h" namespace { static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID_OFFSET } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 0 + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 0 } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID } } }; @@ -164,21 +165,25 @@ ble_error_t nRF5xGattServer::addService(GattService &service) } ASSERT_TRUE ( ERROR_NONE == - custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, - &nordicUUID, - p_char->getProperties(), - p_char->getRequiredSecurity(), - p_char->getValueAttribute().getValuePtr(), - p_char->getValueAttribute().getLength(), - p_char->getValueAttribute().getMaxLength(), - p_char->getValueAttribute().hasVariableLength(), - userDescriptionDescriptorValuePtr, - userDescriptionDescriptorValueLen, - presentationFormatDescriptorValuePtr, - presentationFormatDescriptorValueLen, - p_char->isReadAuthorizationEnabled(), - p_char->isWriteAuthorizationEnabled(), - &nrfCharacteristicHandles[characteristicCount]), + custom_add_in_characteristic( + BLE_GATT_HANDLE_INVALID, + &nordicUUID, + p_char->getProperties(), + p_char->getReadSecurityRequirement(), + p_char->getWriteSecurityRequirement(), + p_char->getUpdateSecurityRequirement(), + p_char->getValueAttribute().getValuePtr(), + p_char->getValueAttribute().getLength(), + p_char->getValueAttribute().getMaxLength(), + p_char->getValueAttribute().hasVariableLength(), + userDescriptionDescriptorValuePtr, + userDescriptionDescriptorValueLen, + presentationFormatDescriptorValuePtr, + presentationFormatDescriptorValueLen, + p_char->isReadAuthorizationEnabled(), + p_char->isWriteAuthorizationEnabled(), + &nrfCharacteristicHandles[characteristicCount] + ), BLE_ERROR_PARAM_OUT_OF_RANGE ); /* Update the characteristic handle */ @@ -218,7 +223,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service) p_desc->getLength(), p_desc->getMaxLength(), p_desc->hasVariableLength(), - &nrfDescriptorHandles[descriptorCount]), + &nrfDescriptorHandles[descriptorCount], + p_desc->getReadSecurityRequirement(), + p_desc->getWriteSecurityRequirement()), BLE_ERROR_PARAM_OUT_OF_RANGE); p_descriptors[descriptorCount] = p_desc; @@ -260,9 +267,9 @@ ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { - .len = *lengthP, - .offset = 0, - .p_value = buffer, + /* .len = */ *lengthP, + /* .offset = */ 0, + /* .p_value = */ buffer, }; ASSERT_TRUE( ERROR_NONE == @@ -302,9 +309,9 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute ble_error_t returnValue = BLE_ERROR_NONE; ble_gatts_value_t value = { - .len = len, - .offset = 0, - .p_value = const_cast(buffer), + /* .len = */ len, + /* .offset = */ 0, + /* .p_value = */ const_cast(buffer), }; if (localOnly) { @@ -345,7 +352,16 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute } } - if (updatesEnabled) { + bool updates_permitted = false; + ble_gap_conn_sec_t connection_security; + uint32_t err = sd_ble_gap_conn_sec_get(connectionHandle, &connection_security); + if (!err && + (connection_security.sec_mode.sm == 1) && + (connection_security.sec_mode.lv >= p_characteristics[characteristicIndex]->getUpdateSecurityRequirement().value())) { + updates_permitted = true; + } + + if (updatesEnabled && updates_permitted) { error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); if (error != ERROR_NONE) { switch (error) { @@ -453,7 +469,7 @@ ble_error_t nRF5xGattServer::reset(void) @brief Callback handler for events getting pushed up from the SD */ /**************************************************************************/ -void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) +void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) { GattAttribute::Handle_t handle_value; GattServerEvents::gattEvent_t eventType; @@ -611,14 +627,14 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) // success, signal it to the softdevice ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 1, - .offset = input_req.offset, - .len = input_req.len, - .p_data = input_req.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 1, + /* .offset = */ input_req.offset, + /* .len = */ input_req.len, + /* .p_data = */ input_req.data } } }; @@ -639,12 +655,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .offset = req->offset, - .len = req->length, - .data = req->data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; @@ -661,9 +677,9 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) // FIXME can't use ::write here, this function doesn't take the offset into account ... ble_gatts_value_t value = { - .len = req->length, - .offset = req->offset, - .p_value = req->data + /* .len = */ req->length, + /* .offset = */ req->offset, + /* .p_value = */ req->data }; uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value); if (update_err) { @@ -688,25 +704,25 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), - .update = 1, - .offset = cbParams.offset, - .len = cbParams.len, - .p_data = cbParams.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), + /* .update = */ 1, + /* .offset = */ cbParams.offset, + /* .len = */ cbParams.len, + /* .p_data = */ cbParams.data } } }; @@ -740,21 +756,21 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { GattReadAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.read.offset, - .len = 0, - .data = NULL, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.read.offset, + /* .len = */ 0, + /* .data = */ NULL, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_READ, - .params = { - .read = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_READ, + /* .params = */ { + /* .read = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeRead(&cbParams) } } }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h index ca4e069d80..6be90ff733 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h @@ -39,7 +39,7 @@ public: /* nRF51 Functions */ void eventCallback(void); - void hwCallback(ble_evt_t *p_ble_evt); + void hwCallback(const ble_evt_t *p_ble_evt); private: diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.cpp similarity index 94% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.cpp rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.cpp index cba1ea60d4..404b3bdc96 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.cpp @@ -16,7 +16,7 @@ #include -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" #include "ble/pal/PalGattClient.h" #include "ble/pal/SimpleAttServerMessage.h" @@ -159,30 +159,30 @@ static const size_t characteristic_declaration_length = 1 + 2 + 16; } // end of anonymous namespace -nRF5XGattClient::nRF5XGattClient() : +nRF5xGattClient::nRF5xGattClient() : ble::pal::GattClient(), _procedures() { } -nRF5XGattClient::~nRF5XGattClient() +nRF5xGattClient::~nRF5xGattClient() { terminate(); } -ble_error_t nRF5XGattClient::initialize() +ble_error_t nRF5xGattClient::initialize() { return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::exchange_mtu(connection_handle_t connection) +ble_error_t nRF5xGattClient::exchange_mtu(connection_handle_t connection) { // FIXME: implement when SD 140 5.x.x is present // (see sd_ble_gatts_exchange_mtu_reply) return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5XGattClient::get_mtu_size( +ble_error_t nRF5xGattClient::get_mtu_size( connection_handle_t connection_handle, uint16_t& mtu_size ) { #if (NRF_SD_BLE_API_VERSION >= 3) @@ -195,7 +195,7 @@ ble_error_t nRF5XGattClient::get_mtu_size( return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::discover_primary_service( +ble_error_t nRF5xGattClient::discover_primary_service( connection_handle_t connection, attribute_handle_t discovery_range_begining ) { @@ -204,7 +204,7 @@ ble_error_t nRF5XGattClient::discover_primary_service( ); } -ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( +ble_error_t nRF5xGattClient::discover_primary_service_by_service_uuid( connection_handle_t connection_handle, attribute_handle_t discovery_range_beginning, const UUID& uuid @@ -214,7 +214,7 @@ ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( ); } -ble_error_t nRF5XGattClient::find_included_service( +ble_error_t nRF5xGattClient::find_included_service( connection_handle_t connection_handle, attribute_handle_range_t service_range ) { @@ -223,7 +223,7 @@ ble_error_t nRF5XGattClient::find_included_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( +ble_error_t nRF5xGattClient::discover_characteristics_of_a_service( connection_handle_t connection_handle, attribute_handle_range_t discovery_range ) { @@ -232,7 +232,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_descriptors( +ble_error_t nRF5xGattClient::discover_characteristics_descriptors( connection_handle_t connection_handle, attribute_handle_range_t descriptors_discovery_range ) { @@ -241,7 +241,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_descriptors( ); } -ble_error_t nRF5XGattClient::read_attribute_value( +ble_error_t nRF5xGattClient::read_attribute_value( connection_handle_t connection_handle, attribute_handle_t attribute_handle ) { @@ -250,7 +250,7 @@ ble_error_t nRF5XGattClient::read_attribute_value( ); } -ble_error_t nRF5XGattClient::read_using_characteristic_uuid( +ble_error_t nRF5xGattClient::read_using_characteristic_uuid( connection_handle_t connection_handle, attribute_handle_range_t read_range, const UUID& uuid @@ -260,7 +260,7 @@ ble_error_t nRF5XGattClient::read_using_characteristic_uuid( ); } -ble_error_t nRF5XGattClient::read_attribute_blob( +ble_error_t nRF5xGattClient::read_attribute_blob( connection_handle_t connection, attribute_handle_t attribute_handle, uint16_t offset @@ -270,7 +270,7 @@ ble_error_t nRF5XGattClient::read_attribute_blob( ); } -ble_error_t nRF5XGattClient::read_multiple_characteristic_values( +ble_error_t nRF5xGattClient::read_multiple_characteristic_values( connection_handle_t connection, const ArrayView& characteristic_handles ) { @@ -279,7 +279,7 @@ ble_error_t nRF5XGattClient::read_multiple_characteristic_values( ); } -ble_error_t nRF5XGattClient::write_without_response( +ble_error_t nRF5xGattClient::write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -297,7 +297,7 @@ ble_error_t nRF5XGattClient::write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::signed_write_without_response( +ble_error_t nRF5xGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -315,7 +315,7 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::write_attribute( +ble_error_t nRF5xGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, const ArrayView& value @@ -325,7 +325,7 @@ ble_error_t nRF5XGattClient::write_attribute( ); } -ble_error_t nRF5XGattClient::queue_prepare_write( +ble_error_t nRF5xGattClient::queue_prepare_write( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value, @@ -336,7 +336,7 @@ ble_error_t nRF5XGattClient::queue_prepare_write( ); } -ble_error_t nRF5XGattClient::execute_write_queue( +ble_error_t nRF5xGattClient::execute_write_queue( connection_handle_t connection_handle, bool execute ) { @@ -367,7 +367,7 @@ ble_error_t nRF5XGattClient::execute_write_queue( * @note Commands such as write without response or signed write without response * are not procedures. */ -struct nRF5XGattClient::GattProcedure { +struct nRF5xGattClient::GattProcedure { /** * Initialize the procedure. * @@ -424,7 +424,7 @@ struct nRF5XGattClient::GattProcedure { * Given that such procedure expects a single event type from the soft device, * error handling can be generalized. */ -struct nRF5XGattClient::RegularGattProcedure : GattProcedure { +struct nRF5xGattClient::RegularGattProcedure : GattProcedure { /** * Construct a RegularGattProcedure. @@ -483,7 +483,7 @@ protected: * In such case a read request is issued for each service attribute handle * to extract that information. */ -struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { typedef ArrayView services_array_t; @@ -692,7 +692,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { * response it is possible to reconstruct it by keeping a copy of the UUID to * find. */ -struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -766,7 +766,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProce /** * Procedure that manage Find Included Services transactions. */ -struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { +struct nRF5xGattClient::FindIncludedServicesProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -841,7 +841,7 @@ struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { * In such case a read request is issued for each attribute handle of * characteristics that exposes a long UUID. */ -struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Data structure returned by the function flatten_response. */ @@ -1060,7 +1060,7 @@ struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Procedure that handle discovery of characteristic descriptors. */ -struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { DiscoverDescriptorsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1151,7 +1151,7 @@ struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { /** * Procedure that handle read of attribute handles. */ -struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeProcedure : RegularGattProcedure { ReadAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1178,7 +1178,7 @@ struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { /** * Procedure that handle read of characteristic using characteristic UUID. */ -struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { ReadUsingCharacteristicUUIDProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1265,7 +1265,7 @@ struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProced /** * Procedure that handles read blob transactions. */ -struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { ReadAttributeBlobProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_BLOB_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1291,7 +1291,7 @@ struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { /** * Procedure that handles Read Multiple Characteristic Values transactions. */ -struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { ReadMultipleCharacteristicsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1321,7 +1321,7 @@ struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProced /** * Procedure that handles Write transactions. */ -struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::WriteAttributeProcedure : RegularGattProcedure { WriteAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::WRITE_REQUEST, BLE_GATTC_EVT_WRITE_RSP @@ -1352,7 +1352,7 @@ struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { /** * Procedure that handles Prepare Write transactions. */ -struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { +struct nRF5xGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { QueuePrepareWriteProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1398,7 +1398,7 @@ struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { /** * Procedure that handles Execute Write transactions. */ -struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { +struct nRF5xGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { ExecuteWriteQueueProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1437,7 +1437,7 @@ struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { }; // NOTE: position after declaration of GattProcedure on purpose. -ble_error_t nRF5XGattClient::terminate() +ble_error_t nRF5xGattClient::terminate() { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i]) { @@ -1450,7 +1450,7 @@ ble_error_t nRF5XGattClient::terminate() } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1473,7 +1473,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1496,7 +1496,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2 ) { @@ -1520,7 +1520,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2, const A3& a3 ) { @@ -1543,7 +1543,7 @@ ble_error_t nRF5XGattClient::launch_procedure( return err; } -nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( +nRF5xGattClient::GattProcedure* nRF5xGattClient::get_procedure( connection_handle_t connection ) const { for (size_t i = 0; i < max_procedures_count; ++i) { @@ -1554,7 +1554,7 @@ nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( return NULL; } -bool nRF5XGattClient::register_procedure(GattProcedure *p) +bool nRF5xGattClient::register_procedure(GattProcedure *p) { if (get_procedure(p->connection_handle)) { return false; @@ -1570,7 +1570,7 @@ bool nRF5XGattClient::register_procedure(GattProcedure *p) return false; } -bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) +bool nRF5xGattClient::remove_procedure(nRF5xGattClient::GattProcedure* p) { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i] == p) { @@ -1583,13 +1583,13 @@ bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) } // singleton of the ARM Cordio client -nRF5XGattClient& nRF5XGattClient::get_client() +nRF5xGattClient& nRF5xGattClient::get_client() { - static nRF5XGattClient _client; + static nRF5xGattClient _client; return _client; } -void nRF5XGattClient::handle_events(const ble_evt_t *evt) { +void nRF5xGattClient::handle_events(const ble_evt_t *evt) { switch (evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: case BLE_GATTC_EVT_REL_DISC_RSP: @@ -1611,7 +1611,7 @@ void nRF5XGattClient::handle_events(const ble_evt_t *evt) { } } -void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_procedure_event(const ble_evt_t &evt) { GattProcedure* p = get_procedure(evt.evt.gattc_evt.conn_handle); if (p) { @@ -1619,7 +1619,7 @@ void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_hvx_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; const ble_gattc_evt_hvx_t &hvx_evt = evt.evt.gattc_evt.params.hvx; @@ -1650,7 +1650,7 @@ void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_timeout_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; GattProcedure* p = get_procedure(connection); @@ -1661,7 +1661,7 @@ void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) on_transaction_timeout(connection); } -void nRF5XGattClient::handle_connection_termination(connection_handle_t connection) +void nRF5xGattClient::handle_connection_termination(connection_handle_t connection) { GattProcedure* p = get_client().get_procedure(connection); if (p) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.h similarity index 97% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.h rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.h index ede03ce3f4..986fe1b48f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalGattClient.h @@ -34,12 +34,12 @@ namespace nordic { /** * Implementation of pal::GattClient for the Nordic stack. */ -class nRF5XGattClient : public ble::pal::GattClient { +class nRF5xGattClient : public ble::pal::GattClient { public: - nRF5XGattClient(); + nRF5xGattClient(); - virtual ~nRF5XGattClient(); + virtual ~nRF5xGattClient(); /** * see pal::GattClient::initialize . @@ -184,7 +184,7 @@ public: ); // singleton of the ARM Cordio client - static nRF5XGattClient& get_client(); + static nRF5xGattClient& get_client(); /** * Function call from btle.cpp diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp new file mode 100644 index 0000000000..ba615211ac --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp @@ -0,0 +1,1216 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 +#include "nRF5xPalSecurityManager.h" +#include "nrf_ble.h" +#include "nrf_ble_gap.h" +#include "nrf_soc.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +namespace { +static ble_error_t convert_sd_error(uint32_t err) { + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + case BLE_ERROR_INVALID_ROLE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NOT_SUPPORTED: + return BLE_ERROR_NOT_IMPLEMENTED; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_TIMEOUT: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_UNSPECIFIED; + } +} +} + +enum pairing_role_t { + PAIRING_INITIATOR, + PAIRING_RESPONDER +}; + +struct nRF5xSecurityManager::pairing_control_block_t { + pairing_control_block_t* next; + connection_handle_t connection; + pairing_role_t role; + + // flags of the key present + KeyDistribution initiator_dist; + KeyDistribution responder_dist; + + // own keys + ble_gap_enc_key_t own_enc_key; + ble_gap_id_key_t own_id_key; + ble_gap_sign_info_t own_sign_key; + ble_gap_lesc_p256_pk_t own_pk; + + // peer keys + ble_gap_enc_key_t peer_enc_key; + ble_gap_id_key_t peer_id_key; + ble_gap_sign_info_t peer_sign_key; + ble_gap_lesc_p256_pk_t peer_pk; + + // flag required to help DHKey computation/process; should be removed with + // later versions of the softdevice + uint8_t own_oob:1; + uint8_t peer_oob:1; +}; + +nRF5xSecurityManager::nRF5xSecurityManager() + : ::ble::pal::SecurityManager(), + _sign_counter(), + _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), + _min_encryption_key_size(7), + _max_encryption_key_size(16), + _control_blocks(NULL), + resolving_list_entry_count(0) +{ + +} + +nRF5xSecurityManager::~nRF5xSecurityManager() +{ + terminate(); +} + +//////////////////////////////////////////////////////////////////////////// +// SM lifecycle management +// + +ble_error_t nRF5xSecurityManager::initialize() +{ +#if defined(MBEDTLS_ECDH_C) + if (_crypto.generate_keys( + make_ArrayView(X), + make_ArrayView(Y), + make_ArrayView(secret) + )) { + return BLE_ERROR_NONE; + } + + return BLE_ERROR_INTERNAL_STACK_FAILURE; +#endif + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::terminate() +{ + release_all_pairing_cb(); + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::reset() +{ + ble_error_t err = terminate(); + if (err) { + return err; + } + + return initialize(); +} + +//////////////////////////////////////////////////////////////////////////// +// Resolving list management +// + +// FIXME: on nordic, the irk is passed in sd_ble_gap_scan_start where whitelist +// and resolving list are all mixed up. + +uint8_t nRF5xSecurityManager::read_resolving_list_capacity() +{ + return MAX_RESOLVING_LIST_ENTRIES; +} + +ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk +) { + if (resolving_list_entry_count >= MAX_RESOLVING_LIST_ENTRIES) { + return BLE_ERROR_INVALID_STATE; + } + + resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count]; + entry.peer_identity_address_type = peer_identity_address_type; + entry.peer_identity_address = peer_identity_address; + entry.peer_irk = peer_irk; + + ++resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) { + size_t entry_index; + + // first the index needs to be found + for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) { + resolving_list_entry_t& entry = resolving_list[entry_index]; + if (entry.peer_identity_address_type == peer_identity_address_type && + entry.peer_identity_address == peer_identity_address + ) { + break; + } + } + + if (entry_index == resolving_list_entry_count) { + return BLE_ERROR_INVALID_PARAM; + } + + // Elements after the entry can be moved in the list + for (size_t i = entry_index; i < (resolving_list_entry_count - 1); ++i) { + resolving_list[i] = resolving_list[i + 1]; + } + + --resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::clear_resolving_list() +{ + resolving_list_entry_count = 0; + return BLE_ERROR_NONE; +} + +ArrayView +nRF5xSecurityManager::get_resolving_list() { + return ArrayView( + resolving_list, + resolving_list_entry_count + ); +} + +const nRF5xSecurityManager::resolving_list_entry_t* +nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { + typedef byte_array_t hash_t; + + for (size_t i = 0; i < resolving_list_entry_count; ++i) { + resolving_list_entry_t& entry = resolving_list[i]; + hash_t hash_generated; + + // Compute the hash part from the random address part when the irk of + // the entry is used + CryptoToolbox::ah( + make_const_ArrayView(entry.peer_irk), + make_const_ArrayView( + resolvable_address.data() + CryptoToolbox::hash_size_ + ), + make_ArrayView(hash_generated) + ); + + // Compare hash generated with the hash present in the address passed as + // parameter. If they are equal then the IRK of the entry has been used + // to generate the resolvable address. + if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) { + return &entry; + } + } + + return NULL; +} + + + +//////////////////////////////////////////////////////////////////////////// +// Pairing +// + + +ble_error_t nRF5xSecurityManager::send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + // allocate the control block required for the procedure completion + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_INITIATOR; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_RESPONDER; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ &security_params, + /* keys */ &keyset + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::cancel_pairing( + connection_handle_t connection, pairing_failure_t reason +) { + // this is the default path except when a key is expected to be entered by + // the user. + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + reason.value() | 0x80, + /* sec params */ NULL, + /* keyset */ NULL + ); + + if (!err) { + return BLE_ERROR_NONE; + } + + // Failed because we're in the wrong state; try to cancel pairing with + // sd_ble_gap_auth_key_reply + if (err == NRF_ERROR_INVALID_STATE) { + err = sd_ble_gap_auth_key_reply( + connection, + /* key type */ BLE_GAP_AUTH_KEY_TYPE_NONE, + /* key */ NULL + ); + } + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Feature support +// + +ble_error_t nRF5xSecurityManager::get_secure_connections_support( + bool &enabled +) { + enabled = false; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) +{ + _io_capability = io_capability; + return BLE_ERROR_NONE; +} + +//////////////////////////////////////////////////////////////////////////// +// Security settings +// + +ble_error_t nRF5xSecurityManager::set_authentication_timeout( + connection_handle_t connection, uint16_t timeout_in_10ms +) { + // FIXME: Use sd_ble_opt_set(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, ...) when + // available + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5xSecurityManager::get_authentication_timeout( + connection_handle_t connection, uint16_t &timeout_in_10ms +) { + // Return default value for now (30s) + timeout_in_10ms = 30 * 100; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size +) { + if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || + (min_encryption_key_size > max_encryption_key_size)) { + return BLE_ERROR_INVALID_PARAM; + } + + _min_encryption_key_size = min_encryption_key_size; + _max_encryption_key_size = max_encryption_key_size; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication +) { + // In the peripheral role, only the bond, mitm, lesc and keypress fields of + // this structure are used. + ble_gap_sec_params_t security_params = { + /* bond */ authentication.get_bondable(), + /* mitm */ authentication.get_mitm(), + /* lesc */ authentication.get_secure_connections(), + /* keypress */ authentication.get_keypress_notification(), + /* remainder of the data structure is ignored */ 0 + }; + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Encryption +// + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm +) { + ble_gap_master_id_t master_id; + memcpy(master_id.rand, rand.data(), rand.size()); + memcpy(&master_id.ediv, ediv.data(), ediv.size()); + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = false; + enc_info.auth = mitm; + + // FIXME: how to pass the lenght of the LTK ??? + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm +) { + ble_gap_master_id_t master_id = {0}; + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = true; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data +) { + // FIXME: Implement in LescCrypto ? + return BLE_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////////// +// Privacy +// + +ble_error_t nRF5xSecurityManager::set_private_address_timeout( + uint16_t timeout_in_seconds +) { + // get the previous config + ble_gap_irk_t irk; + ble_opt_t privacy_config; + privacy_config.gap_opt.privacy.p_irk = &irk; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the timeout and return the result + privacy_config.gap_opt.privacy.interval_s = timeout_in_seconds; + err = sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_config); + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Keys +// + +ble_error_t nRF5xSecurityManager::set_ltk( + connection_handle_t connection, + const ltk_t& ltk, + bool mitm, + bool secure_connections +) { + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = secure_connections; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + // FIXME: provide peer irk and csrk ? + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + &enc_info, + /* id info */ NULL, + /* sign info */ NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_ltk_not_found( + connection_handle_t connection +) { + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + NULL, + NULL, + NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) +{ + // get the previous config + ble_gap_irk_t sd_irk; + ble_opt_t privacy_config; + privacy_config.gap_opt.privacy.p_irk = &sd_irk; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the new irk + memcpy(sd_irk.irk, irk.data(), irk.size()); + err = sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_config); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_csrk( + const csrk_t& csrk, + sign_count_t sign_counter +) { + _csrk = csrk; + _sign_counter = sign_counter; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5xSecurityManager::remove_peer_csrk(connection_handle_t connection) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////////// +// Authentication +// + +ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) +{ + uint32_t err = sd_rand_application_vector_get( + random_data.data(), random_data.size() + ); + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// MITM +// + +ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) +{ + PasskeyAscii passkey_ascii(passkey); + ble_opt_t sd_passkey; + sd_passkey.gap_opt.passkey.p_passkey = passkey ? passkey_ascii.value() : NULL; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sd_passkey); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::passkey_request_reply( + connection_handle_t connection, const passkey_num_t passkey +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + PasskeyAscii pkasc(passkey); + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, + pkasc.value() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + ble_gap_lesc_oob_data_t oob_own; + ble_gap_lesc_oob_data_t oob_peer; + + // is own address important ? + memcpy(oob_own.r, local_random.data(), local_random.size()); + // FIXME: What to do with local confirm ??? + + // is peer address important ? + memcpy(oob_peer.r, peer_random.data(), peer_random.size()); + memcpy(oob_peer.c, peer_confirm.data(), peer_confirm.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_set( + connection, + pairing_cb->own_oob ? &oob_own : NULL, + pairing_cb->peer_oob ? &oob_peer : NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t& oob_data +) { + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_OOB, + oob_data.data() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::confirmation_entered( + connection_handle_t connection, bool confirmation +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE, + NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_keypress_notification( + connection_handle_t connection, Keypress_t keypress +) { + uint32_t err = sd_ble_gap_keypress_notify( + connection, + static_cast(keypress) + ); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() +{ +#if defined(MBEDTLS_ECDH_C) + ble_gap_lesc_p256_pk_t own_secret; + ble_gap_lesc_oob_data_t oob_data; + + memcpy(own_secret.pk, secret.data(), secret.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_get( + BLE_CONN_HANDLE_INVALID, + &own_secret, + &oob_data + ); + + if (!err) { + get_event_handler()->on_secure_connections_oob_generated( + oob_data.r, + oob_data.c + ); + } + + return convert_sd_error(err); +#endif + return BLE_ERROR_NOT_IMPLEMENTED; +} + +nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() +{ + static nRF5xSecurityManager _security_manager; + return _security_manager; +} + +bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) +{ + nRF5xSecurityManager& self = nRF5xSecurityManager::get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); + + if ((evt == NULL) || (handler == NULL)) { + return false; + } + + const ble_gap_evt_t& gap_evt = evt->evt.gap_evt; + uint16_t connection = gap_evt.conn_handle; + pairing_control_block_t* pairing_cb = self.get_pairing_cb(connection); + + switch (evt->header.evt_id) { + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { + const ble_gap_sec_params_t& params = + gap_evt.params.sec_params_request.peer_params; + + KeyDistribution initiator_dist( + params.kdist_peer.enc, + params.kdist_peer.id, + params.kdist_peer.sign, + params.kdist_peer.link + ); + + KeyDistribution responder_dist( + params.kdist_own.enc, + params.kdist_own.id, + params.kdist_own.sign, + params.kdist_own.link + ); + + if (pairing_cb && pairing_cb->role == PAIRING_INITIATOR) { + // when this event is received by an initiator, it should not be + // forwarded via the handler; this is not a behaviour expected + // by the bluetooth standard ... + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ NULL, + /* keys ... */ &keyset + ); + + // in case of error; release the pairing control block and signal + // it to the event handler + if (err) { + release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + pairing_failure_t::UNSPECIFIED_REASON + ); + } + } else { + handler->on_pairing_request( + connection, + params.oob, + AuthenticationMask( + params.bond, + params.mitm, + params.lesc, + params.keypress + ), + initiator_dist, + responder_dist + ); + } + return true; + } + + case BLE_GAP_EVT_SEC_INFO_REQUEST: { + const ble_gap_evt_sec_info_request_t& req = + gap_evt.params.sec_info_request; + + handler->on_ltk_request( + connection, + ediv_t((uint8_t*)(&req.master_id.ediv)), + rand_t(req.master_id.rand) + ); + + return true; + } + + case BLE_GAP_EVT_PASSKEY_DISPLAY: { + const ble_gap_evt_passkey_display_t& req = + gap_evt.params.passkey_display; + + if (req.match_request == 0) { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + } else { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + handler->on_confirmation_request(connection); + } + + return true; + } + + case BLE_GAP_EVT_KEY_PRESSED: { + handler->on_keypress_notification( + connection, + (Keypress_t)gap_evt.params.key_pressed.kp_not + ); + return true; + } + + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { + uint8_t key_type = gap_evt.params.auth_key_request.key_type; + + switch (key_type) { + case BLE_GAP_AUTH_KEY_TYPE_NONE: // Illegal + break; + + case BLE_GAP_AUTH_KEY_TYPE_PASSKEY: + handler->on_passkey_request(connection); + break; + + case BLE_GAP_AUTH_KEY_TYPE_OOB: + handler->on_legacy_pairing_oob_request(connection); + break; + } + + return true; + } + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: { +#if defined(MBEDTLS_ECDH_C) + const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = + gap_evt.params.lesc_dhkey_request; + + static const size_t key_size = public_key_coord_t::size_; + ble_gap_lesc_dhkey_t shared_secret; + + _crypto.generate_shared_secret( + make_const_ArrayView(dhkey_request.p_pk_peer->pk), + make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size), + make_const_ArrayView(secret), + shared_secret.key + ); + + sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret); + + if (dhkey_request.oobd_req) { + handler->on_secure_connections_oob_request(connection); + } +#endif + return true; + } + + case BLE_GAP_EVT_AUTH_STATUS: { + const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status; + + switch (status.auth_status) { + // NOTE: pairing_cb must be valid if this event has been + // received as it is being allocated earlier and release + // in this block + // The memory is released before the last call to the event handler + // to free the heap a bit before subsequent allocation with user + // code. + case BLE_GAP_SEC_STATUS_SUCCESS: { + KeyDistribution own_dist; + KeyDistribution peer_dist; + + if (pairing_cb->role == PAIRING_INITIATOR) { + own_dist = pairing_cb->initiator_dist; + peer_dist = pairing_cb->responder_dist; + } else { + own_dist = pairing_cb->responder_dist; + peer_dist = pairing_cb->initiator_dist; + } + + if (own_dist.get_encryption()) { + handler->on_keys_distributed_local_ltk( + connection, + ltk_t(pairing_cb->own_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_local_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->own_enc_key.master_id.ediv + )), + pairing_cb->own_enc_key.master_id.rand + ); + } + + if (peer_dist.get_encryption()) { + handler->on_keys_distributed_ltk( + connection, + ltk_t(pairing_cb->peer_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->peer_enc_key.master_id.ediv + )), + pairing_cb->peer_enc_key.master_id.rand + ); + } + + if (peer_dist.get_identity()) { + handler->on_keys_distributed_irk( + connection, + irk_t(pairing_cb->peer_id_key.id_info.irk) + ); + + advertising_peer_address_type_t + address_type(advertising_peer_address_type_t::PUBLIC_ADDRESS); + + if (pairing_cb->peer_id_key.id_addr_info.addr_type) { + address_type = advertising_peer_address_type_t::RANDOM_ADDRESS; + } + + handler->on_keys_distributed_bdaddr( + connection, + address_type, + ble::address_t(pairing_cb->peer_id_key.id_addr_info.addr) + ); + } + + if (peer_dist.get_signing()) { + handler->on_keys_distributed_csrk( + connection, + pairing_cb->peer_sign_key.csrk + ); + } + + self.release_pairing_cb(pairing_cb); + handler->on_pairing_completed(connection); + break; + } + + case BLE_GAP_SEC_STATUS_TIMEOUT: + self.release_pairing_cb(pairing_cb); + handler->on_pairing_timed_out(connection); + break; + + case BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED: + case BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE: + case BLE_GAP_SEC_STATUS_AUTH_REQ: + case BLE_GAP_SEC_STATUS_CONFIRM_VALUE: + case BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP: + case BLE_GAP_SEC_STATUS_ENC_KEY_SIZE: + case BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED: + case BLE_GAP_SEC_STATUS_UNSPECIFIED: + case BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS: + case BLE_GAP_SEC_STATUS_INVALID_PARAMS: + case BLE_GAP_SEC_STATUS_DHKEY_FAILURE: + case BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE: + case BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG: + case BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED: + self.release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + (pairing_failure_t::type) (status.auth_status & 0xF) + ); + break; + + default: + self.release_pairing_cb(pairing_cb); + break; + } + + return true; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { + const ble_gap_evt_conn_sec_update_t& req = + gap_evt.params.conn_sec_update; + + if((req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2)) { + handler->on_link_encryption_result( + connection, link_encryption_t::ENCRYPTED + ); + } else { + handler->on_link_encryption_result( + connection, link_encryption_t::NOT_ENCRYPTED + ); + } + return true; + } + + case BLE_GAP_EVT_TIMEOUT: { + switch (gap_evt.params.timeout.src) { + case BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST: + // Note: pairing_cb does not exist at this point; it is + // created when the module receive the pairing request. + handler->on_link_encryption_request_timed_out(connection); + return true; + + // FIXME: enable with latest SDK +#if 0 + case BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD: + handler->on_valid_mic_timeout(connection); + return true; +#endif + default: + return false; + } + return false; + } + + case BLE_GAP_EVT_SEC_REQUEST: { + const ble_gap_evt_sec_request_t& req = gap_evt.params.sec_request; + handler->on_slave_security_request( + connection, + AuthenticationMask(req.bond, req.mitm, req.lesc, req.keypress) + ); + return true; + } + + default: + return false; + } +} + +ble_gap_sec_params_t nRF5xSecurityManager::make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + ble_gap_sec_params_t security_params = { + /* bond */ authentication_requirements.get_bondable(), + /* mitm */ authentication_requirements.get_mitm(), + /* lesc */ authentication_requirements.get_secure_connections(), + /* keypress */ authentication_requirements.get_keypress_notification(), + /* io_caps */ _io_capability.value(), + /* oob */ oob_data_flag, + /* min_key_size */ _min_encryption_key_size, + /* max_key_size */ _max_encryption_key_size, + /* kdist_periph */ { + /* enc */ responder_dist.get_encryption(), + /* id */ responder_dist.get_identity(), + /* sign */ responder_dist.get_signing(), + /* link */ responder_dist.get_link() + }, + /* kdist_central */ { + /* enc */ initiator_dist.get_encryption(), + /* id */ initiator_dist.get_identity(), + /* sign */ initiator_dist.get_signing(), + /* link */ initiator_dist.get_link() + } + }; + return security_params; +} + +ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_cb.initiator_dist = initiator_dist; + pairing_cb.responder_dist = responder_dist; + + KeyDistribution* own_dist = NULL; + KeyDistribution* peer_dist = NULL; + + if (pairing_cb.role == PAIRING_INITIATOR) { + own_dist = &initiator_dist; + peer_dist = &responder_dist; + } else { + own_dist = &responder_dist; + peer_dist = &initiator_dist; + } + + ble_gap_sec_keyset_t keyset = { + /* keys_own */ { + own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL, + own_dist->get_identity() ? &pairing_cb.own_id_key : NULL, + own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL, + &pairing_cb.own_pk + }, + /* keys_peer */ { + peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL, + peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL, + peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL, + &pairing_cb.peer_pk + } + }; + + // copy csrk if necessary + if (keyset.keys_own.p_sign_key) { + memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size()); + } + + // copy public keys used +#if defined(MBEDTLS_ECDH_C) + memcpy(pairing_cb.own_pk.pk, X.data(), X.size()); + memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size()); +#endif + return keyset; +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::allocate_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pairing_cb = + new (std::nothrow) pairing_control_block_t(); + if (pairing_cb) { + pairing_cb->next = _control_blocks; + _control_blocks = pairing_cb; + } + return pairing_cb; +} + +void nRF5xSecurityManager::release_pairing_cb(pairing_control_block_t* pairing_cb) +{ + if (pairing_cb == _control_blocks) { + _control_blocks = _control_blocks->next; + delete pairing_cb; + } else { + pairing_control_block_t* it = _control_blocks; + while (it->next) { + if (it->next == pairing_cb) { + it->next = pairing_cb->next; + delete pairing_cb; + return; + } + it = it->next; + } + } +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pcb = _control_blocks; + while (pcb) { + if (pcb->connection == connection) { + return pcb; + } + pcb = pcb->next; + } + + return NULL; +} + +void nRF5xSecurityManager::release_all_pairing_cb() +{ + while(_control_blocks) { + release_pairing_cb(_control_blocks); + } +} + +} // nordic +} // vendor +} // pal +} // ble + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.h new file mode 100644 index 0000000000..46482fcee4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.h @@ -0,0 +1,408 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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. + */ + +#ifndef NRF5X_PAL_SECURITY_MANAGER_ +#define NRF5X_PAL_SECURITY_MANAGER_ + +#include "ble/BLETypes.h" +#include "ble/pal/PalSecurityManager.h" +#include "nrf_ble.h" +#include "nRF5xCrypto.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +class nRF5xSecurityManager : public ::ble::pal::SecurityManager { +public: + nRF5xSecurityManager(); + + virtual ~nRF5xSecurityManager(); + + //////////////////////////////////////////////////////////////////////////// + // SM lifecycle management + // + + /** + * @see ::ble::pal::SecurityManager::initialize + */ + virtual ble_error_t initialize(); + + /** + * @see ::ble::pal::SecurityManager::terminate + */ + virtual ble_error_t terminate(); + + /** + * @see ::ble::pal::SecurityManager::reset + */ + virtual ble_error_t reset() ; + + //////////////////////////////////////////////////////////////////////////// + // Resolving list management + // + + /** + * @see ::ble::pal::SecurityManager::read_resolving_list_capacity + */ + virtual uint8_t read_resolving_list_capacity(); + + /** + * @see ::ble::pal::SecurityManager::add_device_to_resolving_list + */ + virtual ble_error_t add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ); + + /** + * @see ::ble::pal::SecurityManager::remove_device_from_resolving_list + */ + virtual ble_error_t remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ); + + /** + * @see ::ble::pal::SecurityManager::clear_resolving_list + */ + virtual ble_error_t clear_resolving_list(); + + /** + * An entry of the resolving list stored in the SecurityManager. + */ + struct resolving_list_entry_t { + resolving_list_entry_t() : + peer_identity_address_type( + advertising_peer_address_type_t::PUBLIC_ADDRESS + ) + { } + + irk_t peer_irk; + address_t peer_identity_address; + advertising_peer_address_type_t peer_identity_address_type; + }; + + /** + * Return the IRKs present in the resolving list + * @param count The number of entries present in the resolving list. + * @param pointer to the first entry of the resolving list. + */ + ArrayView get_resolving_list(); + + /** + * Try to resolve a private resolvable address. + * + * @param resolvable_address The address to resolve. + * + * @return Pointer to the entry found if any. + */ + const resolving_list_entry_t* resolve_address( + const address_t& resolvable_address + ); + + + //////////////////////////////////////////////////////////////////////////// + // Pairing + // + + /** + * @see ::ble::pal::SecurityManager::send_pairing_request + */ + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + + /** + * @see ::ble::pal::SecurityManager::get_secure_connections_support + */ + virtual ble_error_t get_secure_connections_support( + bool &enabled + ); + + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + + //////////////////////////////////////////////////////////////////////////// + // Security settings + // + + /** + * @see ::ble::pal::SecurityManager::set_authentication_timeout + */ + virtual ble_error_t set_authentication_timeout( + connection_handle_t, uint16_t timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::get_authentication_timeout + */ + virtual ble_error_t get_authentication_timeout( + connection_handle_t, uint16_t &timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ + virtual ble_error_t slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication + ); + + //////////////////////////////////////////////////////////////////////////// + // Encryption + // + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm + ); + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm + ) ; + + /** + * @see ::ble::pal::SecurityManager::encrypt_data + */ + virtual ble_error_t encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data + ); + + //////////////////////////////////////////////////////////////////////////// + // Privacy + // + + /** + * @see ::ble::pal::SecurityManager::set_private_address_timeout + */ + virtual ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds); + + //////////////////////////////////////////////////////////////////////////// + // Keys + // + + /** + * @see ::ble::pal::SecurityManager::set_ltk + */ + virtual ble_error_t set_ltk( + connection_handle_t connection, + const ltk_t <k, + bool mitm, + bool secure_connections + ); + + /** + * @see ::ble::pal::SecurityManager::set_ltk_not_found + */ + virtual ble_error_t set_ltk_not_found( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::set_irk + */ + virtual ble_error_t set_irk(const irk_t &irk); + + /** + * @see ::ble::pal::SecurityManager::set_csrk + */ + virtual ble_error_t set_csrk(const csrk_t &csrk, sign_count_t sign_counter); + + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ); + + /** + * @see ::ble::pal::SecurityManager::remove_peer_csrk + */ + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); + + + //////////////////////////////////////////////////////////////////////////// + // Authentication + // + + /** + * @see ::ble::pal::SecurityManager::get_random_data + */ + virtual ble_error_t get_random_data(byte_array_t<8> &random_data); + + //////////////////////////////////////////////////////////////////////////// + // MITM + // + + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + + /** + * @see ::ble::pal::SecurityManager::passkey_request_reply + */ + virtual ble_error_t passkey_request_reply( + connection_handle_t connection, + passkey_num_t passkey + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + + /** + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply + */ + virtual ble_error_t legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t &oob_data + ); + + /** + * @see ::ble::pal::SecurityManager::confirmation_entered + */ + virtual ble_error_t confirmation_entered( + connection_handle_t connection, bool confirmation + ); + + /** + * @see ::ble::pal::SecurityManager::send_keypress_notification + */ + virtual ble_error_t send_keypress_notification( + connection_handle_t connection, Keypress_t keypress + ); + + /** + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob + */ + virtual ble_error_t generate_secure_connections_oob(); + + // singleton of nordic Security Manager + static nRF5xSecurityManager& get_security_manager(); + + // Event handler + bool sm_handler(const ble_evt_t *evt); + +private: + csrk_t _csrk; + sign_count_t _sign_counter; + io_capability_t _io_capability; + uint8_t _min_encryption_key_size; + uint8_t _max_encryption_key_size; + + struct pairing_control_block_t; + + ble_gap_sec_params_t make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + ble_gap_sec_keyset_t make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection); + void release_pairing_cb(pairing_control_block_t* pairing_cb); + pairing_control_block_t* get_pairing_cb(connection_handle_t connection); + void release_all_pairing_cb(); + + pairing_control_block_t* _control_blocks; +#if defined(MBEDTLS_ECDH_C) + CryptoToolbox _crypto; + ble::public_key_coord_t X; + ble::public_key_coord_t Y; + ble::public_key_coord_t secret; +#endif + + static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_WHITELIST_IRK_MAX_COUNT; + + size_t resolving_list_entry_count; + resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif /* NRF5X_PAL_SECURITY_MANAGER_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xSecurityManager.h deleted file mode 100644 index 0e901b5701..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xSecurityManager.h +++ /dev/null @@ -1,194 +0,0 @@ -/* 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 __NRF51822_SECURITY_MANAGER_H__ -#define __NRF51822_SECURITY_MANAGER_H__ - -#include - -#include "nRF5xGap.h" -#include "ble/SecurityManager.h" -#include "btle_security.h" - -class nRF5xSecurityManager : public SecurityManager -{ -public: - /* Functions that must be implemented from SecurityManager */ - virtual ble_error_t init(bool enableBonding, - bool requireMITM, - SecurityIOCapabilities_t iocaps, - const Passkey_t passkey) { - return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); - } - - virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { - return btle_getLinkSecurity(connectionHandle, securityStatusP); - } - - virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) { - return btle_setLinkSecurity(connectionHandle, securityMode); - } - - virtual ble_error_t purgeAllBondingState(void) { - return btle_purgeAllBondingState(); - } -#if (NRF_SD_BLE_API_VERSION <= 2) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - uint8_t i; - - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - /* Initialize the structure so that we get as many addreses as the whitelist can hold */ - whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_addrs = addressPtr; - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - addresses.size = 0; - return error; - } - - /* Put all the addresses in the structure */ - for (i = 0; i < whitelistFromBondTable.addr_count; ++i) { - if (i >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size = i; - return BLE_ERROR_NONE; - } - memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t)); - } - - /* Update the current address count */ - addresses.size = i; - - /* The assumption here is that the underlying implementation of - * createWhitelistFromBondTable() will not return the private resolvable - * addresses (which is the case in the SoftDevice). Rather it returns the - * IRKs, so we need to generate the private resolvable address by ourselves. - */ - for (i = 0; i < whitelistFromBondTable.irk_count; ++i) { - if (i + addresses.size >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size += i; - return BLE_ERROR_NONE; - } - btle_generateResolvableAddress( - *whitelistFromBondTable.pp_irks[i], - (ble_gap_addr_t &) addresses.addresses[i + addresses.size] - ); - } - - /* Update the current address count */ - addresses.size += i; - - return BLE_ERROR_NONE; - } -#else // -> NRF_SD_BLE_API_VERSION >= 3 - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - return btle_getAddressesFromBondTable(addresses); - } -#endif // #if (NRF_SD_BLE_API_VERSION <= 2) - - - - /** - * @brief Clear nRF5xSecurityManager's state. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t reset(void) - { - if (SecurityManager::reset() != BLE_ERROR_NONE) { - return BLE_ERROR_INVALID_STATE; - } - - return BLE_ERROR_NONE; - } - - bool hasInitialized(void) const { - return btle_hasInitializedSecurity(); - } - -public: - /* - * Allow instantiation from nRF5xn when required. - */ - friend class nRF5xn; - - nRF5xSecurityManager() { - /* empty */ - } - -private: - nRF5xSecurityManager(const nRF5xSecurityManager &); - const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &); - -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * Expose an interface that allows us to query the SoftDevice bond table - * and extract a whitelist. - */ - ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const { - return btle_createWhitelistFromBondTable(&whitelistFromBondTable); - } -#endif - /* - * Given a BLE address and a IRK this function check whether the address - * can be generated from the IRK. To do so, this function uses the hash - * function and algorithm described in the Bluetooth low Energy - * Specification. Internally, Nordic SDK functions are used. - */ - bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const { - return btle_matchAddressAndIrk(address, irk); - } - - /* - * Give nRF5xGap access to createWhitelistFromBondTable() and - * matchAddressAndIrk() - */ - friend class nRF5xGap; -}; - -#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.cpp index 111bfc1bb0..0b2eda1f80 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.cpp @@ -31,7 +31,7 @@ extern "C" { #include "softdevice_handler.h" } -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" /** * The singleton which represents the nRF51822 transport for the BLE. @@ -62,8 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())), - securityManagerInstance(NULL) + gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())) { } @@ -126,7 +125,7 @@ ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContex return BLE_ERROR_ALREADY_INITIALIZED; } - instanceID = instanceID; + this->instanceID = instanceID; /* ToDo: Clear memory contents, reset the SD, etc. */ if (btle_init() != ERROR_NONE) { @@ -171,7 +170,6 @@ ble_error_t nRF5xn::shutdown(void) return BLE_STACK_BUSY; } - /* Shutdown the BLE API and nRF51 glue code */ ble_error_t error; @@ -182,13 +180,6 @@ ble_error_t nRF5xn::shutdown(void) } } - if (securityManagerInstance != NULL) { - error = securityManagerInstance->reset(); - if (error != BLE_ERROR_NONE) { - return error; - } - } - /* S110 does not support BLE client features, nothing to reset. */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) error = getGattClient().reset(); @@ -209,6 +200,29 @@ ble_error_t nRF5xn::shutdown(void) return BLE_ERROR_NONE; } +SecurityManager& nRF5xn::getSecurityManager() +{ + const nRF5xn* self = this; + return const_cast(self->getSecurityManager()); +} + +const SecurityManager& nRF5xn::getSecurityManager() const +{ + ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal = + ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager(); + static struct : ble::pal::SigningEventMonitor { + virtual void set_signing_event_handler(EventHandler *signing_event_handler) { } + } dummy_signing_event_monitor; + + static ble::generic::GenericSecurityManager m_instance( + m_pal, + const_cast(getGap()), + dummy_signing_event_monitor + ); + + return m_instance; +} + void nRF5xn::waitForEvent(void) { @@ -217,8 +231,12 @@ nRF5xn::waitForEvent(void) } void nRF5xn::processEvents() { + core_util_critical_section_enter(); if (isEventsSignaled) { isEventsSignaled = false; + core_util_critical_section_exit(); intern_softdevice_events_execute(); + } else { + core_util_critical_section_exit(); } } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h index 154b9e49dc..8829d72347 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h @@ -21,10 +21,13 @@ #include "ble/blecommon.h" #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" +#include "ble/generic/GenericSecurityManager.h" +#include "ble/pal/SimpleEventQueue.h" +#include "nRF5xPalSecurityManager.h" + #include "nRF5xGap.h" #include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" #include "btle.h" @@ -82,18 +85,14 @@ public: } /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A reference to GattServer. + * @see BLEInstanceBase::getSecurityManager */ - virtual nRF5xSecurityManager &getSecurityManager() { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; /** * Accessors to GAP. This function checks whether gapInstance points to an @@ -130,23 +129,6 @@ public: return *gattServerInstance; }; - /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A const reference to GattServer. - * - * @note The accessor is able to modify the object's state because the - * internal pointer has been declared mutable. - */ - virtual const nRF5xSecurityManager &getSecurityManager() const { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } - virtual void waitForEvent(void); virtual void processEvents(); @@ -170,10 +152,7 @@ private: * it can be assigned inside a 'const' function. */ ble::generic::GenericGattClient gattClient; - mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance. - * If NULL, then SecurityManager has not been initialized. - * The pointer has been declared as 'mutable' so that - * it can be assigned inside a 'const' function. */ + }; #endif 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 5d6def57ac..09091c8326 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 @@ -21,24 +21,12 @@ #include "btle_clock.h" #include "ble_flash.h" -#include "ble_conn_params.h" -#include "btle_gap.h" #include "custom/custom_helper.h" #include "ble/GapEvents.h" #include "nRF5xn.h" -// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work -#undef STATIC_ASSERT_SIMPLE -#undef STATIC_ASSERT_MSG - -// FIXME : We can't use mbed_assert.h because we're using these macros within functions -#define STATIC_ASSERT_MSG(EXPR, MSG) -#define STATIC_ASSERT_SIMPLE(EXPR) - -#warning FIXME : We can't use mbed_assert.h because we're using these within functions - #ifdef S110 #define IS_LEGACY_DEVICE_MANAGER_ENABLED 1 #elif defined(S130) || defined(S132) @@ -52,8 +40,6 @@ extern "C" { #else #include "nrf_fstorage.h" #include "fds.h" - #include "peer_manager.h" - #include "ble_conn_state.h" #endif #include "nrf_sdh.h" @@ -62,7 +48,17 @@ extern "C" { #include "headers/ble_hci.h" -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" + +// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work +#undef STATIC_ASSERT_SIMPLE +#undef STATIC_ASSERT_MSG + +// FIXME : We can't use mbed_assert.h because we're using these macros within functions +#define STATIC_ASSERT_MSG(EXPR, MSG) +#define STATIC_ASSERT_SIMPLE(EXPR) + +#warning FIXME : We can't use mbed_assert.h because we're using these within functions // Make this volatile at it will be set in interrupt context @@ -76,9 +72,9 @@ void app_error_handler(uint32_t error_code, uint32_t line_num, const extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector. #if NRF_SDK14PLUS_EVENT_HANDLERS -static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); +void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); #else -static void btle_handler(ble_evt_t *p_ble_evt); +void btle_handler(ble_evt_t *p_ble_evt); #endif #if !NRF_SDK14PLUS_EVENT_HANDLERS @@ -232,9 +228,6 @@ error_t btle_init(void) } #endif - // Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp) - pm_init(); - #if (NRF_SD_BLE_API_VERSION <= 2) ble_gap_addr_t addr; if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) { @@ -243,10 +236,6 @@ error_t btle_init(void) if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) { return ERROR_INVALID_PARAM; } -#else - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - pm_privacy_set(&privacy_params); #endif // From SDK 14 onwards event handlers are registered differently @@ -259,19 +248,20 @@ error_t btle_init(void) ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch)); #endif - return btle_gap_init(); + return ERROR_NONE; } #if NRF_SDK14PLUS_EVENT_HANDLERS -static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context) +void btle_handler(const ble_evt_t *p_ble_evt, void *p_context) #else -static void btle_handler(ble_evt_t *p_ble_evt) +void btle_handler(const ble_evt_t *p_ble_evt) #endif { #if NRF_SDK14PLUS_EVENT_HANDLERS (void)p_context; // Keep compiler happy #endif - using ble::pal::vendor::nordic::nRF5XGattClient; + using ble::pal::vendor::nordic::nRF5xGattClient; + using ble::pal::vendor::nordic::nRF5xSecurityManager; // In SDK14+, all other modules from the SDK will be registered independently as softdevice events observers #if !NRF_SDK14PLUS_EVENT_HANDLERS @@ -286,55 +276,26 @@ static void btle_handler(ble_evt_t *p_ble_evt) // Forward BLE events to the Connection State module. // This must be called before any event handler that uses this module. ble_conn_state_on_ble_evt(p_ble_evt); - - // Forward BLE events to the Peer Manager - pm_on_ble_evt(p_ble_evt); #endif #endif #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) - nRF5XGattClient::handle_events(p_ble_evt); + nRF5xGattClient::handle_events(p_ble_evt); #endif nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); nRF5xGap &gap = (nRF5xGap &) ble.getGap(); nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer(); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager(); /* Custom event handler */ switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; -#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110) - /* Only peripheral role is supported by S110 */ - Gap::Role_t role = Gap::PERIPHERAL; -#else - Gap::Role_t role = static_cast(p_ble_evt->evt.gap_evt.params.connected.role); -#endif - gap.setConnectionHandle(handle); - const Gap::ConnectionParams_t *params = reinterpret_cast(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); - const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; -#if (NRF_SD_BLE_API_VERSION <= 2) - const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - static_cast(own->addr_type), own->addr, - params); -#else - Gap::AddressType_t addr_type; - Gap::Address_t own_address; - gap.getAddress(&addr_type, own_address); - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - addr_type, own_address, - params); -#endif + case BLE_GAP_EVT_CONNECTED: + gap.on_connection( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.connected + ); break; - } case BLE_GAP_EVT_DISCONNECTED: { Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; @@ -362,7 +323,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) // Close all pending discoveries for this connection - nRF5XGattClient::handle_connection_termination(handle); + nRF5xGattClient::handle_connection_termination(handle); #endif gap.processDisconnectionEvent(handle, reason); @@ -416,10 +377,6 @@ static void btle_handler(ble_evt_t *p_ble_evt) } #endif - case BLE_GAP_EVT_PASSKEY_DISPLAY: - securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); - break; - case BLE_GAP_EVT_TIMEOUT: gap.processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); break; @@ -431,21 +388,17 @@ static void btle_handler(ble_evt_t *p_ble_evt) // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; - case BLE_GAP_EVT_ADV_REPORT: { - const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - gap.processAdvertisementReport(advReport->peer_addr.addr, - advReport->rssi, - advReport->scan_rsp, - static_cast(advReport->type), - advReport->dlen, - advReport->data); + case BLE_GAP_EVT_ADV_REPORT: + gap.on_advertising_packet(p_ble_evt->evt.gap_evt.params.adv_report); break; - } default: break; } + // Process security manager events + securityManager.sm_handler(p_ble_evt); + gattServer.hwCallback(p_ble_evt); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.h index 9b75ed1714..4c35282d8a 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle.h @@ -23,7 +23,6 @@ extern "C" { #include "common/common.h" -#include "ble_srv_common.h" #include "headers/nrf_ble.h" #if NRF_SD_BLE_API_VERSION >= 5 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.cpp deleted file mode 100644 index 085fb1e08e..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* 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. - */ -#include "common/common.h" - -#include "headers/ble_gap.h" -#include "ble_conn_params.h" - -static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST; -#if SDK_CONN_PARAMS_MODULE_ENABLE -static void error_callback(uint32_t nrf_error); -#endif // SDK_CONN_PARAMS_MODULE_ENABLE - -/**************************************************************************/ -/*! - @brief Initialise GAP in the underlying SoftDevice - - @returns -*/ -/**************************************************************************/ -error_t btle_gap_init(void) -{ - ble_gap_conn_params_t gap_conn_params = {0}; - - gap_conn_params.min_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MIN_INTERVAL_MS); // in 1.25ms units - gap_conn_params.max_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MAX_INTERVAL_MS); // in 1.25ms unit - gap_conn_params.slave_latency = CFG_GAP_CONNECTION_SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS / 10; // in 10ms unit - - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed - - ASSERT_STATUS( sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) CFG_GAP_LOCAL_NAME, strlen(CFG_GAP_LOCAL_NAME))); - ASSERT_STATUS( sd_ble_gap_appearance_set(CFG_GAP_APPEARANCE)); - ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params)); - ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL)); - - /** - * Call to conn_params_init() is not necessary; and so is disabled by default. - * This API should be exposed to the user to be invoked when necessary. - */ -#if SDK_CONN_PARAMS_MODULE_ENABLE - /* Connection Parameters */ - enum { - FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER), - NEXT_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER), - MAX_UPDATE_COUNT = 3 - }; - - ble_conn_params_init_t cp_init = {0}; - - cp_init.p_conn_params = NULL; - cp_init.first_conn_params_update_delay = FIRST_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = true; - cp_init.evt_handler = NULL; - cp_init.error_handler = error_callback; - - ASSERT_STATUS ( ble_conn_params_init(&cp_init)); -#endif // SDK_CONN_PARAMS_MODULE_ENABLE - - return ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Converts msecs to an integer representing 1.25ms units - - @param[in] ms - The number of milliseconds to conver to 1.25ms units - - @returns The number of 1.25ms units in the supplied number of ms -*/ -/**************************************************************************/ -static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) -{ - return (interval_ms * 4) / 5; -} - -#if SDK_CONN_PARAMS_MODULE_ENABLE -static void error_callback(uint32_t nrf_error) -{ - ASSERT_STATUS_RET_VOID( nrf_error ); -} -#endif // SDK_CONN_PARAMS_MODULE_ENABLE diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.h deleted file mode 100644 index 828da3cd78..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_gap.h +++ /dev/null @@ -1,24 +0,0 @@ -/* 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 _BTLE_GAP_H_ -#define _BTLE_GAP_H_ - -#include "common/common.h" - -error_t btle_gap_init(void); - -#endif // ifndef _BTLE_GAP_H_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.cpp deleted file mode 100644 index 389c9b5c4c..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* 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. - */ -#if defined(S110) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "pstorage.h" -#include "device_manager.h" -#include "id_manager.h" -} - -#include "btle_security.h" - -static dm_application_instance_t applicationInstance; -static bool initialized = false; -static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result); - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 1, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - if (pstorage_init() != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - dm_init_param_t dm_init_param = { - .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */ - }; - if (dm_init(&dm_init_param) != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - const dm_application_param_t dm_param = { - .evt_handler = dm_handler, - .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID, - .sec_param = securityParameters - }; - - if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - dm_handle_t dmHandle = { - .appl_id = applicationInstance, - }; - if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) { - if (rc == NRF_ERROR_NOT_FOUND) { - return BLE_ERROR_INVALID_PARAM; - } else { - return BLE_ERROR_UNSPECIFIED; - } - } - - if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast(securityStatusP))) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ble_gap_sec_params_t params = securityParameters; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - uint32_t result = sd_ble_gap_authenticate(connectionHandle, ¶ms); - - if (result == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_UNSPECIFIED; - } -} - -ret_code_t -dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - - switch (p_event->event_id) { - case DM_EVT_SECURITY_SETUP: /* started */ { - const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - break; - } - case DM_EVT_SECURITY_SETUP_COMPLETE: - securityManager. - processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, - (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); - break; - case DM_EVT_LINK_SECURED: { - unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm; - unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv; - SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - switch (securityMode) { - case 1: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); - break; - } - case DM_EVT_DEVICE_CONTEXT_STORED: - securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); - break; - default: - break; - } - - return NRF_SUCCESS; -} - -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} - - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} -#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.h deleted file mode 100644 index a1354a36ee..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security.h +++ /dev/null @@ -1,146 +0,0 @@ -/* 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 _BTLE_SECURITY_H_ -#define _BTLE_SECURITY_H_ - -#include "ble/Gap.h" -#include "ble/SecurityManager.h" - -/** - * Function to test whether the SecurityManager has been initialized. - * Possible by a call to @ref btle_initializeSecurity(). - * - * @return True if the SecurityManager was previously initialized, false - * otherwise. - */ -bool btle_hasInitializedSecurity(void); - -/** - * Enable Nordic's Device Manager, which brings in functionality from the - * stack's Security Manager. The Security Manager implements the actual - * cryptographic algorithms and protocol exchanges that allow two devices to - * securely exchange data and privately detect each other. - * - * @param[in] enableBonding Allow for bonding. - * @param[in] requireMITM Require protection for man-in-the-middle attacks. - * @param[in] iocaps To specify IO capabilities of this peripheral, - * such as availability of a display or keyboard to - * support out-of-band exchanges of security data. - * @param[in] passkey To specify a static passkey. - * - * @return BLE_ERROR_NONE on success. - */ -ble_error_t btle_initializeSecurity(bool enableBonding = true, - bool requireMITM = true, - SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE, - const SecurityManager::Passkey_t passkey = NULL); - -/** - * Get the security status of a link. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[out] securityStatusP - * security status. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP); - -/** - * Set the security mode on a connection. Useful for elevating the security mode - * once certain conditions are met, e.g., a particular service is found. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[in] securityMode - * security mode. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode); - -/** - * Function for deleting all peer device context and all related bonding - * information from the database. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. - * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or - * application registration. - */ -ble_error_t btle_purgeAllBondingState(void); - -#if (NRF_SD_BLE_API_VERSION <= 2) -/** - * Query the SoftDevice bond table to extract a whitelist containing the BLE - * addresses and IRKs of bonded devices. - * - * @param[in/out] p_whitelist - * (on input) p_whitelist->addr_count and - * p_whitelist->irk_count specify the maximum number of - * addresses and IRKs added to the whitelist structure. - * (on output) *p_whitelist is a whitelist containing the - * addresses and IRKs of the bonded devices. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist); -#endif - -/** - * Function to test whether a BLE address is generated using an IRK. - * - * @param[in] p_addr - * Pointer to a BLE address. - * @param[in] p_irk - * Pointer to an IRK. - * - * @return True if p_addr can be generated using p_irk, false otherwise. - */ -bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - -/** - * Function to generate a private resolvable BLE address. - * - * @param[out] p_addr - * The output address. - * @param[in] p_irk - * A reference to a IRK. - * - * @note This function does not generate a secure address since the prand number in the - * resolvable address is not truly random. Therefore, the output of this function - * is only meant to be used by the application internally but never exported. - */ -void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address); - -#if (NRF_SD_BLE_API_VERSION >= 3) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList); -#endif - -#endif /* _BTLE_SECURITY_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security_pm.cpp deleted file mode 100644 index cdc5eba3d9..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/btle_security_pm.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* 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. - */ - -#if defined(S130) || defined(S132) || defined(S140) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "peer_manager.h" -#include "id_manager.h" -#include "fds.h" -} - -#include "btle_security.h" - -extern "C" void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash); - -static bool initialized = false; - -static void pm_handler(pm_evt_t const *p_event); -static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing. -volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API. - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - if (enableBonding) { - securityParameters.kdist_own.enc = 1; - securityParameters.kdist_own.id = 1; - } else { - securityParameters.kdist_own.enc = 0; - securityParameters.kdist_own.id = 0; - } - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_register(pm_handler); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } - - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - - async_ret_code = NRF_ERROR_BUSY; - - rc = pm_peers_delete(); // it is asynhronous API - - if (rc == NRF_SUCCESS) - { - // waiting for respond from pm_handler - while (async_ret_code == NRF_ERROR_BUSY) { - // busy-loop - } - - rc = async_ret_code; - } - - switch (rc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - pm_conn_sec_status_t conn_sec_status; - - rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status); - - if (rc == NRF_SUCCESS) - { - if (conn_sec_status.encrypted) { - *securityStatusP = SecurityManager::ENCRYPTED; - } - else if (conn_sec_status.connected) { - if (_enc_in_progress) { - *securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS; - } - else { - *securityStatusP = SecurityManager::NOT_ENCRYPTED; - } - } - - return BLE_ERROR_NONE; - } - - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - return BLE_ERROR_INVALID_PARAM; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ret_code_t rc; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 0; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 1; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_conn_secure(connectionHandle, false); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - - -void pm_handler(pm_evt_t const *p_event) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - ret_code_t err_code; - SecurityManager::SecurityMode_t resolvedSecurityMode; - - switch (p_event->evt_id) { - case PM_EVT_CONN_SEC_START: /* started */ { - const ble_gap_sec_params_t *peerParams = &securityParameters; - securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - _enc_in_progress = true; - break; - } - case PM_EVT_CONN_SEC_SUCCEEDED: - // Update the rank of the peer. - if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) - { - err_code = pm_peer_rank_highest(p_event->peer_id); - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, - SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t - - ble_gap_conn_sec_t conn_sec; - sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec); - - resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - - switch (conn_sec.sec_mode.sm) { - case 1: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode); - - _enc_in_progress = false; - break; - - case PM_EVT_CONN_SEC_FAILED: - SecurityManager::SecurityCompletionStatus_t securityCompletionStatus; - - if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) { - securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED; - } else { - securityCompletionStatus = - (SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error; - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus); - - _enc_in_progress = false; - break; - - case PM_EVT_BONDED_PEER_CONNECTED: - pm_peer_rank_highest(p_event->peer_id); - break; - - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - securityManager.processSecurityContextStoredEvent(p_event->conn_handle); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - break; - - case PM_EVT_PEERS_DELETE_SUCCEEDED: - async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_PEERS_DELETE_FAILED: - async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_STORAGE_FULL: - // Run garbage collection on the flash. - err_code = fds_gc(); - if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) - { - // Retry. - } - else - { - APP_ERROR_CHECK(err_code); - } - break;//PM_EVT_STORAGE_FULL - - case PM_EVT_CONN_SEC_CONFIG_REQ:{ - // A connected peer (central) is trying to pair, but the Peer Manager already has a bond - // for that peer. Setting allow_repairing to false rejects the pairing request. - // If this event is ignored (pm_conn_sec_config_reply is not called in the event - // handler), the Peer Manager assumes allow_repairing to be false. - pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; - pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config); - } - break;//PM_EVT_CONN_SEC_CONFIG_REQ - - default: - break; - } -} - -#if (NRF_SD_BLE_API_VERSION <= 2) -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} -#endif - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} - - -#if (NRF_SD_BLE_API_VERSION >= 3) -ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) -{ - pm_peer_id_t peer_id; - ret_code_t ret; - pm_peer_data_bonding_t bond_data; - - addrList.size = 0; - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - /** - * Fill addresses list: - * Copy addresses from bond table, or - * for every private resolvable address in the bond table generate the resolvable address. - */ - while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - btle_generateResolvableAddress(bond_data.peer_ble_id.id_info, - (ble_gap_addr_t &) addrList.addresses[addrList.size].address); - } else { - memcpy(&addrList.addresses[addrList.size].address, - &bond_data.peer_ble_id.id_addr_info.addr, - sizeof(addrList.addresses[0].address)); - } - - addrList.addresses[addrList.size].type = static_cast (bond_data.peer_ble_id.id_addr_info.addr_type); - - addrList.size++; - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - return BLE_ERROR_NONE; -} -#endif - -#endif // defined(S130) || defined(S132) || defined(S140) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.cpp index ea6e63c74c..95be197637 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.cpp @@ -31,6 +31,32 @@ typedef struct { static unsigned uuidTableEntries = 0; /* current usage of the table */ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES]; +namespace { + +static void set_perm(ble_gap_conn_sec_mode_t& dest, GattAttribute::Security_t src) { + switch (src.value()) { + case GattAttribute::Security_t::NONE: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dest); + break; + + case GattAttribute::Security_t::UNAUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dest); + break; + + case GattAttribute::Security_t::AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&dest); + break; + + case GattAttribute::Security_t::SC_AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dest); + break; + + default: + break; + } +} + +} void custom_reset_128bits_uuid_table() { uuidTableEntries = 0; } @@ -204,7 +230,9 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -227,8 +255,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Notification requires cccd */ memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); cccd_md.vloc = BLE_GATTS_VLOC_STACK; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + set_perm(cccd_md.read_perm, GattAttribute::Security_t::NONE); + set_perm(cccd_md.write_perm, update_security); } ble_gatts_char_md_t char_md = {0}; @@ -257,49 +285,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Always set variable size */ attr_md.vlen = has_variable_len; - if (char_props.read || char_props.notify || char_props.indicate) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm); - break; - default: - break; - }; - } - - if (char_props.write || char_props.write_wo_resp) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm); - break; - default: - break; - }; - } + set_perm(attr_md.read_perm, read_security); + set_perm(attr_md.write_perm, write_security); ble_gatts_attr_t attr_char_value = {0}; @@ -343,7 +330,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle) + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security) { /* Descriptor metadata */ ble_gatts_attr_md_t desc_md = {0}; @@ -353,8 +342,8 @@ error_t custom_add_in_descriptor(uint16_t char_handle, desc_md.vlen = has_variable_len; /* Make it readable and writable */ - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); + set_perm(desc_md.read_perm, read_security); + set_perm(desc_md.write_perm, write_security); ble_gatts_attr_t attr_desc = {0}; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.h index 49505c5eec..e5cddc2bd5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/btle/custom/custom_helper.h @@ -42,7 +42,9 @@ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid); error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -61,7 +63,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle); + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security); #ifdef __cplusplus } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.cpp new file mode 100644 index 0000000000..b555b0dc33 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.cpp @@ -0,0 +1,188 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include +#include + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "platform/CriticalSectionLock.h" +#include "ble/BLETypes.h" +#include "cmsis.h" +#include "nRF5xCrypto.h" +#include "platform/mbed_assert.h" +#include "nrf_soc.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +CryptoToolbox::CryptoToolbox() : _initialized(false) { + mbedtls_entropy_init(&_entropy_context); + mbedtls_ecp_group_init(&_group); + int err = mbedtls_ecp_group_load( + &_group, + MBEDTLS_ECP_DP_SECP256R1 + ); + _initialized = err ? false : true; +} + +CryptoToolbox::~CryptoToolbox() { + mbedtls_ecp_group_free(&_group); + mbedtls_entropy_free(&_entropy_context); +} + +bool CryptoToolbox::generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret +) { + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + int err = mbedtls_ecp_gen_keypair( + &_group, + &secret_key, + &public_keys, + mbedtls_entropy_func, + &_entropy_context + ); + + if (!err) { + store_mpi(secret, secret_key); + store_mpi(X, public_keys.X); + store_mpi(Y, public_keys.Y); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + + return err ? false : true; +} + +bool CryptoToolbox::generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret +) { + mbedtls_mpi result; + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&result); + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + load_mpi(secret_key, own_secret); + load_mpi(public_keys.X, peer_X); + load_mpi(public_keys.Y, peer_Y); + mbedtls_mpi_lset( &public_keys.Z, 1 ); + + int err = mbedtls_ecdh_compute_shared( + &_group, + &result, + &public_keys, + &secret_key, + /* rng function; optional */ NULL, + /* rng param */ NULL + ); + + if (!err) { + store_mpi(shared_secret, result); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + mbedtls_mpi_free(&result); + + return err ? false : true; +} + +bool CryptoToolbox::ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash +) { + // Note copy then swap operation can be optimized. + + // Note: the encryption block works in big endian; go figure. + nrf_ecb_hal_data_t ecb_hal_data; + + memcpy(ecb_hal_data.key, irk.data(), irk.size()); + swap_endian(ecb_hal_data.key, sizeof(ecb_hal_data.key)); + + memcpy(ecb_hal_data.cleartext, prand.data(), prand.size()); + memset(ecb_hal_data.cleartext + prand.size(), 0, sizeof(ecb_hal_data.cleartext) - prand.size()); + swap_endian(ecb_hal_data.cleartext, sizeof(ecb_hal_data.cleartext)); + + uint32_t err = sd_ecb_block_encrypt(&ecb_hal_data); + + if (err) { + return false; + } + + swap_endian(ecb_hal_data.ciphertext, sizeof(ecb_hal_data.ciphertext)); + + memcpy(hash.data(), ecb_hal_data.ciphertext, hash.size()); + + return true; +} + + +void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { + ble::public_key_coord_t src_be = src.data(); + swap_endian(src_be.data(), src_be.size()); + mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); +} + +void CryptoToolbox::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { + mbedtls_mpi_write_binary(&src, dest.data(), dest.size()); + swap_endian(dest.data(), dest.size()); +} + +void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { + for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { + std::swap(buf[low], buf[high]); + } +} + +} // nordic +} // vendor +} // pal +} // ble + +#endif //defined(MBEDTLS_ECDH_C) + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.h new file mode 100644 index 0000000000..35c56a875e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xCrypto.h @@ -0,0 +1,146 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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. + */ + +#ifndef NRF5X_CRYPTO_ +#define NRF5X_CRYPTO_ + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +/** + * Toolbox of cryptographic functions used in BLE. + */ +class CryptoToolbox : mbed::NonCopyable { + +public: + /** + * Size of the Key used in lesc crypto operations. + */ + static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; + + /** + * Size of an IRK. + */ + static const ptrdiff_t irk_size_ = irk_t::size_; + + /** + * Size of the hash generated by ah. + */ + static const ptrdiff_t hash_size_ = 3; + + /** + * Size of prand. + */ + static const ptrdiff_t prand_size_ = 3; + + /** + * Create a new CryptoToolbox. + */ + CryptoToolbox(); + + /** + * Destroy a CryptoTioolbox object. + */ + ~CryptoToolbox(); + + /** + * Generate lesc public and private keys. + * @param[out] X The component X of the public key. + * @param[out] Y The component Y of the public key. + * @param[out] secret The secret key. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret + ); + + /** + * Generate a shared secret from a peer public key and a local secret key. + * @param[in] peer_X The component X of the peer public key. + * @param[in] peer_Y The component Y of the peer public key. + * @param[in] own_secret The local secret key. + * @param[out] shared_secret The shared secret generated. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret + ); + + /** + * Execute the function ah. This function can be used to generate private + * resolvable addresses and resolve them. + * + * @note all parameters passed and return by this fucntion are in little + * endian. + * + * @param[in] irk The key used to create hash. + * @param[in] prand The random part from which the hash will be generated. + * @param[out] hash The hash generated. + * + * @return true in case of success and false otherwise. + */ + bool ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash + ); + +private: + void load_mpi(mbedtls_mpi& dest, const ArrayView& src); + + void store_mpi(ArrayView& dest, const mbedtls_mpi& src); + + void swap_endian(uint8_t* buf, size_t len); + + bool _initialized; + mbedtls_entropy_context _entropy_context; + mbedtls_ecp_group _group; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif // defined(MBEDTLS_ECDH_C) + +#endif // NRF5X_CRYPTO_ 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 09f99fb12f..a5053b23f4 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 @@ -23,20 +23,120 @@ #include "ble/BLE.h" #include "common/common.h" -#include "ble_advdata.h" #include "headers/ble_hci.h" +#include "ble/pal/ConnectionEventMonitor.h" +#include "nRF5xPalSecurityManager.h" +#include -#if (NRF_SD_BLE_API_VERSION >= 3) - #include "peer_manager.h" - #include "peer_data_storage.h" +using ble::pal::vendor::nordic::nRF5xSecurityManager; +using ble::ArrayView; +using ble::pal::advertising_peer_address_type_t; +using ble::peer_address_type_t; + +typedef BLEProtocol::AddressType LegacyAddressType; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; + +namespace { + +nRF5xSecurityManager& get_sm() { + return nRF5xSecurityManager::get_security_manager(); +} + +ble_error_t set_private_resolvable_address() { +#if (NRF_SD_BLE_API_VERSION <= 2) + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE }; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); +#else + ble_gap_privacy_params_t privacy_config = { 0 }; + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; + err = sd_ble_gap_privacy_set(&privacy_config); #endif + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; +} +ble_error_t set_private_non_resolvable_address() { +#if (NRF_SD_BLE_API_VERSION <= 2) + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); +#else + ble_gap_privacy_params_t privacy_config = { 0 }; + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE; + err = sd_ble_gap_privacy_set(&privacy_config); +#endif + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; +} + +bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { + switch (params.getAdvertisingType()) { + case GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED: + case GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED: + return true; + default: + return false; + } +} + +bool is_identity_address(peer_address_type_t address_type) { + return address_type == peer_address_type_t::PUBLIC_IDENTITY || + address_type == peer_address_type_t::RANDOM_STATIC_IDENTITY; +} + +peer_address_type_t convert_nordic_address(bool identity, uint8_t address) { + if (identity) { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return peer_address_type_t::PUBLIC_IDENTITY; + } else { + return peer_address_type_t::RANDOM_STATIC_IDENTITY; + } + } else { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return peer_address_type_t::PUBLIC; + } else { + return peer_address_type_t::RANDOM; + } + } +} + +peer_address_type_t convert_identity_address(advertising_peer_address_type_t address) { + if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { + return peer_address_type_t::PUBLIC_IDENTITY; + } else { + return peer_address_type_t::RANDOM_STATIC_IDENTITY; + } +} + +} // namespace void radioNotificationStaticCallback(bool param) { nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); gap.processRadioNotificationEvent(param); } +nRF5xGap::nRF5xGap() : Gap(), + advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), + scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), + whitelistAddressesSize(0), + whitelistAddresses(), + radioNotificationCallbackParam(false), + radioNotificationTimeout(), + _connection_event_handler(NULL), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), + _non_private_address_type(LegacyAddressType::RANDOM_STATIC) +{ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; +} /**************************************************************************/ /*! @brief Sets the advertising parameters and payload for the device @@ -196,7 +296,43 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) } } + if (_privacy_enabled) { + if (_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + } + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } adv_para.p_whitelist = &whitelist; +#else + if (_privacy_enabled) { + bool enable_resolution = + _peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE; + update_identities_list(enable_resolution); + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -250,6 +386,7 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) } } + // FIXME: fill the irk list once addresses are resolved by the softdevice. scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else @@ -265,6 +402,19 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + if (_privacy_enabled) { + bool enable_resolution = + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE; + + update_identities_list(enable_resolution); + + if (_central_privacy_configuration.use_non_resolvable_random_address) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } + if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -307,12 +457,76 @@ ble_error_t nRF5xGap::stopAdvertising(void) return BLE_ERROR_NONE; } -ble_error_t nRF5xGap::connect(const Address_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t *connectionParams, - const GapScanningParams *scanParamsIn) -{ +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + peer_address_type_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + // NOTE: Nordic address type is an closer to LegacyAddressType: resolved + // address are treaded either as PUBLIC or RANDOM STATIC adresses. + // The idea is to get the conversion done here and call the legacy function. + + LegacyAddressType_t legacy_address; + + switch (peerAddrType.value()) { + case peer_address_type_t::PUBLIC: + case peer_address_type_t::PUBLIC_IDENTITY: + legacy_address = LegacyAddressType::PUBLIC; + break; + case peer_address_type_t::RANDOM_STATIC_IDENTITY: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case peer_address_type_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = getRandomAddressType(peerAddr, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + break; + default: + return BLE_ERROR_UNSPECIFIED; + } + } break; + default: + return BLE_ERROR_INVALID_PARAM; + } + + bool identity = + peerAddrType == peer_address_type_t::PUBLIC_IDENTITY || + peerAddrType == peer_address_type_t::RANDOM_STATIC_IDENTITY; + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn, identity); +} + + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + return connect(peerAddr, peerAddrType, connectionParams, scanParamsIn, false); +} + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn, + bool identity +) { ble_gap_addr_t addr; + ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); @@ -352,23 +566,52 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ + if (_privacy_enabled) { + // configure the "whitelist" with the IRK associated with the identity + // address in input. + if (is_identity_address(peerAddrType)) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t i; + for (i = 0; i < entries.size(); ++i) { + const ble::address_t& entry_address = entries[i].peer_identity_address; + + // entry found; fill the whitelist and invalidate addr_ptr + if (memcmp(entry_address.data(), peerAddr, entry_address.size_) == 0) { + whitelist.pp_irks[0] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + whitelist.irk_count = 1; + scanParams.selective = 1; + addr_ptr = NULL; + break; + } + } + + // Occur only if the address in input hasn't been resolved. + if (i == entries.size()) { + return BLE_ERROR_INVALID_PARAM; + } + } + + set_private_resolvable_address(); + } #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ scanParams.use_whitelist = (whitelistAddressesSize) ? 1 : 0; - if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - || (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { - /* If a device is using Resolvable Private Addresses Section 1.3.2.2 (Core spec v4.2 volume 6 part B), - it shall also have an Identity Address that is either a Public or Random Static address type.†- To establish a connection, a static address must be provided by the application to the SoftDevice. - The SoftDevice resolves the address and connects to the right device if it is available. */ - addr.addr_id_peer = 1; - addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; - } else { - addr.addr_id_peer = 0; + if (_privacy_enabled) { + bool enable_resolution = + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE; + + update_identities_list(enable_resolution); + + if (enable_resolution && identity) { + addr.addr_id_peer = 1; + } + + set_private_resolvable_address(); } - + #endif if (scanParamsIn != NULL) { @@ -384,9 +627,9 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } #if NRF_SD_BLE_API_VERSION >= 5 - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams, NRF_CONNECTION_TAG); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams, NRF_CONNECTION_TAG); #else - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams); #endif if (rc == NRF_SUCCESS) { return BLE_ERROR_NONE; @@ -499,7 +742,6 @@ ble_error_t nRF5xGap::reset(void) /* Clear the internal whitelist */ whitelistAddressesSize = 0; - return BLE_ERROR_NONE; } @@ -540,105 +782,78 @@ uint16_t nRF5xGap::getConnectionHandle(void) @endcode */ /**************************************************************************/ -ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) +ble_error_t nRF5xGap::setAddress(LegacyAddressType_t type, const Address_t address) { -#if (NRF_SD_BLE_API_VERSION <= 2) - uint8_t cycle_mode; -#else - ble_gap_privacy_params_t privacy_params = {0}; -#endif + if (type != LegacyAddressType::PUBLIC && + type != LegacyAddressType::RANDOM_STATIC + ) { + return BLE_ERROR_INVALID_PARAM; + } + if (_privacy_enabled) { + return BLE_ERROR_INVALID_STATE; + } ble_gap_addr_t dev_addr; + memcpy(dev_addr.addr, address, ADDR_LEN); + if (type == LegacyAddressType::PUBLIC) { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + } else { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; + } - /* When using Public or Static addresses, the cycle mode must be None. - When using Random Private addresses, the cycle mode must be Auto. - In auto mode, the given address is ignored. - */ - if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) - { - memcpy(dev_addr.addr, address, ADDR_LEN); -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; +#if (NRF_SD_BLE_API_VERSION <= 2) + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr); #else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - dev_addr.addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - } - else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) - { -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; -#else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - privacy_params.private_addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - // address is ignored when in auto mode - } - else - { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - dev_addr.addr_type = type; - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + uint32_t err = sd_ble_gap_addr_set(&dev_addr); #endif - return BLE_ERROR_NONE; + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + default: + return BLE_ERROR_UNSPECIFIED; + } } ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) { - ble_gap_addr_t dev_addr; - ble_gap_irk_t irk = {0}; - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.p_device_irk = &irk; + // FIXME: check if privacy is enabled ? + if (typeP == NULL || address == NULL) { + return BLE_ERROR_INVALID_PARAM; + } + ble_gap_addr_t dev_addr; #if (NRF_SD_BLE_API_VERSION <= 2) if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } #else - // Check privacy mode - if( pm_privacy_get(&privacy_params) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - // If in private mode, the address is generated by softdevice, so return a nulled address with correct type - if( privacy_params.privacy_mode == BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY ) - { - memset(address, 0, ADDR_LEN); - switch( privacy_params.private_addr_type ) - { - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: - *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE; - break; - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE: - default: - *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE; - break; - } - return BLE_ERROR_NONE; - } - - // Otherwise recover public/static address if (sd_ble_gap_addr_get(&dev_addr) != NRF_SUCCESS) { +#endif return BLE_ERROR_PARAM_OUT_OF_RANGE; } -#endif - if (typeP != NULL) { - *typeP = static_cast(dev_addr.addr_type); - } - if (address != NULL) { - memcpy(address, dev_addr.addr, ADDR_LEN); + switch (dev_addr.addr_type) { + case BLE_GAP_ADDR_TYPE_PUBLIC: + *typeP = LegacyAddressType::PUBLIC; + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + *typeP = LegacyAddressType::RANDOM_STATIC; + break; + + default: + return BLE_ERROR_INVALID_STATE; } + + memcpy(address, dev_addr.addr, ADDR_LEN); return BLE_ERROR_NONE; } @@ -770,7 +985,7 @@ ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const uint32_t i; for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { memcpy( &whitelistOut.addresses[i].address, &whitelistAddresses[i].addr, sizeof(whitelistOut.addresses[0].address)); - whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); + whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); } @@ -817,24 +1032,42 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) /* Test for invalid parameters before we change the internal state */ for (uint32_t i = 0; i < whitelistIn.size; ++i) { - if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE || + whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE + ) { /* This is not allowed because it is completely meaningless */ return BLE_ERROR_INVALID_PARAM; } } whitelistAddressesSize = whitelistIn.size; + ble_gap_addr_t* pp_addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; for (uint32_t i = 0; i < whitelistIn.size; ++i) { - memcpy(&whitelistAddresses[i].addr , &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr)); + memcpy(&whitelistAddresses[i].addr, &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr)); whitelistAddresses[i].addr_type = static_cast (whitelistIn.addresses[i].type); + pp_addrs[i] = &whitelistAddresses[i]; } -#if (NRF_SD_BLE_API_VERSION >= 3) - updateWhiteAndIdentityListInStack(); -#endif + ble_gap_addr_t** addresses_list_ptr = (whitelistIn.size == 0) ? NULL : pp_addrs; - return BLE_ERROR_NONE; + uint32_t err = sd_ble_gap_whitelist_set(addresses_list_ptr, whitelistAddressesSize); + + switch(err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + + case BLE_ERROR_GAP_WHITELIST_IN_USE: + return BLE_ERROR_INVALID_STATE; + + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + case NRF_ERROR_DATA_SIZE: + return BLE_ERROR_INVALID_PARAM; + + default: + return BLE_ERROR_UNSPECIFIED; + } } /**************************************************************************/ @@ -860,7 +1093,6 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode) { advertisingPolicyMode = mode; - return BLE_ERROR_NONE; } @@ -973,267 +1205,255 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } -#if (NRF_SD_BLE_API_VERSION <= 2) -/**************************************************************************/ -/*! - @brief Helper function used to populate the ble_gap_whitelist_t that - will be used by the SoftDevice for filtering requests. - - @returns \ref ble_error_t - - @retval BLE_ERROR_NONE - Everything executed properly - - @retval BLE_ERROR_INVALID_STATE - The internal stack was not initialized correctly. - - @note Both the SecurityManager and Gap must initialize correctly for - this function to succeed. - - @note This function is needed because for the BLE API the whitelist - is just a collection of keys, but for the stack it also includes - the IRK table. - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) +ble_error_t nRF5xGap::enablePrivacy(bool enable_privacy) { - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[1]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - if (securityManager.hasInitialized()) { - /* We do not care about the addresses, set the count to 0 */ - whitelistFromBondTable.addr_count = 0; - /* The Nordic SDK will return a failure if we set pp_addr to NULL */ - whitelistFromBondTable.pp_addrs = addressPtr; - /* We want all the IRKs we can get because we do not know which ones match the addresses */ - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - /* Use the security manager to get the IRKs from the bond table */ - ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - return error; - } - } else { - /** - * If there is no security manager then we cannot access the bond table, - * so disable IRK matching - */ - whitelistFromBondTable.addr_count = 0; - whitelistFromBondTable.irk_count = 0; + if (enable_privacy == _privacy_enabled) { + return BLE_ERROR_NONE; } - /** - * For every private resolvable address in the local whitelist check if - * there is an IRK for said address in the bond table and add it to the - * local IRK list. - */ - whitelist.irk_count = 0; - whitelist.addr_count = 0; - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - /* Test if there is a matching IRK for this private resolvable address */ - for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { - /* Found the corresponding IRK, add it to our local whitelist */ - whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; - whitelist.irk_count++; - /* Make sure we do not look at this IRK again */ - if (j != whitelistFromBondTable.irk_count - 1) { - /** - * This is not the last IRK, so replace the pointer - * with the last pointer in the array - */ - whitelistFromBondTable.pp_irks[j] = - whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; - } - /** - * If the IRK is the last pointer in the array simply - * decrement the total IRK count - */ - whitelistFromBondTable.irk_count--; - break; - } - } - } else { - /* Include the address into the whitelist */ - whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; - whitelist.addr_count++; - } - } - - return BLE_ERROR_NONE; -} -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - -/** - * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. - * - * Gap::setWhitelist provides the base for preparation of these settings. - * This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table. - * Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice) - * are passed to the identities list (intended to be passed to the Softdevice). - * - * @param[out] gapAdrHelper Reference to the struct for storing settings. - */ - -ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - pm_peer_id_t peer_id; - - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - - uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE]; - - memset(irk_found, 0x00, sizeof(irk_found)); - - - gapAdrHelper.identities_cnt = 0; - - - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - /** - * Build identities list: - * For every private resolvable address in the bond table check if - * there is maching address in th provided whitelist. - */ - while (peer_id != PM_PEER_ID_INVALID) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - - //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info)) - { - // Copy data to the buffer. - memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - gapAdrHelper.identities_cnt++; - - irk_found[i] = 1; // don't look at this address again - } - } - } - } - } - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - gapAdrHelper.addrs_cnt = 0; - - /** - * Build whitelist from the rest of addresses (explicit addresses) - */ - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t)); - gapAdrHelper.addrs[i].addr_id_peer = 0; - gapAdrHelper.addrs_cnt++; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - uint32_t retc; - - if (gapAdrHelper.identities_cnt == 0) { - retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (enable_privacy == false) { + err = setAddress(_non_private_address_type, _non_private_address); } else { - ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i) - { - pp_identities[i] = &gapAdrHelper.identities[i]; - } - - retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); - } - - if (retc == NRF_SUCCESS) { - if (gapAdrHelper.addrs_cnt == 0) { - retc = sd_ble_gap_whitelist_set(NULL, 0); - } else { - ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i) - { - pp_addrs[i] = &gapAdrHelper.addrs[i]; - } - - retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); - } - } - - switch(retc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared. - case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared. - return BLE_ERROR_ALREADY_INITIALIZED; - - case NRF_ERROR_INVALID_ADDR: - case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied. - case NRF_ERROR_DATA_SIZE: - case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() -{ - GapWhiteAndIdentityList_t whiteAndIdentityList; - uint32_t err; - - err = getStackWhiteIdentityList(whiteAndIdentityList); - - if (err != BLE_ERROR_NONE) { - return (ble_error_t)err; + err = getAddress(&_non_private_address_type, _non_private_address); } - return applyWhiteIdentityList(whiteAndIdentityList); -} + if (err) { + return err; + } + +#if (NRF_SD_BLE_API_VERSION > 2) + ble_gap_privacy_params_t privacy_config = { 0 }; + if (sd_ble_gap_privacy_get(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.privacy_mode = enable_privacy ? + BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY : + BLE_GAP_PRIVACY_MODE_OFF; + if (sd_ble_gap_privacy_set(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } #endif + + _privacy_enabled = enable_privacy; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) { + _peripheral_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) { + *configuration = _peripheral_privacy_configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) { + _central_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) { + *configuration = _central_privacy_configuration; + return BLE_ERROR_NONE; +} + +void nRF5xGap::set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler +) { + _connection_event_handler = connection_event_handler; +} + +void nRF5xGap::processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason +) { + if (_connection_event_handler) { + _connection_event_handler->on_disconnected( + handle, + reason + ); + } + + ::Gap::processDisconnectionEvent( + handle, + reason + ); +} + +ble_error_t nRF5xGap::update_identities_list(bool resolution_enabled) +{ + uint32_t err; + + if (resolution_enabled) { + ArrayView entries = get_sm().get_resolving_list(); + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + ble_gap_id_key_t* id_keys_pp[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + + for (size_t i = 0; i < limit; ++i) { + id_keys_pp[i] = &entries[i]; + } + + err = sd_ble_gap_device_identities_set( + limit ? id_keys_pp : NULL, + /* use the local IRK for all devices */ NULL, + limit + ); + } else { + err = sd_ble_gap_device_identities_set( + NULL, + /* use the local IRK for all devices */ NULL, + 0 + ); + } + + return err ? BLE_ERROR_INVALID_STATE : BLE_ERROR_NONE; +} + +void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { + // set the new connection handle as the _default_ handle in gap + setConnectionHandle(handle); + + // deal with own address + LegacyAddressType_t own_addr_type; + ble::address_t own_address; + const uint8_t* own_resolvable_address = NULL; + +#if (NRF_SD_BLE_API_VERSION <= 2) + if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { + own_addr_type = AddressType::PUBLIC; + } else { + own_addr_type = AddressType::RANDOM; + } + memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); +#else + getAddress(&own_addr_type, own_address.data()); + if (_privacy_enabled) { + own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + } +#endif + +#if (NRF_SD_BLE_API_VERSION <= 2) + bool private_peer_known = evt.irk_match; +#else + bool private_peer_known = evt.peer_addr.addr_id_peer; +#endif + + // Filter out private address non resolved if the its required by the + // resolution policy + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + private_peer_known == false && + get_sm().get_resolving_list().size() > 0 + ) { + // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible + // with the softdevice ... + sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + return; + } + + // deal with the peer address: If privacy is enabled then the softdevice + // indicates if the address has been resolved or not. If the address has + // been resolved then the identity address should be passed to the application. + // Depending on the privacy chosen by the application, connection request + // from privacy enabled peers may trigger a disconnection, the pairing procedure + // or the authentication procedure. + peer_address_type_t peer_addr_type = convert_nordic_address( + private_peer_known, + evt.peer_addr.addr_type + ); + + // NOTE: when privacy is enabled, the only address returned is the resolved + // address. + const uint8_t* peer_address = evt.peer_addr.addr; + const uint8_t* peer_resolvable_address = NULL; + + // notify internal event handler before applying the resolution strategy + if (_connection_event_handler) { + _connection_event_handler->on_connected( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address.data(), + reinterpret_cast(&(evt.conn_params)) + ); + } + + // Apply authentication strategy before application notification + if (_privacy_enabled && + !private_peer_known && + evt.role == BLE_GAP_ROLE_PERIPH && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + ) { + switch (_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle); + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + // FIXME: lookup secure DB to know what to do. + break; + + default: + break; + } + } + + processConnectionEvent( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address.data(), + reinterpret_cast(&(evt.conn_params)), + peer_resolvable_address, + own_resolvable_address + ); +} + +void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { + bool peer_address_resolved = evt.peer_addr.addr_id_peer; + + if (_privacy_enabled && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + peer_address_resolved == false && + get_sm().get_resolving_list().size() > 0 && + _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER + ) { + return; + } + + peer_address_type_t peer_addr_type = convert_nordic_address( + evt.peer_addr.addr_id_peer, + evt.peer_addr.addr_type + ); + const uint8_t* peer_address = evt.peer_addr.addr; + + processAdvertisementReport( + peer_address, + evt.rssi, + evt.scan_rsp, + static_cast(evt.type), + evt.dlen, + evt.data, + peer_addr_type + ); +} + 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 05ccc2d863..c8ef171ca4 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 @@ -44,6 +44,7 @@ #include "ble/GapAdvertisingData.h" #include "ble/Gap.h" #include "ble/GapScanningParams.h" +#include "ble/pal/ConnectionEventMonitor.h" #include "nrf_soc.h" @@ -52,8 +53,6 @@ extern "C" { #include "app_util_platform.h" } -#include "btle_security.h" - void radioNotificationStaticCallback(bool param); /**************************************************************************/ @@ -62,9 +61,11 @@ void radioNotificationStaticCallback(bool param); */ /**************************************************************************/ -class nRF5xGap : public Gap -{ +class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor { public: + nRF5xGap(); + + virtual ~nRF5xGap() { } /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); @@ -85,7 +86,9 @@ public: virtual ble_error_t startAdvertising(const GapAdvertisingParams &); virtual ble_error_t stopAdvertising(void); + 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 disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); @@ -129,6 +132,23 @@ public: return BLE_ERROR_UNSPECIFIED; } + virtual ble_error_t enablePrivacy(bool enable); + + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); @@ -148,39 +168,6 @@ private: uint8_t whitelistAddressesSize; ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE]; -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * An internal function used to populate the ble_gap_whitelist_t that will be used by - * the SoftDevice for filtering requests. This function is needed because for the BLE - * API the whitelist is just a collection of keys, but for the stack it also includes - * the IRK table. - */ - ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist); -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - /* internal type for passing a whitelist and a identities list. */ - typedef struct - { - ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; - uint32_t addrs_cnt; - - ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - uint32_t identities_cnt; - } GapWhiteAndIdentityList_t; - - /* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/ - ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/ - ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice. - * - * This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */ - ble_error_t updateWhiteAndIdentityListInStack(void); -#endif - private: bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ Timeout radioNotificationTimeout; @@ -262,22 +249,43 @@ private: radioNotificationTimeout.attach_us(mbed::callback(this, &nRF5xGap::postRadioNotificationCallback), 0); } friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */ +public: + /** @note Implements ConnectionEventMonitor. + * @copydoc ConnectionEventMonitor::set_connection_event_handler + */ + virtual void set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler + ); + + /** + * @copydoc ::Gap::processDisconnectionEvent + */ + void processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason + ); private: + friend void btle_handler(const ble_evt_t *p_ble_evt); + friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); + + ble_error_t update_identities_list(bool resolution_enabled); + void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt); + void on_advertising_packet(const ble_gap_evt_adv_report_t &evt); uint16_t m_connectionHandle; + ConnectionEventMonitor::EventHandler* _connection_event_handler; + + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + AddressType_t _non_private_address_type; + Address_t _non_private_address; /* * Allow instantiation from nRF5xn when required. */ friend class nRF5xn; - nRF5xGap() : - advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), - scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), - whitelistAddressesSize(0) { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; - } - nRF5xGap(nRF5xGap const &); void operator=(nRF5xGap const &); }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.cpp index f606d541a0..8c93ac118c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGattServer.cpp @@ -29,38 +29,38 @@ namespace { static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID_OFFSET } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 0 + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 0 } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID } } }; @@ -164,10 +164,13 @@ ble_error_t nRF5xGattServer::addService(GattService &service) } ASSERT_TRUE ( ERROR_NONE == - custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, + custom_add_in_characteristic( + BLE_GATT_HANDLE_INVALID, &nordicUUID, p_char->getProperties(), - p_char->getRequiredSecurity(), + p_char->getReadSecurityRequirement(), + p_char->getWriteSecurityRequirement(), + p_char->getUpdateSecurityRequirement(), p_char->getValueAttribute().getValuePtr(), p_char->getValueAttribute().getLength(), p_char->getValueAttribute().getMaxLength(), @@ -178,7 +181,8 @@ ble_error_t nRF5xGattServer::addService(GattService &service) presentationFormatDescriptorValueLen, p_char->isReadAuthorizationEnabled(), p_char->isWriteAuthorizationEnabled(), - &nrfCharacteristicHandles[characteristicCount]), + &nrfCharacteristicHandles[characteristicCount] + ), BLE_ERROR_PARAM_OUT_OF_RANGE ); /* Update the characteristic handle */ @@ -218,7 +222,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service) p_desc->getLength(), p_desc->getMaxLength(), p_desc->hasVariableLength(), - &nrfDescriptorHandles[descriptorCount]), + &nrfDescriptorHandles[descriptorCount], + p_desc->getReadSecurityRequirement(), + p_desc->getWriteSecurityRequirement()), BLE_ERROR_PARAM_OUT_OF_RANGE); p_descriptors[descriptorCount] = p_desc; @@ -260,9 +266,9 @@ ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { - .len = *lengthP, - .offset = 0, - .p_value = buffer, + /* .len = */ *lengthP, + /* .offset = */ 0, + /* .p_value = */ buffer, }; ASSERT_TRUE( ERROR_NONE == @@ -302,9 +308,9 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute ble_error_t returnValue = BLE_ERROR_NONE; ble_gatts_value_t value = { - .len = len, - .offset = 0, - .p_value = const_cast(buffer), + /* .len = */ len, + /* .offset = */ 0, + /* .p_value = */ const_cast(buffer), }; if (localOnly) { @@ -345,7 +351,16 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute } } - if (updatesEnabled) { + bool updates_permitted = false; + ble_gap_conn_sec_t connection_security; + uint32_t err = sd_ble_gap_conn_sec_get(connectionHandle, &connection_security); + if (!err && + (connection_security.sec_mode.sm == 1) && + (connection_security.sec_mode.lv >= p_characteristics[characteristicIndex]->getUpdateSecurityRequirement().value())) { + updates_permitted = true; + } + + if (updatesEnabled && updates_permitted) { error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); if (error != ERROR_NONE) { switch (error) { @@ -618,14 +633,14 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) // success, signal it to the softdevice ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 1, - .offset = input_req.offset, - .len = input_req.len, - .p_data = input_req.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 1, + /* .offset = */ input_req.offset, + /* .len = */ input_req.len, + /* .p_data = */ input_req.data } } }; @@ -646,12 +661,12 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .offset = req->offset, - .len = req->length, - .data = req->data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; @@ -668,9 +683,9 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) // FIXME can't use ::write here, this function doesn't take the offset into account ... ble_gatts_value_t value = { - .len = req->length, - .offset = req->offset, - .p_value = req->data + /* .len = */ req->length, + /* .offset = */ req->offset, + /* .p_value = */ req->data }; uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value); if (update_err) { @@ -695,25 +710,25 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), - .update = 1, - .offset = cbParams.offset, - .len = cbParams.len, - .p_data = cbParams.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), + /* .update = */ 1, + /* .offset = */ cbParams.offset, + /* .len = */ cbParams.len, + /* .p_data = */ cbParams.data } } }; @@ -747,21 +762,21 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { GattReadAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.read.offset, - .len = 0, - .data = NULL, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.read.offset, + /* .len = */ 0, + /* .data = */ NULL, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_READ, - .params = { - .read = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_READ, + /* .params = */ { + /* .read = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeRead(&cbParams) } } }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.cpp similarity index 94% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.cpp rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.cpp index ebd194cd76..1778a102f1 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.cpp @@ -16,7 +16,7 @@ #include -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" #include "ble/pal/PalGattClient.h" #include "ble/pal/SimpleAttServerMessage.h" @@ -161,30 +161,30 @@ static const size_t characteristic_declaration_length = 1 + 2 + 16; } // end of anonymous namespace -nRF5XGattClient::nRF5XGattClient() : +nRF5xGattClient::nRF5xGattClient() : ble::pal::GattClient(), _procedures() { } -nRF5XGattClient::~nRF5XGattClient() +nRF5xGattClient::~nRF5xGattClient() { terminate(); } -ble_error_t nRF5XGattClient::initialize() +ble_error_t nRF5xGattClient::initialize() { return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::exchange_mtu(connection_handle_t connection) +ble_error_t nRF5xGattClient::exchange_mtu(connection_handle_t connection) { // FIXME: implement when SD 140 5.x.x is present // (see sd_ble_gatts_exchange_mtu_reply) return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5XGattClient::get_mtu_size( +ble_error_t nRF5xGattClient::get_mtu_size( connection_handle_t connection_handle, uint16_t& mtu_size ) { #if (NRF_SD_BLE_API_VERSION >= 3) @@ -197,7 +197,7 @@ ble_error_t nRF5XGattClient::get_mtu_size( return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::discover_primary_service( +ble_error_t nRF5xGattClient::discover_primary_service( connection_handle_t connection, attribute_handle_t discovery_range_begining ) { @@ -206,7 +206,7 @@ ble_error_t nRF5XGattClient::discover_primary_service( ); } -ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( +ble_error_t nRF5xGattClient::discover_primary_service_by_service_uuid( connection_handle_t connection_handle, attribute_handle_t discovery_range_beginning, const UUID& uuid @@ -216,7 +216,7 @@ ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( ); } -ble_error_t nRF5XGattClient::find_included_service( +ble_error_t nRF5xGattClient::find_included_service( connection_handle_t connection_handle, attribute_handle_range_t service_range ) { @@ -225,7 +225,7 @@ ble_error_t nRF5XGattClient::find_included_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( +ble_error_t nRF5xGattClient::discover_characteristics_of_a_service( connection_handle_t connection_handle, attribute_handle_range_t discovery_range ) { @@ -234,7 +234,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_descriptors( +ble_error_t nRF5xGattClient::discover_characteristics_descriptors( connection_handle_t connection_handle, attribute_handle_range_t descriptors_discovery_range ) { @@ -243,7 +243,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_descriptors( ); } -ble_error_t nRF5XGattClient::read_attribute_value( +ble_error_t nRF5xGattClient::read_attribute_value( connection_handle_t connection_handle, attribute_handle_t attribute_handle ) { @@ -252,7 +252,7 @@ ble_error_t nRF5XGattClient::read_attribute_value( ); } -ble_error_t nRF5XGattClient::read_using_characteristic_uuid( +ble_error_t nRF5xGattClient::read_using_characteristic_uuid( connection_handle_t connection_handle, attribute_handle_range_t read_range, const UUID& uuid @@ -262,7 +262,7 @@ ble_error_t nRF5XGattClient::read_using_characteristic_uuid( ); } -ble_error_t nRF5XGattClient::read_attribute_blob( +ble_error_t nRF5xGattClient::read_attribute_blob( connection_handle_t connection, attribute_handle_t attribute_handle, uint16_t offset @@ -272,7 +272,7 @@ ble_error_t nRF5XGattClient::read_attribute_blob( ); } -ble_error_t nRF5XGattClient::read_multiple_characteristic_values( +ble_error_t nRF5xGattClient::read_multiple_characteristic_values( connection_handle_t connection, const ArrayView& characteristic_handles ) { @@ -281,7 +281,7 @@ ble_error_t nRF5XGattClient::read_multiple_characteristic_values( ); } -ble_error_t nRF5XGattClient::write_without_response( +ble_error_t nRF5xGattClient::write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -299,7 +299,7 @@ ble_error_t nRF5XGattClient::write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::signed_write_without_response( +ble_error_t nRF5xGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -317,7 +317,7 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::write_attribute( +ble_error_t nRF5xGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, const ArrayView& value @@ -327,7 +327,7 @@ ble_error_t nRF5XGattClient::write_attribute( ); } -ble_error_t nRF5XGattClient::queue_prepare_write( +ble_error_t nRF5xGattClient::queue_prepare_write( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value, @@ -338,7 +338,7 @@ ble_error_t nRF5XGattClient::queue_prepare_write( ); } -ble_error_t nRF5XGattClient::execute_write_queue( +ble_error_t nRF5xGattClient::execute_write_queue( connection_handle_t connection_handle, bool execute ) { @@ -369,7 +369,7 @@ ble_error_t nRF5XGattClient::execute_write_queue( * @note Commands such as write without response or signed write without response * are not procedures. */ -struct nRF5XGattClient::GattProcedure { +struct nRF5xGattClient::GattProcedure { /** * Initialize the procedure. * @@ -426,7 +426,7 @@ struct nRF5XGattClient::GattProcedure { * Given that such procedure expects a single event type from the soft device, * error handling can be generalized. */ -struct nRF5XGattClient::RegularGattProcedure : GattProcedure { +struct nRF5xGattClient::RegularGattProcedure : GattProcedure { /** * Construct a RegularGattProcedure. @@ -485,7 +485,7 @@ protected: * In such case a read request is issued for each service attribute handle * to extract that information. */ -struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { typedef ArrayView services_array_t; @@ -694,7 +694,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { * response it is possible to reconstruct it by keeping a copy of the UUID to * find. */ -struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -768,7 +768,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProce /** * Procedure that manage Find Included Services transactions. */ -struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { +struct nRF5xGattClient::FindIncludedServicesProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -843,7 +843,7 @@ struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { * In such case a read request is issued for each attribute handle of * characteristics that exposes a long UUID. */ -struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Data structure returned by the function flatten_response. */ @@ -1062,7 +1062,7 @@ struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Procedure that handle discovery of characteristic descriptors. */ -struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { DiscoverDescriptorsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1153,7 +1153,7 @@ struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { /** * Procedure that handle read of attribute handles. */ -struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeProcedure : RegularGattProcedure { ReadAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1180,7 +1180,7 @@ struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { /** * Procedure that handle read of characteristic using characteristic UUID. */ -struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { ReadUsingCharacteristicUUIDProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1267,7 +1267,7 @@ struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProced /** * Procedure that handles read blob transactions. */ -struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { ReadAttributeBlobProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_BLOB_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1293,7 +1293,7 @@ struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { /** * Procedure that handles Read Multiple Characteristic Values transactions. */ -struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { ReadMultipleCharacteristicsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1323,7 +1323,7 @@ struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProced /** * Procedure that handles Write transactions. */ -struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::WriteAttributeProcedure : RegularGattProcedure { WriteAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::WRITE_REQUEST, BLE_GATTC_EVT_WRITE_RSP @@ -1354,7 +1354,7 @@ struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { /** * Procedure that handles Prepare Write transactions. */ -struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { +struct nRF5xGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { QueuePrepareWriteProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1400,7 +1400,7 @@ struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { /** * Procedure that handles Execute Write transactions. */ -struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { +struct nRF5xGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { ExecuteWriteQueueProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1439,7 +1439,7 @@ struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { }; // NOTE: position after declaration of GattProcedure on purpose. -ble_error_t nRF5XGattClient::terminate() +ble_error_t nRF5xGattClient::terminate() { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i]) { @@ -1452,7 +1452,7 @@ ble_error_t nRF5XGattClient::terminate() } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1475,7 +1475,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1498,7 +1498,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2 ) { @@ -1522,7 +1522,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2, const A3& a3 ) { @@ -1545,7 +1545,7 @@ ble_error_t nRF5XGattClient::launch_procedure( return err; } -nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( +nRF5xGattClient::GattProcedure* nRF5xGattClient::get_procedure( connection_handle_t connection ) const { for (size_t i = 0; i < max_procedures_count; ++i) { @@ -1556,7 +1556,7 @@ nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( return NULL; } -bool nRF5XGattClient::register_procedure(GattProcedure *p) +bool nRF5xGattClient::register_procedure(GattProcedure *p) { if (get_procedure(p->connection_handle)) { return false; @@ -1572,7 +1572,7 @@ bool nRF5XGattClient::register_procedure(GattProcedure *p) return false; } -bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) +bool nRF5xGattClient::remove_procedure(nRF5xGattClient::GattProcedure* p) { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i] == p) { @@ -1585,13 +1585,13 @@ bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) } // singleton of the ARM Cordio client -nRF5XGattClient& nRF5XGattClient::get_client() +nRF5xGattClient& nRF5xGattClient::get_client() { - static nRF5XGattClient _client; + static nRF5xGattClient _client; return _client; } -void nRF5XGattClient::handle_events(const ble_evt_t *evt) { +void nRF5xGattClient::handle_events(const ble_evt_t *evt) { switch (evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: case BLE_GATTC_EVT_REL_DISC_RSP: @@ -1613,7 +1613,7 @@ void nRF5XGattClient::handle_events(const ble_evt_t *evt) { } } -void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_procedure_event(const ble_evt_t &evt) { GattProcedure* p = get_procedure(evt.evt.gattc_evt.conn_handle); if (p) { @@ -1621,7 +1621,7 @@ void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_hvx_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; const ble_gattc_evt_hvx_t &hvx_evt = evt.evt.gattc_evt.params.hvx; @@ -1652,7 +1652,7 @@ void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_timeout_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; GattProcedure* p = get_procedure(connection); @@ -1663,7 +1663,7 @@ void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) on_transaction_timeout(connection); } -void nRF5XGattClient::handle_connection_termination(connection_handle_t connection) +void nRF5xGattClient::handle_connection_termination(connection_handle_t connection) { GattProcedure* p = get_client().get_procedure(connection); if (p) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.h similarity index 97% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.h rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.h index 79633d6fa3..6c298aa3e3 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalGattClient.h @@ -34,12 +34,12 @@ namespace nordic { /** * Implementation of pal::GattClient for the Nordic stack. */ -class nRF5XGattClient : public ble::pal::GattClient { +class nRF5xGattClient : public ble::pal::GattClient { public: - nRF5XGattClient(); + nRF5xGattClient(); - virtual ~nRF5XGattClient(); + virtual ~nRF5xGattClient(); /** * see pal::GattClient::initialize . @@ -184,7 +184,7 @@ public: ); // singleton of the ARM Cordio client - static nRF5XGattClient& get_client(); + static nRF5xGattClient& get_client(); /** * Function call from btle.cpp diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp new file mode 100644 index 0000000000..9a48de2267 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp @@ -0,0 +1,1201 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 +#include "nRF5xPalSecurityManager.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "nrf_soc.h" +#include "nrf_error.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +namespace { +static ble_error_t convert_sd_error(uint32_t err) { + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + case BLE_ERROR_INVALID_ROLE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NOT_SUPPORTED: + return BLE_ERROR_NOT_IMPLEMENTED; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_TIMEOUT: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_UNSPECIFIED; + } +} +} + +enum pairing_role_t { + PAIRING_INITIATOR, + PAIRING_RESPONDER +}; + +struct nRF5xSecurityManager::pairing_control_block_t { + pairing_control_block_t* next; + connection_handle_t connection; + pairing_role_t role; + + // flags of the key present + KeyDistribution initiator_dist; + KeyDistribution responder_dist; + + // own keys + ble_gap_enc_key_t own_enc_key; + ble_gap_id_key_t own_id_key; + ble_gap_sign_info_t own_sign_key; + ble_gap_lesc_p256_pk_t own_pk; + + // peer keys + ble_gap_enc_key_t peer_enc_key; + ble_gap_id_key_t peer_id_key; + ble_gap_sign_info_t peer_sign_key; + ble_gap_lesc_p256_pk_t peer_pk; + + // flag required to help DHKey computation/process; should be removed with + // later versions of the softdevice + uint8_t own_oob:1; + uint8_t peer_oob:1; +}; + +nRF5xSecurityManager::nRF5xSecurityManager() + : ::ble::pal::SecurityManager(), + _sign_counter(), + _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), + _min_encryption_key_size(7), + _max_encryption_key_size(16), + _control_blocks(NULL), + resolving_list_entry_count(0) +{ + +} + +nRF5xSecurityManager::~nRF5xSecurityManager() +{ + terminate(); +} + +//////////////////////////////////////////////////////////////////////////// +// SM lifecycle management +// + +ble_error_t nRF5xSecurityManager::initialize() +{ +#if defined(MBEDTLS_ECDH_C) + if (_crypto.generate_keys( + make_ArrayView(X), + make_ArrayView(Y), + make_ArrayView(secret) + )) { + return BLE_ERROR_NONE; + } + + return BLE_ERROR_INTERNAL_STACK_FAILURE; +#endif + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::terminate() +{ + release_all_pairing_cb(); + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::reset() +{ + ble_error_t err = terminate(); + if (err) { + return err; + } + + return initialize(); +} + +//////////////////////////////////////////////////////////////////////////// +// Resolving list management +// + +// FIXME: on nordic, the irk is passed in sd_ble_gap_scan_start where whitelist +// and resolving list are all mixed up. + +uint8_t nRF5xSecurityManager::read_resolving_list_capacity() +{ + return MAX_RESOLVING_LIST_ENTRIES; +} + +ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk +) { + if (resolving_list_entry_count >= MAX_RESOLVING_LIST_ENTRIES) { + return BLE_ERROR_INVALID_STATE; + } + + ble_gap_id_key_t& entry = resolving_list[resolving_list_entry_count]; + entry.id_addr_info.addr_type = peer_identity_address_type.value(); + memcpy( + entry.id_addr_info.addr, + peer_identity_address.data(), + peer_identity_address.size() + ); + memcpy( + entry.id_info.irk, + peer_irk.data(), + peer_irk.size() + ); + + ++resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) { + size_t entry_index; + + // first the index needs to be found + for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) { + ble_gap_id_key_t& entry = resolving_list[entry_index]; + if (entry.id_addr_info.addr_type == peer_identity_address_type.value() && + entry.id_addr_info.addr == peer_identity_address + ) { + break; + } + } + + if (entry_index == resolving_list_entry_count) { + return BLE_ERROR_INVALID_PARAM; + } + + // Elements after the entry can be moved in the list + for (size_t i = entry_index; i < (resolving_list_entry_count - 1); ++i) { + resolving_list[i] = resolving_list[i + 1]; + } + + --resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::clear_resolving_list() +{ + resolving_list_entry_count = 0; + return BLE_ERROR_NONE; +} + +ArrayView nRF5xSecurityManager::get_resolving_list() { + return ArrayView( + resolving_list, + resolving_list_entry_count + ); +} + +//////////////////////////////////////////////////////////////////////////// +// Pairing +// + + +ble_error_t nRF5xSecurityManager::send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + // allocate the control block required for the procedure completion + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_INITIATOR; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_RESPONDER; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ &security_params, + /* keys */ &keyset + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::cancel_pairing( + connection_handle_t connection, pairing_failure_t reason +) { + // this is the default path except when a key is expected to be entered by + // the user. + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + reason.value() | 0x80, + /* sec params */ NULL, + /* keyset */ NULL + ); + + if (!err) { + return BLE_ERROR_NONE; + } + + // Failed because we're in the wrong state; try to cancel pairing with + // sd_ble_gap_auth_key_reply + if (err == NRF_ERROR_INVALID_STATE) { + err = sd_ble_gap_auth_key_reply( + connection, + /* key type */ BLE_GAP_AUTH_KEY_TYPE_NONE, + /* key */ NULL + ); + } + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Feature support +// + +ble_error_t nRF5xSecurityManager::get_secure_connections_support( + bool &enabled +) { + enabled = true; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) +{ + _io_capability = io_capability; + return BLE_ERROR_NONE; +} + +//////////////////////////////////////////////////////////////////////////// +// Security settings +// + +ble_error_t nRF5xSecurityManager::set_authentication_timeout( + connection_handle_t connection, uint16_t timeout_in_10ms +) { + ble_opt_t opt; + opt.gap_opt.auth_payload_timeout.conn_handle = connection; + opt.gap_opt.auth_payload_timeout.auth_payload_timeout = timeout_in_10ms; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, &opt); + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::get_authentication_timeout( + connection_handle_t connection, uint16_t &timeout_in_10ms +) { + ble_opt_t opt; + opt.gap_opt.auth_payload_timeout.conn_handle = connection; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, &opt); + if (err) { + return convert_sd_error(err); + } + + timeout_in_10ms = opt.gap_opt.auth_payload_timeout.auth_payload_timeout; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size +) { + if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || + (min_encryption_key_size > max_encryption_key_size)) { + return BLE_ERROR_INVALID_PARAM; + } + + _min_encryption_key_size = min_encryption_key_size; + _max_encryption_key_size = max_encryption_key_size; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication +) { + // In the peripheral role, only the bond, mitm, lesc and keypress fields of + // this structure are used. + ble_gap_sec_params_t security_params = { + /* bond */ authentication.get_bondable(), + /* mitm */ authentication.get_mitm(), + /* lesc */ authentication.get_secure_connections(), + /* keypress */ authentication.get_keypress_notification(), + /* remainder of the data structure is ignored */ 0 + }; + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Encryption +// + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm +) { + ble_gap_master_id_t master_id; + memcpy(master_id.rand, rand.data(), rand.size()); + memcpy(&master_id.ediv, ediv.data(), ediv.size()); + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = false; + enc_info.auth = mitm; + + // FIXME: how to pass the lenght of the LTK ??? + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm +) { + ble_gap_master_id_t master_id = {0}; + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = true; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data +) { + nrf_ecb_hal_data_t ecb; + memcpy(&ecb.key, key.data(), key.size()); + memcpy(&ecb.cleartext, data.data(), data.size()); + + uint32_t err = sd_ecb_block_encrypt(&ecb); + if (err) { + return convert_sd_error(err); + } + + memcpy(data.data(), &ecb.ciphertext, data.size()); + return BLE_ERROR_NONE; +} + +//////////////////////////////////////////////////////////////////////////// +// Privacy +// + +ble_error_t nRF5xSecurityManager::set_private_address_timeout( + uint16_t timeout_in_seconds +) { + ble_gap_privacy_params_t privacy_config; + + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return convert_sd_error(err); + } + + privacy_config.private_addr_cycle_s = timeout_in_seconds; + err = sd_ble_gap_privacy_set(&privacy_config); + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Keys +// + +ble_error_t nRF5xSecurityManager::set_ltk( + connection_handle_t connection, + const ltk_t& ltk, + bool mitm, + bool secure_connections +) { + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = secure_connections; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + // FIXME: provide peer irk and csrk ? + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + &enc_info, + /* id info */ NULL, + /* sign info */ NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_ltk_not_found( + connection_handle_t connection +) { + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + NULL, + NULL, + NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) +{ + + ble_gap_privacy_params_t privacy_config; + + // get the previous config + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the new irk + memcpy(privacy_config.p_device_irk, irk.data(), irk.size()); + err = sd_ble_gap_privacy_set(&privacy_config); + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_csrk( + const csrk_t& csrk, + sign_count_t sign_counter +) { + _csrk = csrk; + _sign_counter = sign_counter; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5xSecurityManager::remove_peer_csrk(connection_handle_t connection) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} +//////////////////////////////////////////////////////////////////////////// +// Authentication +// + +ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) +{ + uint32_t err = sd_rand_application_vector_get( + random_data.data(), random_data.size() + ); + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// MITM +// + +ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) +{ + PasskeyAscii passkey_ascii(passkey); + ble_opt_t sd_passkey; + sd_passkey.gap_opt.passkey.p_passkey = passkey ? passkey_ascii.value() : NULL; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sd_passkey); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::passkey_request_reply( + connection_handle_t connection, const passkey_num_t passkey +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + PasskeyAscii pkasc(passkey); + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, + pkasc.value() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + ble_gap_lesc_oob_data_t oob_own; + ble_gap_lesc_oob_data_t oob_peer; + + // is own address important ? + memcpy(oob_own.r, local_random.data(), local_random.size()); + // FIXME: What to do with local confirm ??? + + // is peer address important ? + memcpy(oob_peer.r, peer_random.data(), peer_random.size()); + memcpy(oob_peer.c, peer_confirm.data(), peer_confirm.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_set( + connection, + pairing_cb->own_oob ? &oob_own : NULL, + pairing_cb->peer_oob ? &oob_peer : NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t& oob_data +) { + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_OOB, + oob_data.data() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::confirmation_entered( + connection_handle_t connection, bool confirmation +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE, + NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_keypress_notification( + connection_handle_t connection, Keypress_t keypress +) { + uint32_t err = sd_ble_gap_keypress_notify( + connection, + static_cast(keypress) + ); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() +{ +#if defined(MBEDTLS_ECDH_C) + ble_gap_lesc_p256_pk_t own_secret; + ble_gap_lesc_oob_data_t oob_data; + + memcpy(own_secret.pk, secret.data(), secret.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_get( + BLE_CONN_HANDLE_INVALID, + &own_secret, + &oob_data + ); + + if (!err) { + get_event_handler()->on_secure_connections_oob_generated( + oob_data.r, + oob_data.c + ); + } + + return convert_sd_error(err); +#endif + return BLE_ERROR_NOT_IMPLEMENTED; +} + +nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() +{ + static nRF5xSecurityManager _security_manager; + return _security_manager; +} + +bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) +{ + nRF5xSecurityManager& self = nRF5xSecurityManager::get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); + + if ((evt == NULL) || (handler == NULL)) { + return false; + } + + const ble_gap_evt_t& gap_evt = evt->evt.gap_evt; + uint16_t connection = gap_evt.conn_handle; + pairing_control_block_t* pairing_cb = self.get_pairing_cb(connection); + + switch (evt->header.evt_id) { + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { + const ble_gap_sec_params_t& params = + gap_evt.params.sec_params_request.peer_params; + + KeyDistribution initiator_dist( + params.kdist_peer.enc, + params.kdist_peer.id, + params.kdist_peer.sign, + params.kdist_peer.link + ); + + KeyDistribution responder_dist( + params.kdist_own.enc, + params.kdist_own.id, + params.kdist_own.sign, + params.kdist_own.link + ); + + if (pairing_cb && pairing_cb->role == PAIRING_INITIATOR) { + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + // when this event is received by an initiator, it should not be + // forwarded via the handler; this is not a behaviour expected + // by the bluetooth standard ... + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ NULL, + /* keys ... */ &keyset + ); + + // in case of error; release the pairing control block and signal + // it to the event handler + if (err) { + release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + pairing_failure_t::UNSPECIFIED_REASON + ); + } + } else { + handler->on_pairing_request( + connection, + params.oob, + AuthenticationMask( + params.bond, + params.mitm, + params.lesc, + params.keypress + ), + initiator_dist, + responder_dist + ); + } + return true; + } + + case BLE_GAP_EVT_SEC_INFO_REQUEST: { + const ble_gap_evt_sec_info_request_t& req = + gap_evt.params.sec_info_request; + + handler->on_ltk_request( + connection, + ediv_t((uint8_t*)(&req.master_id.ediv)), + rand_t(req.master_id.rand) + ); + + return true; + } + + case BLE_GAP_EVT_PASSKEY_DISPLAY: { + const ble_gap_evt_passkey_display_t& req = + gap_evt.params.passkey_display; + + if (req.match_request == 0) { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + } else { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + handler->on_confirmation_request(connection); + } + + return true; + } + + case BLE_GAP_EVT_KEY_PRESSED: { + handler->on_keypress_notification( + connection, + (Keypress_t)gap_evt.params.key_pressed.kp_not + ); + return true; + } + + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { + uint8_t key_type = gap_evt.params.auth_key_request.key_type; + + switch (key_type) { + case BLE_GAP_AUTH_KEY_TYPE_NONE: // Illegal + break; + + case BLE_GAP_AUTH_KEY_TYPE_PASSKEY: + handler->on_passkey_request(connection); + break; + + case BLE_GAP_AUTH_KEY_TYPE_OOB: + handler->on_legacy_pairing_oob_request(connection); + break; + } + + return true; + } + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: { +#if defined(MBEDTLS_ECDH_C) + const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = + gap_evt.params.lesc_dhkey_request; + + static const size_t key_size = public_key_coord_t::size_; + ble_gap_lesc_dhkey_t shared_secret; + + _crypto.generate_shared_secret( + make_const_ArrayView(dhkey_request.p_pk_peer->pk), + make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size), + make_const_ArrayView(secret), + shared_secret.key + ); + + sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret); + + if (dhkey_request.oobd_req) { + handler->on_secure_connections_oob_request(connection); + } +#endif + return true; + } + + case BLE_GAP_EVT_AUTH_STATUS: { + const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status; + + switch (status.auth_status) { + // NOTE: pairing_cb must be valid if this event has been + // received as it is being allocated earlier and release + // in this block + // The memory is released before the last call to the event handler + // to free the heap a bit before subsequent allocation with user + // code. + case BLE_GAP_SEC_STATUS_SUCCESS: { + KeyDistribution own_dist; + KeyDistribution peer_dist; + + if (pairing_cb->role == PAIRING_INITIATOR) { + own_dist = pairing_cb->initiator_dist; + peer_dist = pairing_cb->responder_dist; + } else { + own_dist = pairing_cb->responder_dist; + peer_dist = pairing_cb->initiator_dist; + } + + if (own_dist.get_encryption()) { + handler->on_keys_distributed_local_ltk( + connection, + ltk_t(pairing_cb->own_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_local_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->own_enc_key.master_id.ediv + )), + pairing_cb->own_enc_key.master_id.rand + ); + } + + if (peer_dist.get_encryption()) { + handler->on_keys_distributed_ltk( + connection, + ltk_t(pairing_cb->peer_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->peer_enc_key.master_id.ediv + )), + pairing_cb->peer_enc_key.master_id.rand + ); + } + + if (peer_dist.get_identity()) { + handler->on_keys_distributed_irk( + connection, + irk_t(pairing_cb->peer_id_key.id_info.irk) + ); + + advertising_peer_address_type_t + address_type(advertising_peer_address_type_t::PUBLIC_ADDRESS); + + if (pairing_cb->peer_id_key.id_addr_info.addr_type) { + address_type = advertising_peer_address_type_t::RANDOM_ADDRESS; + } + + handler->on_keys_distributed_bdaddr( + connection, + address_type, + ble::address_t(pairing_cb->peer_id_key.id_addr_info.addr) + ); + } + + if (peer_dist.get_signing()) { + handler->on_keys_distributed_csrk( + connection, + pairing_cb->peer_sign_key.csrk + ); + } + + self.release_pairing_cb(pairing_cb); + handler->on_pairing_completed(connection); + break; + } + + case BLE_GAP_SEC_STATUS_TIMEOUT: + if (!pairing_cb) { + // Note: if pairing_cb does not exist then the timeout; + // is caused by a security request as the paiting_cb is + // created when the module receive the pairing request. + handler->on_link_encryption_request_timed_out(connection); + } else { + self.release_pairing_cb(pairing_cb); + handler->on_pairing_timed_out(connection); + } + break; + + case BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED: + case BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE: + case BLE_GAP_SEC_STATUS_AUTH_REQ: + case BLE_GAP_SEC_STATUS_CONFIRM_VALUE: + case BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP: + case BLE_GAP_SEC_STATUS_ENC_KEY_SIZE: + case BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED: + case BLE_GAP_SEC_STATUS_UNSPECIFIED: + case BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS: + case BLE_GAP_SEC_STATUS_INVALID_PARAMS: + case BLE_GAP_SEC_STATUS_DHKEY_FAILURE: + case BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE: + case BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG: + case BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED: + self.release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + (pairing_failure_t::type) (status.auth_status & 0xF) + ); + break; + + default: + self.release_pairing_cb(pairing_cb); + break; + } + + return true; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { + const ble_gap_evt_conn_sec_update_t& req = + gap_evt.params.conn_sec_update; + + if((req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2)) { + handler->on_link_encryption_result( + connection, link_encryption_t::ENCRYPTED + ); + } else { + handler->on_link_encryption_result( + connection, link_encryption_t::NOT_ENCRYPTED + ); + } + return true; + } + + case BLE_GAP_EVT_TIMEOUT: { + switch (gap_evt.params.timeout.src) { + case BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD: + handler->on_valid_mic_timeout(connection); + return true; + + default: + return false; + } + return false; + } + + case BLE_GAP_EVT_SEC_REQUEST: { + const ble_gap_evt_sec_request_t& req = gap_evt.params.sec_request; + handler->on_slave_security_request( + connection, + AuthenticationMask(req.bond, req.mitm, req.lesc, req.keypress) + ); + return true; + } + + default: + return false; + } +} + +ble_gap_sec_params_t nRF5xSecurityManager::make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + ble_gap_sec_params_t security_params = { + /* bond */ authentication_requirements.get_bondable(), + /* mitm */ authentication_requirements.get_mitm(), + /* lesc */ authentication_requirements.get_secure_connections(), + /* keypress */ authentication_requirements.get_keypress_notification(), + /* io_caps */ _io_capability.value(), + /* oob */ oob_data_flag, + /* min_key_size */ _min_encryption_key_size, + /* max_key_size */ _max_encryption_key_size, + /* kdist_periph */ { + /* enc */ responder_dist.get_encryption(), + /* id */ responder_dist.get_identity(), + /* sign */ responder_dist.get_signing(), + /* link */ responder_dist.get_link() + }, + /* kdist_central */ { + /* enc */ initiator_dist.get_encryption(), + /* id */ initiator_dist.get_identity(), + /* sign */ initiator_dist.get_signing(), + /* link */ initiator_dist.get_link() + } + }; + return security_params; +} + +ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_cb.initiator_dist = initiator_dist; + pairing_cb.responder_dist = responder_dist; + + ble_gap_sec_keyset_t keyset = { + /* keys_own */ { + &pairing_cb.own_enc_key, + &pairing_cb.own_id_key, + &pairing_cb.own_sign_key, + &pairing_cb.own_pk + }, + /* keys_peer */ { + &pairing_cb.peer_enc_key, + &pairing_cb.peer_id_key, + &pairing_cb.peer_sign_key, + &pairing_cb.peer_pk + } + }; + + // copy csrk if necessary + if (keyset.keys_own.p_sign_key) { + memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size()); + } + + // copy public keys used +#if defined(MBEDTLS_ECDH_C) + memcpy(pairing_cb.own_pk.pk, X.data(), X.size()); + memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size()); +#endif + return keyset; +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::allocate_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pairing_cb = + new (std::nothrow) pairing_control_block_t(); + if (pairing_cb) { + pairing_cb->next = _control_blocks; + _control_blocks = pairing_cb; + } + return pairing_cb; +} + +void nRF5xSecurityManager::release_pairing_cb(pairing_control_block_t* pairing_cb) +{ + if (pairing_cb == _control_blocks) { + _control_blocks = _control_blocks->next; + delete pairing_cb; + } else { + pairing_control_block_t* it = _control_blocks; + while (it->next) { + if (it->next == pairing_cb) { + it->next = pairing_cb->next; + delete pairing_cb; + return; + } + it = it->next; + } + } +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pcb = _control_blocks; + while (pcb) { + if (pcb->connection == connection) { + return pcb; + } + pcb = pcb->next; + } + + return NULL; +} + +void nRF5xSecurityManager::release_all_pairing_cb() +{ + while(_control_blocks) { + release_pairing_cb(_control_blocks); + } +} + +} // nordic +} // vendor +} // pal +} // ble + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h new file mode 100644 index 0000000000..30ac7e20cc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h @@ -0,0 +1,380 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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. + */ + +#ifndef NRF5X_PAL_SECURITY_MANAGER_ +#define NRF5X_PAL_SECURITY_MANAGER_ + +#include "ble/BLETypes.h" +#include "ble/pal/PalSecurityManager.h" +#include "nrf_ble.h" +#include "nRF5xCrypto.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +class nRF5xSecurityManager : public ::ble::pal::SecurityManager { +public: + nRF5xSecurityManager(); + + virtual ~nRF5xSecurityManager(); + + //////////////////////////////////////////////////////////////////////////// + // SM lifecycle management + // + + /** + * @see ::ble::pal::SecurityManager::initialize + */ + virtual ble_error_t initialize(); + + /** + * @see ::ble::pal::SecurityManager::terminate + */ + virtual ble_error_t terminate(); + + /** + * @see ::ble::pal::SecurityManager::reset + */ + virtual ble_error_t reset() ; + + //////////////////////////////////////////////////////////////////////////// + // Resolving list management + // + + /** + * @see ::ble::pal::SecurityManager::read_resolving_list_capacity + */ + virtual uint8_t read_resolving_list_capacity(); + + /** + * @see ::ble::pal::SecurityManager::add_device_to_resolving_list + */ + virtual ble_error_t add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ); + + /** + * @see ::ble::pal::SecurityManager::remove_device_from_resolving_list + */ + virtual ble_error_t remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ); + + /** + * @see ::ble::pal::SecurityManager::clear_resolving_list + */ + virtual ble_error_t clear_resolving_list(); + + /** + * Return the IRKs present in the resolving list + * @param count The number of entries present in the resolving list. + * @param pointer to the first entry of the resolving list. + */ + ArrayView get_resolving_list(); + + //////////////////////////////////////////////////////////////////////////// + // Pairing + // + + /** + * @see ::ble::pal::SecurityManager::send_pairing_request + */ + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + + /** + * @see ::ble::pal::SecurityManager::get_secure_connections_support + */ + virtual ble_error_t get_secure_connections_support( + bool &enabled + ); + + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + + //////////////////////////////////////////////////////////////////////////// + // Security settings + // + + /** + * @see ::ble::pal::SecurityManager::set_authentication_timeout + */ + virtual ble_error_t set_authentication_timeout( + connection_handle_t, uint16_t timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::get_authentication_timeout + */ + virtual ble_error_t get_authentication_timeout( + connection_handle_t, uint16_t &timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ + virtual ble_error_t slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication + ); + + //////////////////////////////////////////////////////////////////////////// + // Encryption + // + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm + ); + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm + ) ; + + /** + * @see ::ble::pal::SecurityManager::encrypt_data + */ + virtual ble_error_t encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data + ); + + //////////////////////////////////////////////////////////////////////////// + // Privacy + // + + /** + * @see ::ble::pal::SecurityManager::set_private_address_timeout + */ + virtual ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds); + + //////////////////////////////////////////////////////////////////////////// + // Keys + // + + /** + * @see ::ble::pal::SecurityManager::set_ltk + */ + virtual ble_error_t set_ltk( + connection_handle_t connection, + const ltk_t <k, + bool mitm, + bool secure_connections + ); + + /** + * @see ::ble::pal::SecurityManager::set_ltk_not_found + */ + virtual ble_error_t set_ltk_not_found( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::set_irk + */ + virtual ble_error_t set_irk(const irk_t &irk); + + /** + * @see ::ble::pal::SecurityManager::set_csrk + */ + virtual ble_error_t set_csrk(const csrk_t &csrk, sign_count_t sign_counter); + + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ); + + /** + * @see ::ble::pal::SecurityManager::remove_peer_csrk + */ + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); + + //////////////////////////////////////////////////////////////////////////// + // Authentication + // + + /** + * @see ::ble::pal::SecurityManager::get_random_data + */ + virtual ble_error_t get_random_data(byte_array_t<8> &random_data); + + //////////////////////////////////////////////////////////////////////////// + // MITM + // + + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + + /** + * @see ::ble::pal::SecurityManager::passkey_request_reply + */ + virtual ble_error_t passkey_request_reply( + connection_handle_t connection, + passkey_num_t passkey + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + + /** + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply + */ + virtual ble_error_t legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t &oob_data + ); + + /** + * @see ::ble::pal::SecurityManager::confirmation_entered + */ + virtual ble_error_t confirmation_entered( + connection_handle_t connection, bool confirmation + ); + + /** + * @see ::ble::pal::SecurityManager::send_keypress_notification + */ + virtual ble_error_t send_keypress_notification( + connection_handle_t connection, Keypress_t keypress + ); + + /** + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob + */ + virtual ble_error_t generate_secure_connections_oob(); + + // singleton of nordic Security Manager + static nRF5xSecurityManager& get_security_manager(); + + // Event handler + bool sm_handler(const ble_evt_t *evt); + +private: + csrk_t _csrk; + sign_count_t _sign_counter; + io_capability_t _io_capability; + uint8_t _min_encryption_key_size; + uint8_t _max_encryption_key_size; + + struct pairing_control_block_t; + + ble_gap_sec_params_t make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + ble_gap_sec_keyset_t make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection); + void release_pairing_cb(pairing_control_block_t* pairing_cb); + pairing_control_block_t* get_pairing_cb(connection_handle_t connection); + void release_all_pairing_cb(); + + pairing_control_block_t* _control_blocks; +#if defined(MBEDTLS_ECDH_C) + CryptoToolbox _crypto; + ble::public_key_coord_t X; + ble::public_key_coord_t Y; + ble::public_key_coord_t secret; +#endif + + static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; + + size_t resolving_list_entry_count; + ble_gap_id_key_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif /* NRF5X_PAL_SECURITY_MANAGER_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xSecurityManager.h deleted file mode 100644 index 0e901b5701..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xSecurityManager.h +++ /dev/null @@ -1,194 +0,0 @@ -/* 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 __NRF51822_SECURITY_MANAGER_H__ -#define __NRF51822_SECURITY_MANAGER_H__ - -#include - -#include "nRF5xGap.h" -#include "ble/SecurityManager.h" -#include "btle_security.h" - -class nRF5xSecurityManager : public SecurityManager -{ -public: - /* Functions that must be implemented from SecurityManager */ - virtual ble_error_t init(bool enableBonding, - bool requireMITM, - SecurityIOCapabilities_t iocaps, - const Passkey_t passkey) { - return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); - } - - virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { - return btle_getLinkSecurity(connectionHandle, securityStatusP); - } - - virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) { - return btle_setLinkSecurity(connectionHandle, securityMode); - } - - virtual ble_error_t purgeAllBondingState(void) { - return btle_purgeAllBondingState(); - } -#if (NRF_SD_BLE_API_VERSION <= 2) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - uint8_t i; - - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - /* Initialize the structure so that we get as many addreses as the whitelist can hold */ - whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_addrs = addressPtr; - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - addresses.size = 0; - return error; - } - - /* Put all the addresses in the structure */ - for (i = 0; i < whitelistFromBondTable.addr_count; ++i) { - if (i >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size = i; - return BLE_ERROR_NONE; - } - memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t)); - } - - /* Update the current address count */ - addresses.size = i; - - /* The assumption here is that the underlying implementation of - * createWhitelistFromBondTable() will not return the private resolvable - * addresses (which is the case in the SoftDevice). Rather it returns the - * IRKs, so we need to generate the private resolvable address by ourselves. - */ - for (i = 0; i < whitelistFromBondTable.irk_count; ++i) { - if (i + addresses.size >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size += i; - return BLE_ERROR_NONE; - } - btle_generateResolvableAddress( - *whitelistFromBondTable.pp_irks[i], - (ble_gap_addr_t &) addresses.addresses[i + addresses.size] - ); - } - - /* Update the current address count */ - addresses.size += i; - - return BLE_ERROR_NONE; - } -#else // -> NRF_SD_BLE_API_VERSION >= 3 - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - return btle_getAddressesFromBondTable(addresses); - } -#endif // #if (NRF_SD_BLE_API_VERSION <= 2) - - - - /** - * @brief Clear nRF5xSecurityManager's state. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t reset(void) - { - if (SecurityManager::reset() != BLE_ERROR_NONE) { - return BLE_ERROR_INVALID_STATE; - } - - return BLE_ERROR_NONE; - } - - bool hasInitialized(void) const { - return btle_hasInitializedSecurity(); - } - -public: - /* - * Allow instantiation from nRF5xn when required. - */ - friend class nRF5xn; - - nRF5xSecurityManager() { - /* empty */ - } - -private: - nRF5xSecurityManager(const nRF5xSecurityManager &); - const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &); - -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * Expose an interface that allows us to query the SoftDevice bond table - * and extract a whitelist. - */ - ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const { - return btle_createWhitelistFromBondTable(&whitelistFromBondTable); - } -#endif - /* - * Given a BLE address and a IRK this function check whether the address - * can be generated from the IRK. To do so, this function uses the hash - * function and algorithm described in the Bluetooth low Energy - * Specification. Internally, Nordic SDK functions are used. - */ - bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const { - return btle_matchAddressAndIrk(address, irk); - } - - /* - * Give nRF5xGap access to createWhitelistFromBondTable() and - * matchAddressAndIrk() - */ - friend class nRF5xGap; -}; - -#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.cpp index 7bc8b821b7..e8e463a0c5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.cpp @@ -31,7 +31,7 @@ extern "C" { #include "nrf_sdh.h" } -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" /** * The singleton which represents the nRF51822 transport for the BLE. @@ -62,8 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())), - securityManagerInstance(NULL) + gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())) { } @@ -126,7 +125,7 @@ ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContex return BLE_ERROR_ALREADY_INITIALIZED; } - instanceID = instanceID; + this->instanceID = instanceID; /* ToDo: Clear memory contents, reset the SD, etc. */ if (btle_init() != ERROR_NONE) { @@ -187,13 +186,6 @@ ble_error_t nRF5xn::shutdown(void) } } - if (securityManagerInstance != NULL) { - error = securityManagerInstance->reset(); - if (error != BLE_ERROR_NONE) { - return error; - } - } - /* S110 does not support BLE client features, nothing to reset. */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) error = getGattClient().reset(); @@ -214,6 +206,29 @@ ble_error_t nRF5xn::shutdown(void) return BLE_ERROR_NONE; } +SecurityManager& nRF5xn::getSecurityManager() +{ + const nRF5xn* self = this; + return const_cast(self->getSecurityManager()); +} + +const SecurityManager& nRF5xn::getSecurityManager() const +{ + ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal = + ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager(); + static struct : ble::pal::SigningEventMonitor { + virtual void set_signing_event_handler(EventHandler *signing_event_handler) { } + } dummy_signing_event_monitor; + + static ble::generic::GenericSecurityManager m_instance( + m_pal, + const_cast(getGap()), + dummy_signing_event_monitor + ); + + return m_instance; +} + void nRF5xn::waitForEvent(void) { @@ -223,19 +238,18 @@ nRF5xn::waitForEvent(void) void nRF5xn::processEvents() { core_util_critical_section_enter(); - while (isEventsSignaled) { + if (isEventsSignaled) { isEventsSignaled = false; core_util_critical_section_exit(); - #if NRF_SD_BLE_API_VERSION >= 5 +#if NRF_SD_BLE_API_VERSION >= 5 // We use the "polling" dispatch model // http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v14.2.0/group__nrf__sdh.html?cp=4_0_0_6_11_60_20#gab4d7be69304d4f5feefd1d440cc3e6c7 // This will process any pending events from the Softdevice nrf_sdh_evts_poll(); - #else +#else intern_softdevice_events_execute(); - #endif - - core_util_critical_section_enter(); +#endif + } else { + core_util_critical_section_exit(); } - core_util_critical_section_exit(); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h index 154b9e49dc..38ee87ec8e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xn.h @@ -21,10 +21,12 @@ #include "ble/blecommon.h" #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" +#include "ble/generic/GenericSecurityManager.h" +#include "ble/pal/SimpleEventQueue.h" +#include "nRF5xPalSecurityManager.h" #include "nRF5xGap.h" #include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" #include "btle.h" @@ -82,18 +84,14 @@ public: } /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A reference to GattServer. + * @see BLEInstanceBase::getSecurityManager */ - virtual nRF5xSecurityManager &getSecurityManager() { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; /** * Accessors to GAP. This function checks whether gapInstance points to an @@ -130,23 +128,6 @@ public: return *gattServerInstance; }; - /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A const reference to GattServer. - * - * @note The accessor is able to modify the object's state because the - * internal pointer has been declared mutable. - */ - virtual const nRF5xSecurityManager &getSecurityManager() const { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } - virtual void waitForEvent(void); virtual void processEvents(); @@ -170,10 +151,7 @@ private: * it can be assigned inside a 'const' function. */ ble::generic::GenericGattClient gattClient; - mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance. - * If NULL, then SecurityManager has not been initialized. - * The pointer has been declared as 'mutable' so that - * it can be assigned inside a 'const' function. */ + }; #endif diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct index e69ed0c74f..2bdba912a1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct @@ -14,8 +14,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x10000 #else - #define MBED_RAM_START 0x20003800 - #define MBED_RAM_SIZE 0xC800 + #define MBED_RAM_START 0x200031D0 + #define MBED_RAM_SIZE 0xCE30 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld index fd78080909..0fa07980fc 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld @@ -30,8 +30,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x10000 #else - #define MBED_RAM_START 0x20003800 - #define MBED_RAM_SIZE 0xC800 + #define MBED_RAM_START 0x200031D0 + #define MBED_RAM_SIZE 0xCE30 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf index d66a6ab5ab..fd96dc6952 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf @@ -16,8 +16,8 @@ if (MBED_APP_START == 0) { define symbol MBED_RAM_START = 0x20000000; define symbol MBED_RAM_SIZE = 0x10000; } else { - define symbol MBED_RAM_START = 0x20003800; - define symbol MBED_RAM_SIZE = 0xC800; + define symbol MBED_RAM_START = 0x20003188; + define symbol MBED_RAM_SIZE = 0x3CE78; } define symbol MBED_RAM0_START = MBED_RAM_START; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct index 6849dc2239..8aaa8a42ba 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct @@ -14,8 +14,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x40000 #else - #define MBED_RAM_START 0x20003700 - #define MBED_RAM_SIZE 0x3C900 + #define MBED_RAM_START 0x20003188 + #define MBED_RAM_SIZE 0x3CE78 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld index 55f39e9c4f..99b8a4e4dd 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld @@ -30,8 +30,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x40000 #else - #define MBED_RAM_START 0x20003700 - #define MBED_RAM_SIZE 0x3C900 + #define MBED_RAM_START 0x20003188 + #define MBED_RAM_SIZE 0x3CE78 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf index 2605356911..95819fe1df 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf @@ -16,8 +16,8 @@ if (MBED_APP_START == 0) { define symbol MBED_RAM_START = 0x20000000; define symbol MBED_RAM_SIZE = 0x40000; } else { - define symbol MBED_RAM_START = 0x20003700; - define symbol MBED_RAM_SIZE = 0x3C900; + define symbol MBED_RAM_START = 0x20003188; + define symbol MBED_RAM_SIZE = 0x3CE78; } define symbol MBED_RAM0_START = MBED_RAM_START; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md index c9f238a697..0b7a849b17 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md @@ -7,6 +7,14 @@ components/ble Removed * ble_services/* * ble_dtm/ble_dtm_hw_nrf51.c + * ble_advertising/* + * ble_db_discovery/* + * ble_dtm/* + * ble_racp/* + * common/* + * nrf_ble_gatt/* + * nrf_ble_qwr/* + * peer_manager/* Renamed * #include "ble.h" -> #include "nrf_ble.h" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c deleted file mode 100644 index 1cb77cd6c8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c +++ /dev/null @@ -1,695 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_ADVERTISING) -#include "ble_advdata.h" -#include "ble_advertising.h" -#include "nrf_soc.h" -#include "nrf_log.h" -#include "nrf_fstorage.h" -#include "sdk_errors.h" -#include "nrf_sdh_ble.h" -#include "nrf_sdh_soc.h" - -#define BLE_ADV_MODES (5) /**< Total number of possible advertising modes. */ - - -#if (NRF_SD_BLE_API_VERSION <= 2) - - static bool whitelist_has_entries(ble_advertising_t * const p_advertising) - { - return ((p_advertising->whitelist.addr_count != 0) || (p_advertising->whitelist.irk_count != 0)); - } - -#else - - static bool whitelist_has_entries(ble_advertising_t * const p_advertising) - { - return p_advertising->whitelist_in_use; - } - -#endif - - - -/**@brief Function for checking if an address is valid. - */ -static bool addr_is_valid(uint8_t const * const addr) -{ - for (uint32_t i = 0; i < BLE_GAP_ADDR_LEN; i++) - { - if (addr[i] != 0) - { - return true; - } - } - return false; -} - - -static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode) -{ - return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES); -} - - -/**@brief Function for handling the Connected event. - * - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_connected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) - { - p_advertising->current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - } -} - - -/**@brief Function for handling the Disconnected event. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - uint32_t ret; - - p_advertising->whitelist_temporarily_disabled = false; - - if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle && - p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false) - { - ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED); - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - } -} - - -/**@brief Function for handling the Timeout event. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_timeout(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - ret_code_t ret; - - if (p_ble_evt->evt.gap_evt.params.timeout.src != BLE_GAP_TIMEOUT_SRC_ADVERTISING) - { - // Nothing to do. - return; - } - - // Start advertising in the next mode. - ret = ble_advertising_start(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current)); - - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } -} - - -/** @brief Function to determine if a flash write operation in in progress. - * - * @return true if a flash operation is in progress, false if not. - */ -static bool flash_access_in_progress() -{ - return nrf_fstorage_is_busy(NULL); -} - - -/**@brief Get the next available advertising mode. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] adv_mode Requested advertising mode. - * - * @returns adv_mode if possible, or the best available mode if not. - */ -static ble_adv_mode_t adv_mode_next_avail_get(ble_advertising_t * const p_advertising, - ble_adv_mode_t adv_mode) -{ - bool peer_addr_is_valid = addr_is_valid(p_advertising->peer_address.addr); - - // If a mode is disabled, continue to the next mode. - - switch (adv_mode) - { - case BLE_ADV_MODE_DIRECTED: - if ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid) - { - return BLE_ADV_MODE_DIRECTED; - } - // Fallthrough. - - case BLE_ADV_MODE_DIRECTED_SLOW: - if ((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && peer_addr_is_valid) - { - return BLE_ADV_MODE_DIRECTED_SLOW; - } - // Fallthrough. - - case BLE_ADV_MODE_FAST: - if (p_advertising->adv_modes_config.ble_adv_fast_enabled) - { - return BLE_ADV_MODE_FAST; - } - // Fallthrough. - - case BLE_ADV_MODE_SLOW: - if (p_advertising->adv_modes_config.ble_adv_slow_enabled) - { - return BLE_ADV_MODE_SLOW; - } - // Fallthrough. - - default: - return BLE_ADV_MODE_IDLE; - } -} - - -/**@brief Function for starting directed advertising. - * - * @param[in] p_advertising Advertising instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS - */ -static ret_code_t set_adv_mode_directed(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED; - - p_adv_params->p_peer_addr = &(p_advertising->peer_address); - p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; - p_adv_params->timeout = 0; - p_adv_params->interval = 0; - - return NRF_SUCCESS; -} - - -/**@brief Function for starting directed slow advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS - */ -static ret_code_t set_adv_mode_directed_slow(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED_SLOW; - - p_adv_params->p_peer_addr = &p_advertising->peer_address; - p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_directed_slow_timeout; - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_directed_slow_interval; - - return NRF_SUCCESS; -} - - -/**@brief Function for starting fast advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS or an error from @ref ble_advdata_set(). - */ -static ret_code_t set_adv_mode_fast(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - ret_code_t ret; - - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_fast_interval; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_fast_timeout; - - if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled) && - (whitelist_has_entries(p_advertising))) - { - #if (NRF_SD_BLE_API_VERSION <= 2) - p_adv_params->p_whitelist = &m_whitelist; - #endif - - p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; - p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - p_advertising->adv_evt = BLE_ADV_EVT_FAST_WHITELIST; - } - else - { - p_advertising->adv_evt = BLE_ADV_EVT_FAST; - } - - return NRF_SUCCESS; -} - - -/**@brief Function for starting slow advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS or an error from @ref ble_advdata_set(). - */ -static ret_code_t set_adv_mode_slow(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - ret_code_t ret; - - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_slow_interval; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_slow_timeout; - - if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled) && - (whitelist_has_entries(p_advertising))) - { - #if (NRF_SD_BLE_API_VERSION <= 2) - { - p_adv_params->p_whitelist = &p_advertising->whitelist; - } - #endif - - p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; - p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - p_advertising->adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; - } - else - { - p_advertising->adv_evt = BLE_ADV_EVT_SLOW; - } - - return NRF_SUCCESS; -} - - -void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, - uint8_t ble_cfg_tag) -{ - p_advertising->conn_cfg_tag = ble_cfg_tag; -} - - -uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, - ble_advertising_init_t const * const p_init) -{ - uint32_t ret; - if ((p_init == NULL) || (p_advertising == NULL)) - { - return NRF_ERROR_NULL; - } - - p_advertising->initialized = true; - p_advertising->adv_mode_current = BLE_ADV_MODE_IDLE; - p_advertising->adv_modes_config = p_init->config; - p_advertising->conn_cfg_tag = BLE_CONN_CFG_TAG_DEFAULT; - p_advertising->evt_handler = p_init->evt_handler; - p_advertising->error_handler = p_init->error_handler; - p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; - - memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); - memset(&p_advertising->advdata, 0, sizeof(p_advertising->advdata)); - - // Copy advertising data. - p_advertising->advdata.name_type = p_init->advdata.name_type; - p_advertising->advdata.include_appearance = p_init->advdata.include_appearance; - p_advertising->advdata.flags = p_init->advdata.flags; - p_advertising->advdata.short_name_len = p_init->advdata.short_name_len; - - p_advertising->advdata.uuids_complete = p_init->advdata.uuids_complete; - p_advertising->advdata.uuids_more_available = p_init->advdata.uuids_more_available; - p_advertising->advdata.uuids_solicited = p_init->advdata.uuids_solicited; - p_advertising->advdata.include_ble_device_addr = p_init->advdata.include_ble_device_addr; - - if (p_init->advdata.p_manuf_specific_data != NULL) - { - p_advertising->advdata.p_manuf_specific_data = &(p_advertising->manuf_specific_data); - p_advertising->manuf_specific_data.data.p_data = p_advertising->manuf_data_array; - p_advertising->advdata.p_manuf_specific_data->company_identifier = - p_init->advdata.p_manuf_specific_data->company_identifier; - p_advertising->advdata.p_manuf_specific_data->data.size = p_init->advdata.p_manuf_specific_data->data.size; - - for (uint32_t i = 0; i < p_advertising->advdata.p_manuf_specific_data->data.size; i++) - { - p_advertising->manuf_data_array[i] = p_init->advdata.p_manuf_specific_data->data.p_data[i]; - } - } - - if (p_init->advdata.p_service_data_array != NULL) - { - p_advertising->service_data.data.p_data = p_advertising->service_data_array; - p_advertising->advdata.p_service_data_array = &(p_advertising->service_data); - p_advertising->advdata.p_service_data_array->data.p_data = p_advertising->service_data_array; - p_advertising->advdata.p_service_data_array->data.size = p_init->advdata.p_service_data_array->data.size; - p_advertising->advdata.p_service_data_array->service_uuid = p_init->advdata.p_service_data_array->service_uuid; - - for (uint32_t i = 0; i < p_advertising->advdata.p_service_data_array->data.size; i++) - { - p_advertising->service_data_array[i] = p_init->advdata.p_service_data_array->data.p_data[i]; - } - - p_advertising->advdata.service_data_count = p_init->advdata.service_data_count; - } - - if (p_init->advdata.p_slave_conn_int != NULL) - { - p_advertising->advdata.p_slave_conn_int = &(p_advertising->slave_conn_int); - p_advertising->advdata.p_slave_conn_int->max_conn_interval = p_init->advdata.p_slave_conn_int->max_conn_interval; - p_advertising->advdata.p_slave_conn_int->min_conn_interval = p_init->advdata.p_slave_conn_int->min_conn_interval; - } - - if (p_init->advdata.p_tx_power_level != NULL) - { - p_advertising->advdata.p_tx_power_level = p_init->advdata.p_tx_power_level; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - for (int i = 0; i whitelist.pp_addrs[i] = &p_advertising->whitelist_addrs[i]; - } - - for (int i = 0; i whitelist.pp_irks[i] = &p_advertising->whitelist_irks[i]; - } -#endif - ret = ble_advdata_set(&(p_advertising->advdata), &(p_init->srdata)); - return ret; -} - - -uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, - ble_adv_mode_t advertising_mode) -{ - uint32_t ret; - ble_gap_adv_params_t adv_params; - - if (p_advertising->initialized == false) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->adv_mode_current = advertising_mode; - - // Delay starting advertising until the flash operations are complete. - if (flash_access_in_progress()) - { - p_advertising->advertising_start_pending = true; - return NRF_SUCCESS; - } - - memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); - - if ( ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) - ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) - ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW)) - ) - { - if (p_advertising->evt_handler != NULL) - { - p_advertising->peer_addr_reply_expected = true; - p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); - } - else - { - p_advertising->peer_addr_reply_expected = false; - } - } - - p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode); - - // Fetch the whitelist. - if ((p_advertising->evt_handler != NULL) && - (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) && - (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled)) - { - #if (NRF_SD_BLE_API_VERSION >= 3) - p_advertising->whitelist_in_use = false; - #endif - p_advertising->whitelist_reply_expected = true; - p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); - } - else - { - p_advertising->whitelist_reply_expected = false; - } - - // Initialize advertising parameters with default values. - memset(&adv_params, 0, sizeof(adv_params)); - - adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; - adv_params.fp = BLE_GAP_ADV_FP_ANY; - - // Set advertising parameters and events according to selected advertising mode. - switch (p_advertising->adv_mode_current) - { - case BLE_ADV_MODE_DIRECTED: - ret = set_adv_mode_directed(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_DIRECTED_SLOW: - ret = set_adv_mode_directed_slow(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_FAST: - ret = set_adv_mode_fast(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_SLOW: - ret = set_adv_mode_slow(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_IDLE: - p_advertising->adv_evt = BLE_ADV_EVT_IDLE; - break; - - default: - break; - } - - if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE) - { - ret = sd_ble_gap_adv_start(&adv_params, p_advertising->conn_cfg_tag); - if (ret != NRF_SUCCESS) - { - return ret; - } - } - - if (p_advertising->evt_handler != NULL) - { - p_advertising->evt_handler(p_advertising->adv_evt); - } - - return NRF_SUCCESS; -} - - -void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connected(p_advertising, p_ble_evt); - break; - - // Upon disconnection, whitelist will be activated and direct advertising is started. - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected(p_advertising, p_ble_evt); - break; - - // Upon time-out, the next advertising mode is started. - case BLE_GAP_EVT_TIMEOUT: - on_timeout(p_advertising, p_ble_evt); - break; - - default: - break; - } -} - - -void ble_advertising_on_sys_evt(uint32_t evt_id, void * p_context) -{ - ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; - - switch (evt_id) - { - //When a flash operation finishes, re-attempt to start advertising operations. - case NRF_EVT_FLASH_OPERATION_SUCCESS: - case NRF_EVT_FLASH_OPERATION_ERROR: - { - if (p_advertising->advertising_start_pending) - { - p_advertising->advertising_start_pending = false; - ret_code_t ret = ble_advertising_start(p_advertising, - p_advertising->adv_mode_current); - - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - } - } break; - - default: - // No implementation needed. - break; - } -} - - -uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t * p_peer_address) -{ - if (!p_advertising->peer_addr_reply_expected) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->peer_addr_reply_expected = false; - - memcpy(&p_advertising->peer_address, p_peer_address, sizeof(p_advertising->peer_address)); - - return NRF_SUCCESS; -} - - -uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t const * p_gap_addrs, - uint32_t addr_cnt, - ble_gap_irk_t const * p_gap_irks, - uint32_t irk_cnt) -{ - if (!p_advertising->whitelist_reply_expected) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->whitelist_reply_expected = false; - - #if (NRF_SD_BLE_API_VERSION <= 2) - - p_advertising->whitelist.addr_count = addr_cnt; - p_advertising->whitelist.irk_count = irk_cnt; - - for (uint32_t i = 0; i < addr_cnt; i++) - { - *p_advertising->whitelist.pp_addrs[i] = p_gap_addrs[i]; - } - - for (uint32_t i = 0; i < irk_cnt; i++) - { - *p_advertising->whitelist.pp_irks[i] = p_gap_irks[i]; - } - - #else - - p_advertising->whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0)); - - #endif - - return NRF_SUCCESS; -} - - -uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising) -{ - uint32_t ret; - - (void) sd_ble_gap_adv_stop(); - - p_advertising->whitelist_temporarily_disabled = true; - - #if (NRF_SD_BLE_API_VERSION >= 3) - p_advertising->whitelist_in_use = false; - #endif - - p_advertising->advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - ret = ble_advertising_start(p_advertising, p_advertising->adv_mode_current); - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - - return NRF_SUCCESS; -} - - -void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, - ble_adv_modes_config_t const * const p_adv_modes_config) -{ - p_advertising->adv_modes_config = *p_adv_modes_config; -} - - -#endif // NRF_MODULE_ENABLED(BLE_ADVERTISING) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h deleted file mode 100644 index 61bbb7b0b6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_advertising Advertising Module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for handling connectable BLE advertising. - * - * @details The Advertising Module handles connectable advertising for your application. It can - * be configured with advertising modes to suit most typical use cases. - * Your main application can react to changes in advertising modes - * if an event handler is provided. - * - * @note The Advertising Module supports only applications with a single peripheral link. - * - */ - -#ifndef BLE_ADVERTISING_H__ -#define BLE_ADVERTISING_H__ - -#include -#include "nrf_error.h" -#include "nrf_ble.h" -#include "ble_gattc.h" -#include "ble_advdata.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a ble_advertising instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define BLE_ADVERTISING_DEF(_name) \ -static ble_advertising_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ - BLE_ADV_BLE_OBSERVER_PRIO, \ - ble_advertising_on_ble_evt, &_name); \ -NRF_SDH_SOC_OBSERVER(_name ## _soc_obs, \ - BLE_ADV_SOC_OBSERVER_PRIO, \ - ble_advertising_on_sys_evt, &_name) - - -/**@brief Advertising modes. */ -typedef enum -{ - BLE_ADV_MODE_IDLE, /**< Idle; no connectable advertising is ongoing. */ - BLE_ADV_MODE_DIRECTED, /**< Directed advertising attempts to connect to the most recently disconnected peer. */ - BLE_ADV_MODE_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) attempts to connect to the most recently disconnected peer. */ - BLE_ADV_MODE_FAST, /**< Fast advertising will connect to any peer device, or filter with a whitelist if one exists. */ - BLE_ADV_MODE_SLOW, /**< Slow advertising is similar to fast advertising. By default, it uses a longer advertising interval and time-out than fast advertising. However, these options are defined by the user. */ -} ble_adv_mode_t; - -/**@brief Advertising events. - * - * @details These events are propagated to the main application if a handler was provided during - * initialization of the Advertising Module. Events for modes that are not used can be - * ignored. Similarly, BLE_ADV_EVT_WHITELIST_REQUEST and BLE_ADV_EVT_PEER_ADDR_REQUEST - * can be ignored if whitelist and direct advertising is not used. - */ -typedef enum -{ - BLE_ADV_EVT_IDLE, /**< Idle; no connectable advertising is ongoing.*/ - BLE_ADV_EVT_DIRECTED, /**< Direct advertising mode has started. */ - BLE_ADV_EVT_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) has started. */ - BLE_ADV_EVT_FAST, /**< Fast advertising mode has started. */ - BLE_ADV_EVT_SLOW, /**< Slow advertising mode has started. */ - BLE_ADV_EVT_FAST_WHITELIST, /**< Fast advertising mode using the whitelist has started. */ - BLE_ADV_EVT_SLOW_WHITELIST, /**< Slow advertising mode using the whitelist has started. */ - BLE_ADV_EVT_WHITELIST_REQUEST, /**< Request a whitelist from the main application. For whitelist advertising to work, the whitelist must be set when this event occurs. */ - BLE_ADV_EVT_PEER_ADDR_REQUEST /**< Request a peer address from the main application. For directed advertising to work, the peer address must be set when this event occurs. */ -} ble_adv_evt_t; - -/**@brief Options for the different advertisement modes. - * - * @details This structure is used to enable or disable advertising modes and to configure time-out - * periods and advertising intervals. - */ -typedef struct -{ - bool ble_adv_on_disconnect_disabled; /**< Enable or disable automatic return to advertising upon disconnecting.*/ - bool ble_adv_whitelist_enabled; /**< Enable or disable use of the whitelist. */ - bool ble_adv_directed_enabled; /**< Enable or disable direct advertising mode. */ - bool ble_adv_directed_slow_enabled; /**< Enable or disable direct advertising mode. */ - bool ble_adv_fast_enabled; /**< Enable or disable fast advertising mode. */ - bool ble_adv_slow_enabled; /**< Enable or disable slow advertising mode. */ - uint32_t ble_adv_directed_slow_interval; /**< Advertising interval for directed advertising. */ - uint32_t ble_adv_directed_slow_timeout; /**< Time-out (number of tries) for direct advertising. */ - uint32_t ble_adv_fast_interval; /**< Advertising interval for fast advertising. */ - uint32_t ble_adv_fast_timeout; /**< Time-out (in seconds) for fast advertising. */ - uint32_t ble_adv_slow_interval; /**< Advertising interval for slow advertising. */ - uint32_t ble_adv_slow_timeout; /**< Time-out (in seconds) for slow advertising. */ -} ble_adv_modes_config_t; - -/**@brief BLE advertising event handler type. */ -typedef void (*ble_adv_evt_handler_t) (ble_adv_evt_t const adv_evt); - -/**@brief BLE advertising error handler type. */ -typedef void (*ble_adv_error_handler_t) (uint32_t nrf_error); - -typedef struct -{ - bool initialized; - bool advertising_start_pending; /**< Flag to keep track of ongoing operations in flash. */ - - ble_adv_evt_t adv_evt; /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address. */ - - ble_adv_mode_t adv_mode_current; /**< Variable to keep track of the current advertising mode. */ - ble_adv_modes_config_t adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/ - uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if the advertising results in a connection. */ - - ble_gap_addr_t peer_address; /**< Address of the most recently connected peer, used for direct advertising. */ - bool peer_addr_reply_expected; /**< Flag to verify that peer address is only set when requested. */ - - ble_advdata_t advdata; /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */ - ble_advdata_manuf_data_t manuf_specific_data; /**< Manufacturer specific data structure*/ - uint8_t manuf_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the Manufacturer specific data*/ - ble_advdata_service_data_t service_data; /**< Service data structure. */ - uint8_t service_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the service data. */ - ble_advdata_conn_int_t slave_conn_int; /**< Connection interval range structure.*/ - uint16_t current_slave_link_conn_handle; /**< Connection handle for the active link. */ - - ble_adv_evt_handler_t evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */ - ble_adv_error_handler_t error_handler; /**< Handler for the advertising error events. */ - - bool whitelist_temporarily_disabled; /**< Flag to keep track of temporary disabling of the whitelist. */ - bool whitelist_reply_expected; - -#if (NRF_SD_BLE_API_VERSION <= 2) - // For SoftDevices v 2.x, this module caches a whitelist which is retrieved from the - // application using an event, and which is passed as a parameter when calling - // sd_ble_gap_adv_start(). - ble_gap_addr_t * p_whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_irk_t * p_whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; - ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; - - ble_gap_whitelist_t m_whitelist = - { - .pp_addrs = p_whitelist_addrs, - .pp_irks = p_whitelist_irks - }; -#else - // For SoftDevices v 3.x, this module does not need to cache a whitelist, but it needs to - // be aware of whether or not a whitelist has been set (e.g. using the Peer Manager) - // in order to start advertising with the proper advertising params (filter policy). - bool whitelist_in_use; -#endif -} ble_advertising_t; - -typedef struct -{ - uint32_t interval; - uint32_t timeout; - bool enabled; -} ble_adv_mode_config_t; - -/**@brief Initialization parameters for the Advertising Module. - * @details This structure is used to pass advertising options, advertising data, - * and an event handler to the Advertising Module during initialization. - */ -typedef struct -{ - ble_advdata_t advdata; /**< Advertising data: name, appearance, discovery flags, and more. */ - ble_advdata_t srdata; /**< Scan response data: Supplement to advertising data. */ - ble_adv_modes_config_t config; /**< Select which advertising modes and intervals will be utilized.*/ - ble_adv_evt_handler_t evt_handler; /**< Event handler that will be called upon advertising events. */ - ble_adv_error_handler_t error_handler; /**< Error handler that will propogate internal errors to the main applications. */ -} ble_advertising_init_t; - - -/**@brief Function for handling BLE events. - * - * @details This function must be called from the BLE stack event dispatcher for - * the module to handle BLE events that are relevant for the Advertising Module. - * - * @param[in] p_ble_evt BLE stack event. - * @param[in] p_adv Advertising module instance. - */ -void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_adv); - - -/**@brief Function for handling system events. - * - * @details This function must be called to handle system events that are relevant - * for the Advertising Module. Specifically, the advertising module can not use the - * softdevice as long as there are pending writes to the flash memory. This - * event handler is designed to delay advertising until there is no flash operation. - * - * @param[in] sys_evt System event. - * @param[in] p_adv Advertising module instance. - */ -void ble_advertising_on_sys_evt(uint32_t sys_evt, void * p_adv); - - -/**@brief Function for initializing the Advertising Module. - * - * @details Encodes the required advertising data and passes it to the stack. - * Also builds a structure to be passed to the stack when starting advertising. - * The supplied advertising data is copied to a local structure and is manipulated - * depending on what advertising modes are started in @ref ble_advertising_start. - * - * @param[out] p_advertising Advertising module instance. This structure must be supplied by - * the application. It is initialized by this function and will later - * be used to identify this particular module instance. - * @param[in] p_init Information needed to initialize the module. - * - * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. - */ -uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, - ble_advertising_init_t const * const p_init); - - - /**@brief Function for changing the connection settings tag that will be used for upcoming connections. - * - * @details See @ref sd_ble_cfg_set for more details about changing connection settings. If this - * function is never called, @ref BLE_CONN_CFG_TAG_DEFAULT will be used. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] ble_cfg_tag Configuration for the connection settings (see @ref sd_ble_cfg_set). - */ -void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, uint8_t ble_cfg_tag); - -/**@brief Function for starting advertising. - * - * @details You can start advertising in any of the advertising modes that you enabled - * during initialization. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] advertising_mode Advertising mode. - * - * @retval @ref NRF_SUCCESS On success, else an error code indicating reason for failure. - * @retval @ref NRF_ERROR_INVALID_STATE If the module is not initialized. - */ -uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, - ble_adv_mode_t advertising_mode); - - -/**@brief Function for setting the peer address. - * - * @details The peer address must be set by the application upon receiving a - * @ref BLE_ADV_EVT_PEER_ADDR_REQUEST event. Without the peer address, the directed - * advertising mode will not be run. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_peer_addr Pointer to a peer address. - * - * @retval @ref NRF_SUCCESS Successfully stored the peer address pointer in the advertising module. - * @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected. - */ -uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t * p_peer_addr); - - -/**@brief Function for setting a whitelist. - * - * @details The whitelist must be set by the application upon receiving a - * @ref BLE_ADV_EVT_WHITELIST_REQUEST event. Without the whitelist, the whitelist - * advertising for fast and slow modes will not be run. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_gap_addrs The list of GAP addresses to whitelist. - * @param[in] addr_cnt The number of GAP addresses to whitelist. - * @param[in] p_gap_irks The list of peer IRK to whitelist. - * @param[in] irk_cnt The number of peer IRK to whitelist. - * - * @retval @ref NRF_SUCCESS If the operation was successful. - * @retval @ref NRF_ERROR_INVALID_STATE If a call to this function was made without a - * BLE_ADV_EVT_WHITELIST_REQUEST event being received. - */ -uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t const * p_gap_addrs, - uint32_t addr_cnt, - ble_gap_irk_t const * p_gap_irks, - uint32_t irk_cnt); - - -/**@brief Function for disabling whitelist advertising. - * - * @details This function temporarily disables whitelist advertising. - * Calling this function resets the current time-out countdown. - * - * @param[in] p_advertising Advertising module instance. - * - * @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice. - */ -uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising); - - -/**@brief Function for changing advertising modes configuration. - * - * @details This function can be called if you wish to reconfigure the advertising modes that the - * advertising module will cycle through. Enable or disable modes as listed in - * @ref ble_adv_mode_t; or change the duration of the advertising and use of whitelist. - * - * Keep in mind that @ref ble_adv_modes_config_t is also supplied when calling - * @ref ble_advertising_init. Calling @ref ble_advertising_modes_config_set - * is only necessary if your application requires this behaviour to change. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_adv_modes_config Struct to keep track of disabled and enabled advertising modes, - * as well as time-outs and intervals. - */ -void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, - ble_adv_modes_config_t const * const p_adv_modes_config); -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_ADVERTISING_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c deleted file mode 100644 index d54d6ef773..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c +++ /dev/null @@ -1,986 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "sdk_common.h" - -#if NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) -#include "ble_db_discovery.h" -#include -#include "ble_srv_common.h" -#define NRF_LOG_MODULE_NAME ble_db_disc -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - -#define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */ -#define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */ -#define MODULE_INITIALIZED (m_initialized == true) /**< Macro designating whether the module has been initialized properly. */ - - -/**@brief Array of structures containing information about the registered application modules. */ -static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS]; - - -/**@brief Array of structures containing pending events to be sent to the application modules. - * - * @details Whenever a discovery related event is to be raised to a user module, it will be stored - * in this array first. When all services needed to be discovered have been - * discovered, all pending events will be sent to the corresponding user modules. - **/ -static struct -{ - ble_db_discovery_evt_t evt; /**< The pending event. */ - ble_db_discovery_evt_handler_t evt_handler; /**< The event handler which should be called to raise this event. */ -} m_pending_user_evts[DB_DISCOVERY_MAX_USERS]; - -static ble_db_discovery_evt_handler_t m_evt_handler; -static uint32_t m_pending_usr_evt_index; /**< The index to the pending user event array, pointing to the last added pending user event. */ -static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */ -static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */ - -/**@brief Function for fetching the event handler provided by a registered application module. - * - * @param[in] srv_uuid UUID of the service. - * - * @retval evt_handler Event handler of the module, registered for the given service UUID. - * @retval NULL If no event handler is found. - */ -static ble_db_discovery_evt_handler_t registered_handler_get(ble_uuid_t const * p_srv_uuid) -{ - for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) - { - if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid)) - { - return (m_evt_handler); - } - } - - return NULL; -} - - -/**@brief Function for storing the event handler provided by a registered application module. - * - * @param[in] p_srv_uuid The UUID of the service. - * @param[in] p_evt_handler The event handler provided by the application. - * - * @retval NRF_SUCCESS If the handler was stored or already present in the list. - * @retval NRF_ERROR_NO_MEM If there is no space left to store the handler. - */ -static uint32_t registered_handler_set(ble_uuid_t const * p_srv_uuid, - ble_db_discovery_evt_handler_t p_evt_handler) -{ - if (registered_handler_get(p_srv_uuid) != NULL) - { - return NRF_SUCCESS; - } - - if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS) - { - m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid; - m_num_of_handlers_reg++; - - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_NO_MEM; - } -} - - -/**@brief Function for sending all pending discovery events to the corresponding user modules. - */ -static void pending_user_evts_send(void) -{ - for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) - { - // Pass the event to the corresponding event handler. - m_pending_user_evts[i].evt_handler(&(m_pending_user_evts[i].evt)); - } - - m_pending_usr_evt_index = 0; -} - - -/**@brief Function for indicating error to the application. - * - * @details This function will fetch the event handler based on the UUID of the service being - * discovered. (The event handler is registered by the application beforehand). - * The error code is added to the pending events together with the event handler. - * If no event handler was found, then this function will do nothing. - * - * @param[in] p_db_discovery Pointer to the DB discovery structure. - * @param[in] err_code Error code that should be provided to the application. - * @param[in] conn_handle Connection Handle. - * - */ -static void discovery_error_evt_trigger(ble_db_discovery_t * p_db_discovery, - uint32_t err_code, - uint16_t conn_handle) -{ - ble_db_discovery_evt_handler_t p_evt_handler; - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); - - if (p_evt_handler != NULL) - { - ble_db_discovery_evt_t evt = - { - .conn_handle = conn_handle, - .evt_type = BLE_DB_DISCOVERY_ERROR, - .params.err_code = err_code, - }; - - p_evt_handler(&evt); - } -} - - -/**@brief Function for triggering a Discovery Complete or Service Not Found event to the - * application. - * - * @details This function will fetch the event handler based on the UUID of the service being - * discovered. (The event handler is registered by the application beforehand). - * It then triggers an event indicating the completion of the service discovery. - * If no event handler was found, then this function will do nothing. - * - * @param[in] p_db_discovery Pointer to the DB discovery structure. - * @param[in] is_srv_found Variable to indicate if the service was found at the peer. - * @param[in] conn_handle Connection Handle. - */ -static void discovery_complete_evt_trigger(ble_db_discovery_t * p_db_discovery, - bool is_srv_found, - uint16_t conn_handle) -{ - ble_db_discovery_evt_handler_t p_evt_handler; - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); - - if (p_evt_handler != NULL) - { - if (m_pending_usr_evt_index < DB_DISCOVERY_MAX_USERS) - { - // Insert an event into the pending event list. - m_pending_user_evts[m_pending_usr_evt_index].evt.conn_handle = conn_handle; - m_pending_user_evts[m_pending_usr_evt_index].evt.params.discovered_db = - *p_srv_being_discovered; - - if (is_srv_found) - { - m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type = - BLE_DB_DISCOVERY_COMPLETE; - } - else - { - m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type = - BLE_DB_DISCOVERY_SRV_NOT_FOUND; - } - - m_pending_user_evts[m_pending_usr_evt_index].evt_handler = p_evt_handler; - m_pending_usr_evt_index++; - - if (m_pending_usr_evt_index == m_num_of_handlers_reg) - { - // All registered modules have pending events. Send all pending events to the user - // modules. - pending_user_evts_send(); - } - else - { - // Too many events pending. Do nothing. (Ideally this should not happen.) - } - } - } -} - - -/**@brief Function for handling service discovery completion. - * - * @details This function will be used to determine if there are more services to be discovered, - * and if so, initiate the discovery of the next service. - * - * @param[in] p_db_discovery Pointer to the DB Discovery Structure. - * @param[in] conn_handle Connection Handle. - */ -static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle) -{ - p_db_discovery->discoveries_count++; - - // Check if more services need to be discovered. - if (p_db_discovery->discoveries_count < m_num_of_handlers_reg) - { - // Reset the current characteristic index since a new service discovery is about to start. - p_db_discovery->curr_char_ind = 0; - - // Initiate discovery of the next service. - p_db_discovery->curr_srv_ind++; - - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; - - // Reset the characteristic count in the current service to zero since a new service - // discovery is about to start. - p_srv_being_discovered->char_count = 0; - - NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, conn_handle); - - uint32_t err_code; - - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - SRV_DISC_START_HANDLE, - &(p_srv_being_discovered->srv_uuid)); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = conn_handle; - - return; - } - } - else - { - // No more service discovery is needed. - p_db_discovery->discovery_in_progress = false; - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = conn_handle; - } -} - - -/**@brief Function for finding out if a characteristic discovery should be performed after the - * last discovered characteristic. - * - * @details This function is used during the time of database discovery to find out if there is - * a need to do more characteristic discoveries. The value handles of the - * last discovered characteristic is compared with the end handle of the service. - * If the service handle is greater than one of the former characteristic handles, - * it means that a characteristic discovery is required. - * - * @param[in] p_db_discovery The pointer to the DB Discovery structure. - * @param[in] p_after_char The pointer to the last discovered characteristic. - * - * @retval True if a characteristic discovery is required. - * @retval False if a characteristic discovery is NOT required. - */ -static bool is_char_discovery_reqd(ble_db_discovery_t * p_db_discovery, - ble_gattc_char_t * p_after_char) -{ - if (p_after_char->handle_value < - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle) - { - // Handle value of the characteristic being discovered is less than the end handle of - // the service being discovered. There is a possibility of more characteristics being - // present. Hence a characteristic discovery is required. - return true; - } - - return false; -} - - -/**@brief Function to find out if a descriptor discovery is required. - * - * @details This function finds out if there is a possibility of existence of descriptors between - * current characteristic and the next characteristic. If so, this function will compute - * the handle range on which the descriptors may be present and will return it. - * If the current characteristic is the last known characteristic, then this function - * will use the service end handle to find out if the current characteristic can have - * descriptors. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_curr_char Pointer to the current characteristic. - * @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the - * caller knows that there is no characteristic after the current - * characteristic at the peer. - * @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the - * the peer. - * - * @retval True If a descriptor discovery is required. - * @retval False If a descriptor discovery is NOT required. - */ -static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery, - ble_gatt_db_char_t * p_curr_char, - ble_gatt_db_char_t * p_next_char, - ble_gattc_handle_range_t * p_handle_range) -{ - if (p_next_char == NULL) - { - // Current characteristic is the last characteristic in the service. Check if the value - // handle of the current characteristic is equal to the service end handle. - if ( - p_curr_char->characteristic.handle_value == - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle - ) - { - // No descriptors can be present for the current characteristic. p_curr_char is the last - // characteristic with no descriptors. - return false; - } - - p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; - - // Since the current characteristic is the last characteristic in the service, the end - // handle should be the end handle of the service. - p_handle_range->end_handle = - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle; - - return true; - } - - // p_next_char != NULL. Check for existence of descriptors between the current and the next - // characteristic. - if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl) - { - // No descriptors can exist between the two characteristic. - return false; - } - - p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; - p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1; - - return true; -} - - -/**@brief Function for performing characteristic discovery. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] conn_handle Connection Handle. - * - * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic - * discovery. Otherwise an error code. This function returns the error code returned - * by the SoftDevice API @ref sd_ble_gattc_characteristics_discover. - */ -static uint32_t characteristics_discover(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle) -{ - ble_gatt_db_srv_t * p_srv_being_discovered; - ble_gattc_handle_range_t handle_range; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_db_discovery->curr_char_ind != 0) - { - // This is not the first characteristic being discovered. Hence the 'start handle' to be - // used must be computed using the handle_value of the previous characteristic. - ble_gattc_char_t * p_prev_char; - uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic); - - handle_range.start_handle = p_prev_char->handle_value + 1; - } - else - { - // This is the first characteristic of this service being discovered. - handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle; - } - - handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle; - - return sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); -} - - -/**@brief Function for performing descriptor discovery, if required. - * - * @details This function will check if descriptor discovery is required and then perform it if - * needed. If no more descriptor discovery is required for the service, then the output - * parameter p_raise_discov_complete is set to true, indicating to the caller that a - * discovery complete event can be triggered to the application. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if - * the Discovery Complete event can be triggered to the - * application. - * @param[in] conn_handle Connection Handle. - * - * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor - * discovery, or if no more descriptor discovery is required. Otherwise an error code. - * This function returns the error code returned by the SoftDevice API @ref - * sd_ble_gattc_descriptors_discover. - */ -static uint32_t descriptors_discover(ble_db_discovery_t * p_db_discovery, - bool * p_raise_discov_complete, - uint16_t conn_handle) -{ - ble_gattc_handle_range_t handle_range; - ble_gatt_db_char_t * p_curr_char_being_discovered; - ble_gatt_db_srv_t * p_srv_being_discovered; - bool is_discovery_reqd = false; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_curr_char_being_discovered = - &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); - - if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) - { - // This is the last characteristic of this service. - is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery, - p_curr_char_being_discovered, - NULL, - &handle_range); - } - else - { - uint8_t i; - ble_gatt_db_char_t * p_next_char; - - for (i = p_db_discovery->curr_char_ind; i < p_srv_being_discovered->char_count; i++) - { - if (i == (p_srv_being_discovered->char_count - 1)) - { - // The current characteristic is the last characteristic in the service. - p_next_char = NULL; - } - else - { - p_next_char = &(p_srv_being_discovered->charateristics[i + 1]); - } - - // Check if it is possible for the current characteristic to have a descriptor. - if (is_desc_discovery_reqd(p_db_discovery, - p_curr_char_being_discovered, - p_next_char, - &handle_range)) - { - is_discovery_reqd = true; - break; - } - else - { - // No descriptors can exist. - p_curr_char_being_discovered = p_next_char; - p_db_discovery->curr_char_ind++; - } - } - } - - if (!is_discovery_reqd) - { - // No more descriptor discovery required. Discovery is complete. - // This informs the caller that a discovery complete event can be triggered. - *p_raise_discov_complete = true; - - return NRF_SUCCESS; - } - - *p_raise_discov_complete = false; - - return sd_ble_gattc_descriptors_discover(conn_handle, &handle_range); -} - - -/**@brief Function for handling primary service discovery response. - * - * @details This function will handle the primary service discovery response and start the - * discovery of characteristics within that service. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_primary_srv_discovery_rsp(ble_db_discovery_t * p_db_discovery, - ble_gattc_evt_t const * p_ble_gattc_evt) -{ - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - uint32_t err_code; - ble_gattc_evt_prim_srvc_disc_rsp_t const * p_prim_srvc_disc_rsp_evt; - - NRF_LOG_DEBUG("Found service UUID 0x%x.", p_srv_being_discovered->srv_uuid.uuid); - - p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp); - - p_srv_being_discovered->srv_uuid = p_prim_srvc_disc_rsp_evt->services[0].uuid; - p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range; - - err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - } - } - else - { - NRF_LOG_DEBUG("Service UUID 0x%x not found.", p_srv_being_discovered->srv_uuid.uuid); - // Trigger Service Not Found event to the application. - discovery_complete_evt_trigger(p_db_discovery, false, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } -} - - -/**@brief Function for handling characteristic discovery response. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_characteristic_discovery_rsp(ble_db_discovery_t * p_db_discovery, - ble_gattc_evt_t const * p_ble_gattc_evt) -{ - uint32_t err_code; - ble_gatt_db_srv_t * p_srv_being_discovered; - bool perform_desc_discov = false; - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - ble_gattc_evt_char_disc_rsp_t const * p_char_disc_rsp_evt; - - p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp); - - // Find out the number of characteristics that were previously discovered (in earlier - // characteristic discovery responses, if any). - uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count; - - // Find out the number of characteristics that are currently discovered (in the - // characteristic discovery response being handled). - uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count; - - // Check if the total number of discovered characteristics are supported by this module. - if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS) - { - // Update the characteristics count. - p_srv_being_discovered->char_count += num_chars_curr_disc; - } - else - { - // The number of characteristics discovered at the peer is more than the supported - // maximum. This module will store only the characteristics found up to this point. - p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS; - } - - uint32_t i; - uint32_t j; - - for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++) - { - p_srv_being_discovered->charateristics[i].characteristic = - p_char_disc_rsp_evt->chars[j]; - - p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].ext_prop_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].user_desc_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].report_ref_handle = BLE_GATT_HANDLE_INVALID; - } - - ble_gattc_char_t * p_last_known_char; - - p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic); - - // If no more characteristic discovery is required, or if the maximum number of supported - // characteristic per service has been reached, descriptor discovery will be performed. - if ( !is_char_discovery_reqd(p_db_discovery, p_last_known_char) - || (p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS)) - { - perform_desc_discov = true; - } - else - { - // Update the current characteristic index. - p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count; - - // Perform another round of characteristic discovery. - err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - } - } - else - { - // The previous characteristic discovery resulted in no characteristics. - // descriptor discovery should be performed. - perform_desc_discov = true; - } - - if (perform_desc_discov) - { - bool raise_discov_complete; - - p_db_discovery->curr_char_ind = 0; - - err_code = descriptors_discover(p_db_discovery, - &raise_discov_complete, - p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - if (raise_discov_complete) - { - // No more characteristics and descriptors need to be discovered. Discovery is complete. - // Send a discovery complete event to the user application. - NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" - " on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, - p_ble_gattc_evt->conn_handle); - - discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } - } -} - - -/**@brief Function for handling descriptor discovery response. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery, - const ble_gattc_evt_t * const p_ble_gattc_evt) -{ - const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt; - ble_gatt_db_srv_t * p_srv_being_discovered; - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp); - - ble_gatt_db_char_t * p_char_being_discovered = - &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - // The descriptor was found at the peer. - // Iterate through and collect CCCD, Extended Properties, - // User Description & Report Reference descriptor handles. - for (uint32_t i = 0; i < p_desc_disc_rsp_evt->count; i++) - { - switch (p_desc_disc_rsp_evt->descs[i].uuid.uuid) - { - case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: - p_char_being_discovered->cccd_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP: - p_char_being_discovered->ext_prop_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: - p_char_being_discovered->user_desc_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_REPORT_REF_DESCR: - p_char_being_discovered->report_ref_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - } - - /* Break if we've found all the descriptors we are looking for. */ - if (p_char_being_discovered->cccd_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->ext_prop_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->user_desc_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->report_ref_handle != BLE_GATT_HANDLE_INVALID) - { - break; - } - } - } - - bool raise_discov_complete = false; - - if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) - { - // No more characteristics and descriptors need to be discovered. Discovery is complete. - // Send a discovery complete event to the user application. - - raise_discov_complete = true; - } - else - { - // Begin discovery of descriptors for the next characteristic. - uint32_t err_code; - - p_db_discovery->curr_char_ind++; - - err_code = descriptors_discover(p_db_discovery, - &raise_discov_complete, - p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - } - - if (raise_discov_complete) - { - NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" - " on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, - p_ble_gattc_evt->conn_handle); - - discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } -} - - -uint32_t ble_db_discovery_init(const ble_db_discovery_evt_handler_t evt_handler) -{ - uint32_t err_code = NRF_SUCCESS; - VERIFY_PARAM_NOT_NULL(evt_handler); - - m_num_of_handlers_reg = 0; - m_initialized = true; - m_pending_usr_evt_index = 0; - m_evt_handler = evt_handler; - - return err_code; - -} - - -uint32_t ble_db_discovery_close() -{ - m_num_of_handlers_reg = 0; - m_initialized = false; - m_pending_usr_evt_index = 0; - - return NRF_SUCCESS; -} - - -uint32_t ble_db_discovery_evt_register(ble_uuid_t const * p_uuid) -{ - VERIFY_PARAM_NOT_NULL(p_uuid); - VERIFY_MODULE_INITIALIZED(); - - return registered_handler_set(p_uuid, m_evt_handler); -} - - -static uint32_t discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) -{ - uint32_t err_code; - ble_gatt_db_srv_t * p_srv_being_discovered; - - memset(p_db_discovery, 0x00, sizeof(ble_db_discovery_t)); - - p_db_discovery->conn_handle = conn_handle; - - m_pending_usr_evt_index = 0; - - p_db_discovery->discoveries_count = 0; - p_db_discovery->curr_srv_ind = 0; - p_db_discovery->curr_char_ind = 0; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; - - NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, conn_handle); - - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - SRV_DISC_START_HANDLE, - &(p_srv_being_discovered->srv_uuid)); - if (err_code != NRF_ERROR_BUSY) - { - VERIFY_SUCCESS(err_code); - p_db_discovery->discovery_in_progress = true; - p_db_discovery->discovery_pending = false; - } - else - { - p_db_discovery->discovery_in_progress = true; - p_db_discovery->discovery_pending = true; - } - - return NRF_SUCCESS; -} - - -uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) -{ - VERIFY_PARAM_NOT_NULL(p_db_discovery); - VERIFY_MODULE_INITIALIZED(); - - if (m_num_of_handlers_reg == 0) - { - // No user modules were registered. There are no services to discover. - return NRF_ERROR_INVALID_STATE; - } - - if (p_db_discovery->discovery_in_progress) - { - return NRF_ERROR_BUSY; - } - - return discovery_start(p_db_discovery, conn_handle); -} - - -/**@brief Function for handling disconnected event. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GAP event. - */ -static void on_disconnected(ble_db_discovery_t * p_db_discovery, - ble_gap_evt_t const * p_evt) -{ - if (p_evt->conn_handle == p_db_discovery->conn_handle) - { - p_db_discovery->discovery_in_progress = false; - p_db_discovery->discovery_pending = false; - p_db_discovery->conn_handle = BLE_CONN_HANDLE_INVALID; - } -} - - -void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, - void * p_context) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); - VERIFY_PARAM_NOT_NULL_VOID(p_context); - VERIFY_MODULE_INITIALIZED_VOID(); - - ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GATTC_EVT_DESC_DISC_RSP: - on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt)); - break; - - default: - break; - } - - if ( (p_db_discovery->discovery_pending) - && (p_ble_evt->header.evt_id >= BLE_GATTC_EVT_BASE) - && (p_ble_evt->header.evt_id <= BLE_GATTC_EVT_LAST) - && (p_ble_evt->evt.gattc_evt.conn_handle == p_db_discovery->conn_handle)) - { - (void)discovery_start(p_db_discovery, p_db_discovery->conn_handle); - } -} -#endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h deleted file mode 100644 index e1fe1f554e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_db_discovery Database Discovery - * @{ - * @ingroup ble_sdk_lib - * @brief Database discovery module. - * - * @details This module contains the APIs and types exposed by the DB Discovery module. These APIs - * and types can be used by the application to perform discovery of a service and its - * characteristics at the peer server. This module can also be used to discover the - * desired services in multiple remote devices. - * - * @warning The maximum number of characteristics per service that can be discovered by this module - * is determined by the number of characteristics in the service structure defined in - * db_disc_config.h. If the peer has more than the supported number of characteristics, then - * the first found will be discovered and any further characteristics will be ignored. Only the - * following descriptors will be searched for at the peer: Client Characteristic Configuration, - * Characteristic Extended Properties, Characteristic User Description, and Report Reference. - * - * @note Presently only one instance of a Primary Service can be discovered by this module. If - * there are multiple instances of the service at the peer, only the first instance - * of it at the peer is fetched and returned to the application. - * - * @note The application must propagate BLE stack events to this module by calling - * ble_db_discovery_on_ble_evt(). - * - */ - -#ifndef BLE_DB_DISCOVERY_H__ -#define BLE_DB_DISCOVERY_H__ - -#include -#include -#include "nrf_error.h" -#include "nrf_ble.h" -#include "ble_gattc.h" -#include "ble_gatt_db.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a ble_db_discovery instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define BLE_DB_DISCOVERY_DEF(_name) \ -static ble_db_discovery_t _name = {.discovery_in_progress = 0, \ - .discovery_pending = 0, \ - .conn_handle = BLE_CONN_HANDLE_INVALID}; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - BLE_DB_DISC_BLE_OBSERVER_PRIO, \ - ble_db_discovery_on_ble_evt, &_name) - -/** @brief Macro for defining multiple ble_db_discovery instances. - * - * @param _name Name of the array of instances. - * @param _cnt Number of instances to define. - */ -#define BLE_DB_DISCOVERY_ARRAY_DEF(_name, _cnt) \ -static ble_db_discovery_t _name[_cnt] = {{.discovery_in_progress = 0, \ - .discovery_pending = 0, \ - .conn_handle = BLE_CONN_HANDLE_INVALID}}; \ -NRF_SDH_BLE_OBSERVERS(_name ## _obs, \ - BLE_DB_DISC_BLE_OBSERVER_PRIO, \ - ble_db_discovery_on_ble_evt, &_name, _cnt) - -#define BLE_DB_DISCOVERY_MAX_SRV 6 /**< Maximum number of services supported by this module. This also indicates the maximum number of users allowed to be registered to this module (one user per service). */ - - -/**@brief DB Discovery event type. */ -typedef enum -{ - BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the discovery of one service is complete. */ - BLE_DB_DISCOVERY_ERROR, /**< Event indicating that an internal error has occurred in the DB Discovery module. This could typically be because of the SoftDevice API returning an error code during the DB discover.*/ - BLE_DB_DISCOVERY_SRV_NOT_FOUND, /**< Event indicating that the service was not found at the peer.*/ - BLE_DB_DISCOVERY_AVAILABLE /**< Event indicating that the DB discovery instance is available.*/ -} ble_db_discovery_evt_type_t; - -/**@brief Structure for holding the information related to the GATT database at the server. - * - * @details This module identifies a remote database. Use one instance of this structure per - * connection. - * - * @warning This structure must be zero-initialized. - */ -typedef struct -{ - ble_gatt_db_srv_t services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. This is intended for internal use during service discovery.*/ - uint8_t srv_count; /**< Number of services at the peers GATT database.*/ - uint8_t curr_char_ind; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/ - uint8_t curr_srv_ind; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/ - bool discovery_in_progress; /**< Variable to indicate if there is a service discovery in progress. */ - bool discovery_pending; /**< Discovery was requested, but could not start because the SoftDevice was busy. */ - uint8_t discoveries_count; /**< Number of service discoveries made, both successful and unsuccessful. */ - uint16_t conn_handle; /**< Connection handle on which the discovery is started*/ -} ble_db_discovery_t; - -/**@brief Structure containing the event from the DB discovery module to the application. */ -typedef struct -{ - ble_db_discovery_evt_type_t evt_type; /**< Type of event. */ - uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */ - union - { - ble_gatt_db_srv_t discovered_db; /**< Structure containing the information about the GATT Database at the server. This will be filled when the event type is @ref BLE_DB_DISCOVERY_COMPLETE. The UUID field of this will be filled when the event type is @ref BLE_DB_DISCOVERY_SRV_NOT_FOUND. */ - uint32_t err_code; /**< nRF Error code indicating the type of error which occurred in the DB Discovery module. This will be filled when the event type is @ref BLE_DB_DISCOVERY_ERROR. */ - } params; -} ble_db_discovery_evt_t; - -/**@brief DB Discovery event handler type. */ -typedef void (* ble_db_discovery_evt_handler_t)(ble_db_discovery_evt_t * p_evt); - - -/**@brief Function for initializing the DB Discovery module. - * - * @param[in] evt_handler Event handler to be called by the DB discovery module when any event - * related to discovery of the registered service occurs. - * - * @retval NRF_SUCCESS On successful initialization. - * @retval NRF_ERROR_NULL If the handler was NULL. - */ -uint32_t ble_db_discovery_init(ble_db_discovery_evt_handler_t evt_handler); - - -/**@brief Function for closing the DB Discovery module. - * - * @details This function will clear up any internal variables and states maintained by the - * module. To re-use the module after calling this function, the function @ref - * ble_db_discovery_init must be called again. - * - * @retval NRF_SUCCESS Operation success. - */ -uint32_t ble_db_discovery_close(void); - - -/**@brief Function for registering with the DB Discovery module. - * - * @details The application can use this function to inform which service it is interested in - * discovering at the server. - * - * @param[in] p_uuid Pointer to the UUID of the service to be discovered at the server. - * - * @note The total number of services that can be discovered by this module is @ref - * BLE_DB_DISCOVERY_MAX_SRV. This effectively means that the maximum number of - * registrations possible is equal to the @ref BLE_DB_DISCOVERY_MAX_SRV. - * - * @retval NRF_SUCCESS Operation success. - * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. - * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the - * @ref ble_db_discovery_init. - * @retval NRF_ERROR_NO_MEM The maximum number of registrations allowed by this module - * has been reached. - */ -uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid); - - -/**@brief Function for starting the discovery of the GATT database at the server. - * - * @param[out] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] conn_handle The handle of the connection for which the discovery should be - * started. - * - * @retval NRF_SUCCESS Operation success. - * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. - * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the - * @ref ble_db_discovery_init, or without calling - * @ref ble_db_discovery_evt_register. - * @retval NRF_ERROR_BUSY If a discovery is already in progress using - * @p p_db_discovery. Use a different @ref ble_db_discovery_t - * structure, or wait for a DB Discovery event before retrying. - * - * @return This API propagates the error code returned by the - * SoftDevice API @ref sd_ble_gattc_primary_services_discover. - */ -uint32_t ble_db_discovery_start(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle); - - -/**@brief Function for handling the Application's BLE Stack events. - * - * @param[in] p_ble_evt Pointer to the BLE event received. - * @param[in,out] p_context Pointer to the DB Discovery structure. - */ -void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, - void * p_context); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DB_DISCOVERY_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c deleted file mode 100644 index 3aa8f1c587..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c +++ /dev/null @@ -1,942 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_DTM) -#include "ble_dtm.h" -#include "ble_dtm_hw.h" -#include -#include -#include "nrf.h" - -#define DTM_HEADER_OFFSET 0 /**< Index where the header of the pdu is located. */ -#define DTM_HEADER_SIZE 2 /**< Size of PDU header. */ -#define DTM_PAYLOAD_MAX_SIZE 255 /**< Maximum payload size allowed during dtm execution. */ -#define DTM_LENGTH_OFFSET (DTM_HEADER_OFFSET + 1) /**< Index where the length of the payload is encoded. */ -#define DTM_PDU_MAX_MEMORY_SIZE (DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE) /**< Maximum PDU size allowed during dtm execution. */ -#define DTM_ON_AIR_OVERHEAD_SIZE 10 /**< Size of the packet on air without the payload (preamble + sync word + type + RFU + length + CRC). */ - -#define RX_MODE true /**< Constant defining RX mode for radio during dtm test. */ -#define TX_MODE false /**< Constant defining TX mode for radio during dtm test. */ - -#define PHYS_CH_MAX 39 /**< Maximum number of valid channels in BLE. */ - -// Values that for now are "constants" - they could be configured by a function setting them, -// but most of these are set by the BLE DTM standard, so changing them is not relevant. -#define RFPHY_TEST_0X0F_REF_PATTERN 0x0f /**< RF-PHY test packet patterns, for the repeated octet packets. */ -#define RFPHY_TEST_0X55_REF_PATTERN 0x55 /**< RF-PHY test packet patterns, for the repeated octet packets. */ -#define RFPHY_TEST_0XFF_REF_PATTERN 0xFF /**< RF-PHY test packet patterns, for the repeated octet packets. */ - -#define PRBS9_CONTENT {0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, \ - 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, \ - 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, \ - 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, \ - 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, \ - 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, \ - 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, \ - 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, \ - 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, \ - 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, \ - 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, \ - 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, \ - 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, \ - 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, \ - 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, \ - 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, \ - 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, \ - 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, \ - 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, \ - 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, \ - 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, \ - 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, \ - 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, \ - 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, \ - 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, \ - 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, \ - 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, \ - 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, \ - 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, \ - 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, \ - 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, \ - 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7} /**< The PRBS9 sequence used as packet payload. - The bytes in the sequence is in the right order, but the bits of each byte in the array is reverse. - of that found by running the PRBS9 algorithm. This is because of the endianess of the nRF5 radio. */ - -/**@brief Structure holding the PDU used for transmitting/receiving a PDU. - */ -typedef struct -{ - uint8_t content[DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE]; /**< PDU packet content. */ -} pdu_type_t; - -/**@brief States used for the DTM test implementation. - */ -typedef enum -{ - STATE_UNINITIALIZED, /**< The DTM is uninitialized. */ - STATE_IDLE, /**< State when system has just initialized, or current test has completed. */ - STATE_TRANSMITTER_TEST, /**< State used when a DTM Transmission test is running. */ - STATE_CARRIER_TEST, /**< State used when a DTM Carrier test is running (Vendor specific test). */ - STATE_RECEIVER_TEST /**< State used when a DTM Receive test is running. */ -} state_t; - - -// Internal variables set as side effects of commands or events. -static state_t m_state = STATE_UNINITIALIZED; /**< Current machine state. */ -static uint16_t m_rx_pkt_count; /**< Number of valid packets received. */ -static pdu_type_t m_pdu; /**< PDU to be sent. */ -static uint16_t m_event; /**< current command status - initially "ok", may be set if error detected, or to packet count. */ -static bool m_new_event; /**< Command has been processed - number of not yet reported event bytes. */ -static uint32_t m_packet_length; /**< Payload length of transmitted PDU, bits 2:7 of 16-bit dtm command. */ -static dtm_pkt_type_t m_packet_type; /**< Bits 0..1 of 16-bit transmit command, or 0xFFFFFFFF. */ -static dtm_freq_t m_phys_ch; /**< 0..39 physical channel number (base 2402 MHz, Interval 2 MHz), bits 8:13 of 16-bit dtm command. */ -static uint32_t m_current_time = 0; /**< Counter for interrupts from timer to ensure that the 2 bytes forming a DTM command are received within the time window. */ - -// Nordic specific configuration values (not defined by BLE standard). -// Definition of initial values found in ble_dtm.h -static int32_t m_tx_power = DEFAULT_TX_POWER; /**< TX power for transmission test, default to maximum value (+4 dBm). */ -static NRF_TIMER_Type * mp_timer = DEFAULT_TIMER; /**< Timer to be used. */ -static IRQn_Type m_timer_irq = DEFAULT_TIMER_IRQn; /**< which interrupt line to clear on every timeout */ - -static uint8_t const m_prbs_content[] = PRBS9_CONTENT; /**< Pseudo-random bit sequence defined by the BLE standard. */ -static uint8_t m_packetHeaderLFlen = 8; /**< Length of length field in packet Header (in bits). */ -static uint8_t m_packetHeaderS0len = 1; /**< Length of S0 field in packet Header (in bytes). */ -static uint8_t m_packetHeaderS1len = 0; /**< Length of S1 field in packet Header (in bits). */ -static uint8_t m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; /**< Length of the preamble. */ - -static uint8_t m_crcConfSkipAddr = 1; /**< Leave packet address field out of CRC calculation. */ -static uint8_t m_static_length = 0; /**< Number of bytes sent in addition to the var.length payload. */ -static uint32_t m_balen = 3; /**< Base address length in bytes. */ -static uint32_t m_endian = RADIO_PCNF1_ENDIAN_Little; /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */ -static uint32_t m_whitening = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */ -static uint8_t m_crcLength = RADIO_CRCCNF_LEN_Three; /**< CRC Length (in bytes). */ -static uint32_t m_address = 0x71764129; /**< Address. */ -static uint32_t m_crc_poly = 0x0000065B; /**< CRC polynomial. */ -static uint32_t m_crc_init = 0x00555555; /**< Initial value for CRC calculation. */ -static uint8_t m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; /**< nRF51 specific radio mode value. */ -static uint32_t m_txIntervaluS = 2500; /**< Time between start of Tx packets (in uS). */ - - -/**@brief Function for verifying that a received PDU has the expected structure and content. - */ -static bool check_pdu(void) -{ - uint8_t k; // Byte pointer for running through PDU payload - uint8_t pattern; // Repeating octet value in payload - dtm_pkt_type_t pdu_packet_type; // Note: PDU packet type is a 4-bit field in HCI, but 2 bits in BLE DTM - uint32_t length = 0; - - pdu_packet_type = (dtm_pkt_type_t)(m_pdu.content[DTM_HEADER_OFFSET] & 0x0F); - length = m_pdu.content[DTM_LENGTH_OFFSET]; - - // Check that the length is valid. - if (length > DTM_PAYLOAD_MAX_SIZE) - { - return false; - } - - // If the 1Mbit or 2Mbit radio mode is active, check that one of the three valid uncoded DTM packet types are selected. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0X55)) - { - return false; - } - -#ifdef NRF52840_XXAA - // If a long range radio mode is active, check that one of the four valid coded DTM packet types are selected. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0XFF)) - { - return false; - } -#endif - - if (pdu_packet_type == DTM_PKT_PRBS9) - { - // Payload does not consist of one repeated octet; must compare ir with entire block into - return (memcmp(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, length) == 0); - } - - if (pdu_packet_type == DTM_PKT_0X0F) - { - pattern = RFPHY_TEST_0X0F_REF_PATTERN; - } - else if (pdu_packet_type == DTM_PKT_0X55) - { - pattern = RFPHY_TEST_0X55_REF_PATTERN; - } - else if (pdu_packet_type == DTM_PKT_0XFF) - { - pattern = RFPHY_TEST_0XFF_REF_PATTERN; - } - else - { - // No valid packet type set. - return false; - } - - for (k = 0; k < length; k++) - { - // Check repeated pattern filling the PDU payload - if (m_pdu.content[k + 2] != pattern) - { - return false; - } - } - return true; -} - - -/**@brief Function for turning off the radio after a test. - * Also called after test done, to be ready for next test. - */ -static void radio_reset(void) -{ - NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk | PPI_CHENCLR_CH1_Msk; - - NRF_RADIO->SHORTS = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->TASKS_DISABLE = 1; - - while (NRF_RADIO->EVENTS_DISABLED == 0) - { - // Do nothing - } - - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->TASKS_RXEN = 0; - NRF_RADIO->TASKS_TXEN = 0; - - m_rx_pkt_count = 0; -} - - -/**@brief Function for initializing the radio for DTM. - */ -static uint32_t radio_init(void) -{ - if (dtm_radio_validate(m_tx_power, m_radio_mode) != DTM_SUCCESS) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - // Turn off radio before configuring it - radio_reset(); - - NRF_RADIO->TXPOWER = m_tx_power; - NRF_RADIO->MODE = m_radio_mode << RADIO_MODE_MODE_Pos; - - // Set the access address, address0/prefix0 used for both Rx and Tx address - NRF_RADIO->PREFIX0 &= ~RADIO_PREFIX0_AP0_Msk; - NRF_RADIO->PREFIX0 |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk; - NRF_RADIO->BASE0 = m_address << 8; - NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos; - NRF_RADIO->TXADDRESS = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk; - - // Configure CRC calculation - NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) | - (m_crcLength << RADIO_CRCCNF_LEN_Pos); - - if (m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) - { - // Non-coded PHY - NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | - (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | - (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | - (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); - } -#ifdef NRF52840_XXAA - else - { - // Coded PHY (Long range) - NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | - (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | - (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | - (3 << RADIO_PCNF0_TERMLEN_Pos) | - (2 << RADIO_PCNF0_CILEN_Pos) | - (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); - } -#endif - - NRF_RADIO->PCNF1 = (m_whitening << RADIO_PCNF1_WHITEEN_Pos) | - (m_endian << RADIO_PCNF1_ENDIAN_Pos) | - (m_balen << RADIO_PCNF1_BALEN_Pos) | - (m_static_length << RADIO_PCNF1_STATLEN_Pos) | - (DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos); - - return DTM_SUCCESS; -} - - -/**@brief Function for preparing the radio. At start of each test: Turn off RF, clear interrupt flags of RF, initialize the radio - * at given RF channel. - * - *@param[in] rx boolean indicating if radio should be prepared in rx mode (true) or tx mode. - */ -static void radio_prepare(bool rx) -{ - dtm_turn_off_test(); - NRF_RADIO->CRCPOLY = m_crc_poly; - NRF_RADIO->CRCINIT = m_crc_init; - NRF_RADIO->FREQUENCY = (m_phys_ch << 1) + 2; // Actual frequency (MHz): 2400 + register value - NRF_RADIO->PACKETPTR = (uint32_t)&m_pdu; // Setting packet pointer will start the radio - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->SHORTS = (1 << RADIO_SHORTS_READY_START_Pos) | // Shortcut between READY event and START task - (1 << RADIO_SHORTS_END_DISABLE_Pos); // Shortcut between END event and DISABLE task - - if (rx) - { - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->TASKS_RXEN = 1; // shorts will start radio in RX mode when it is ready - } - else // tx - { - NRF_RADIO->TXPOWER = m_tx_power; - } -} - - -/**@brief Function for terminating the ongoing test (if any) and closing down the radio. - */ -static void dtm_test_done(void) -{ - dtm_turn_off_test(); - NRF_PPI->CHENCLR = 0x01; - NRF_PPI->CH[0].EEP = 0; // Break connection from timer to radio to stop transmit loop - NRF_PPI->CH[0].TEP = 0; - - radio_reset(); - m_state = STATE_IDLE; -} - - -/**@brief Function for configuring the timer for 625us cycle time. - */ -static uint32_t timer_init(void) -{ - // Use 16MHz from external crystal - // This could be customized for RC/Xtal, or even to use a 32 kHz crystal - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) - { - // Do nothing while waiting for the clock to start - } - - mp_timer->TASKS_STOP = 1; // Stop timer, if it was running - mp_timer->TASKS_CLEAR = 1; - mp_timer->MODE = TIMER_MODE_MODE_Timer; // Timer mode (not counter) - mp_timer->EVENTS_COMPARE[0] = 0; // clean up possible old events - mp_timer->EVENTS_COMPARE[1] = 0; - mp_timer->EVENTS_COMPARE[2] = 0; - mp_timer->EVENTS_COMPARE[3] = 0; - - // Timer is polled, but enable the compare0 interrupt in order to wakeup from CPU sleep - mp_timer->INTENSET = TIMER_INTENSET_COMPARE0_Msk; - mp_timer->SHORTS = 1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos; // Clear the count every time timer reaches the CCREG0 count - mp_timer->PRESCALER = 4; // Input clock is 16MHz, timer clock = 2 ^ prescale -> interval 1us - mp_timer->CC[0] = m_txIntervaluS; // 625uS with 1MHz clock to the timer - mp_timer->CC[1] = UART_POLL_CYCLE; // Depends on the baud rate of the UART. Default baud rate of 19200 will result in a 260uS time with 1MHz clock to the timer - mp_timer->TASKS_START = 1; // Start the timer - it will be running continuously - m_current_time = 0; - return DTM_SUCCESS; -} - - -/**@brief Function for handling vendor specific commands. - * Used when packet type is set to Vendor specific. - * The length field is used for encoding vendor specific command. - * The frequency field is used for encoding vendor specific options to the command. - * - * @param[in] vendor_cmd Vendor specific command to be executed. - * @param[in] vendor_option Vendor specific option to the vendor command. - * - * @return DTM_SUCCESS or one of the DTM_ERROR_ values - */ -static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd, dtm_freq_t vendor_option) -{ - switch (vendor_cmd) - { - // nRFgo Studio uses CARRIER_TEST_STUDIO to indicate a continuous carrier without - // a modulated signal. - case CARRIER_TEST: - case CARRIER_TEST_STUDIO: - // Not a packet type, but used to indicate that a continuous carrier signal - // should be transmitted by the radio. - radio_prepare(TX_MODE); - - dtm_constant_carrier(); - - // Shortcut between READY event and START task - NRF_RADIO->SHORTS = 1 << RADIO_SHORTS_READY_START_Pos; - - // Shortcut will start radio in Tx mode when it is ready - NRF_RADIO->TASKS_TXEN = 1; - m_state = STATE_CARRIER_TEST; - break; - - case SET_TX_POWER: - if (!dtm_set_txpower(vendor_option)) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - break; - - case SELECT_TIMER: - if (!dtm_set_timer(vendor_option)) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - break; - } - // Event code is unchanged, successful - return DTM_SUCCESS; -} - - -static uint32_t dtm_packet_interval_calculate(uint32_t test_payload_length, uint32_t mode) -{ - uint32_t test_packet_length = 0; // [us] NOTE: bits are us at 1Mbit - uint32_t packet_interval = 0; // us - uint32_t overhead_bits = 0; // bits - - /* packet overhead - * see BLE [Vol 6, Part F] page 213 - * 4.1 LE TEST PACKET FORMAT */ - if (mode == RADIO_MODE_MODE_Ble_2Mbit) - { - // 16 preamble - // 32 sync word - // 8 PDU header, actually packetHeaderS0len * 8 - // 8 PDU length, actually packetHeaderLFlen - // 24 CRC - overhead_bits = 88; // 11 bytes - } - else if (mode == RADIO_MODE_MODE_Ble_1Mbit) - { - // 8 preamble - // 32 sync word - // 8 PDU header, actually packetHeaderS0len * 8 - // 8 PDU length, actually packetHeaderLFlen - // 24 CRC - overhead_bits = 80; // 10 bytes - } -#ifdef NRF52840_XXAA - else if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) - { - // 80 preamble - // 32 * 8 sync word coding=8 - // 2 * 8 Coding indicator, coding=8 - // 3 * 8 TERM1 coding=8 - // 8 * 8 PDU header, actually packetHeaderS0len * 8 coding=8 - // 8 * 8 PDU length, actually packetHeaderLFlen coding=8 - // 24 * 8 CRC coding=8 - // 3 * 8 TERM2 coding=8 - overhead_bits = 720; // 90 bytes - } - else if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) - { - // 80 preamble - // 32 * 8 sync word coding=8 - // 2 * 8 Coding indicator, coding=8 - // 3 * 8 TERM 1 coding=8 - // 8 * 2 PDU header, actually packetHeaderS0len * 8 coding=2 - // 8 * 2 PDU length, actually packetHeaderLFlen coding=2 - // 24 * 2 CRC coding=2 - // 3 * 2 TERM2 coding=2 - // NOTE: this makes us clock out 46 bits for CI + TERM1 + TERM2 - // assumption the radio will handle this - overhead_bits = 462; // 57.75 bytes - } -#endif - /* add PDU payload test_payload length */ - test_packet_length = (test_payload_length * 8); // in bits -#ifdef NRF52840_XXAA - // account for the encoding of PDU - if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) - { - test_packet_length *= 8; // 1 to 8 encoding - } - if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) - { - test_packet_length *= 2; // 1 to 2 encoding - } -#endif - // add overhead calculated above - test_packet_length += overhead_bits; - // we remember this bits are us in 1Mbit - if (mode == RADIO_MODE_MODE_Ble_2Mbit) - { - test_packet_length /= 2; // double speed - } - - /* - * packet_interval = ceil((test_packet_length+249)/625)*625 - * NOTE: To avoid floating point an equivalent calculation is used. - */ - uint32_t i = 0; - uint32_t timeout = 0; - do - { - i++; - timeout = i * 625; - } while (test_packet_length + 249 > timeout); - packet_interval = i * 625; - - return packet_interval; -} - - -uint32_t dtm_init(void) -{ - if ((timer_init() != DTM_SUCCESS) || (radio_init() != DTM_SUCCESS)) - { - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - m_new_event = false; - m_state = STATE_IDLE; - m_packet_length = 0; - - // Enable wake-up on event - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - - return DTM_SUCCESS; -} - - -uint32_t dtm_wait(void) -{ - // Enable wake-up on event - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - - for (;;) - { - // Event may be the reception of a packet - - // handle radio first, to give it highest priority: - if (NRF_RADIO->EVENTS_END != 0) - { - NRF_RADIO->EVENTS_END = 0; - NVIC_ClearPendingIRQ(RADIO_IRQn); - - if (m_state == STATE_RECEIVER_TEST) - { - NRF_RADIO->TASKS_RXEN = 1; - if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu()) - { - // Count the number of successfully received packets - m_rx_pkt_count++; - } - // Note that failing packets are simply ignored (CRC or contents error). - - // Zero fill all pdu fields to avoid stray data - memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); - } - // If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!) - } - - // Check for timeouts: - if (mp_timer->EVENTS_COMPARE[0] != 0) - { - mp_timer->EVENTS_COMPARE[0] = 0; - } - else if (mp_timer->EVENTS_COMPARE[1] != 0) - { - // Reset timeout event flag for next iteration. - mp_timer->EVENTS_COMPARE[1] = 0; - NVIC_ClearPendingIRQ(m_timer_irq); - return ++m_current_time; - } - - // Other events: No processing - } -} - -uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload) -{ - // Save specified packet in static variable for tx/rx functions to use. - // Note that BLE conformance testers always use full length packets. - m_packet_length = (m_packet_length & 0xC0) | ((uint8_t)length & 0x3F); - m_packet_type = payload; - m_phys_ch = freq; - - // If 1 Mbit or 2 Mbit radio mode is in use check for Vendor Specific payload. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && payload == DTM_PKT_VENDORSPECIFIC) - { - /* Note that in a HCI adaption layer, as well as in the DTM PDU format, - the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not - support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC, - to avoid the risk of confusion, should the code be extended to greater coverage. - */ - m_packet_type = DTM_PKT_TYPE_VENDORSPECIFIC; - } - - // Clean out any non-retrieved event that might linger from an earlier test - m_new_event = true; - - // Set default event; any error will set it to LE_TEST_STATUS_EVENT_ERROR - m_event = LE_TEST_STATUS_EVENT_SUCCESS; - - if (m_state == STATE_UNINITIALIZED) - { - // Application has not explicitly initialized DTM, - return DTM_ERROR_UNINITIALIZED; - } - - if (cmd == LE_TEST_SETUP) - { - // Note that timer will continue running after a reset - dtm_test_done(); - if (freq == LE_TEST_SETUP_RESET) - { - if (length != 0x00) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // Reset the packet length upper bits. - m_packet_length = 0; - - // Reset the selected PHY to 1Mbit - m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - } - else if (freq == LE_TEST_SETUP_SET_UPPER) - { - if (length > 0x03) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - m_packet_length = length << 6; - } - else if (freq == LE_TEST_SETUP_SET_PHY) - { - switch (length) - { - case LE_PHY_1M: - m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - - return radio_init(); - - case LE_PHY_2M: - m_radio_mode = RADIO_MODE_MODE_Ble_2Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_16bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - - return radio_init(); - - case LE_PHY_LE_CODED_S8: -#ifdef NRF52840_XXAA - m_radio_mode = RADIO_MODE_MODE_Ble_LR125Kbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; - - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); - - return radio_init(); -#else - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; -#endif // NRF52840_XXAA - case LE_PHY_LE_CODED_S2: -#ifdef NRF52840_XXAA - m_radio_mode = RADIO_MODE_MODE_Ble_LR500Kbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; - - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); - - return radio_init(); -#else - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; -#endif - default: - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - } - else if(freq == LE_TEST_SETUP_SELECT_MODULATION) - { - if (length > 0x01) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // Only standard modulation is supported. - } - else if (freq == LE_TEST_SETUP_READ_SUPPORTED) - { - if (length != 0x00) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // 0XXXXXXXXXXX0110 indicate that 2Mbit and DLE is supported and stable modulation is not supported (No nRF5 device supports this). - m_event = 0x0006; - } - else if (freq == LE_TEST_SETUP_READ_MAX) - { - // Read max supported value. - switch (length) - { - case 0x00: - // Read supportedMaxTxOctets - m_event = 0x01FE; - break; - - case 0x01: - // Read supportedMaxTxTime - m_event = 0x4290; - break; - - case 0x02: - // Read supportedMaxRxOctets - m_event = 0x01FE; - break; - - case 0x03: - // Read supportedMaxRxTime - m_event = 0x4290; - break; - - default: - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - } - else - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - return DTM_SUCCESS; - } - - if (cmd == LE_TEST_END) - { - if (m_state == STATE_IDLE) - { - // Sequencing error - only rx or tx test may be ended! - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_INVALID_STATE; - } - m_event = LE_PACKET_REPORTING_EVENT | m_rx_pkt_count; - dtm_test_done(); - return DTM_SUCCESS; - } - - if (m_state != STATE_IDLE) - { - // Sequencing error - only TEST_END/RESET are legal while test is running - // Note: State is unchanged; ongoing test not affected - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_INVALID_STATE; - } - - // Check for illegal values of m_phys_ch. Skip the check if the packet is vendor spesific. - if (payload != DTM_PKT_VENDORSPECIFIC && m_phys_ch > PHYS_CH_MAX) - { - // Parameter error - // Note: State is unchanged; ongoing test not affected - m_event = LE_TEST_STATUS_EVENT_ERROR; - - return DTM_ERROR_ILLEGAL_CHANNEL; - } - - m_rx_pkt_count = 0; - - if (cmd == LE_RECEIVER_TEST) - { - // Zero fill all pdu fields to avoid stray data from earlier test run - memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); - radio_prepare(RX_MODE); // Reinitialize "everything"; RF interrupts OFF - m_state = STATE_RECEIVER_TEST; - return DTM_SUCCESS; - } - - if (cmd == LE_TRANSMITTER_TEST) - { - // Check for illegal values of m_packet_length. Skip the check if the packet is vendor spesific. - if (m_packet_type != DTM_PKT_TYPE_VENDORSPECIFIC && m_packet_length > DTM_PAYLOAD_MAX_SIZE) - { - // Parameter error - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_LENGTH; - } - - - m_pdu.content[DTM_LENGTH_OFFSET] = m_packet_length; - // Note that PDU uses 4 bits even though BLE DTM uses only 2 (the HCI SDU uses all 4) - switch (m_packet_type) - { - case DTM_PKT_PRBS9: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_PRBS9; - // Non-repeated, must copy entire pattern to PDU - memcpy(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, m_packet_length); - break; - - case DTM_PKT_0X0F: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X0F; - // Bit pattern 00001111 repeated - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X0F_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_0X55: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X55; - // Bit pattern 01010101 repeated - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X55_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_0XFF: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0XFF; - // Bit pattern 11111111 repeated. Only available in coded PHY (Long range). - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0XFF_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_TYPE_VENDORSPECIFIC: - // The length field is for indicating the vendor specific command to execute. - // The frequency field is used for vendor specific options to the command. - return dtm_vendor_specific_pkt(length, freq); - - default: - // Parameter error - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - // Initialize CRC value, set channel: - radio_prepare(TX_MODE); - - // Set the timer to the correct period. The delay between each packet is described in the - // Bluetooth Core Spsification version 4.2 Vol. 6 Part F Section 4.1.6. - mp_timer->CC[0] = dtm_packet_interval_calculate(m_packet_length, m_radio_mode); - - // Configure PPI so that timer will activate radio every 625 us - NRF_PPI->CH[0].EEP = (uint32_t)&mp_timer->EVENTS_COMPARE[0]; - NRF_PPI->CH[0].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; - NRF_PPI->CHENSET = 0x01; - m_state = STATE_TRANSMITTER_TEST; - } - return DTM_SUCCESS; -} - - -bool dtm_event_get(dtm_event_t *p_dtm_event) -{ - bool was_new = m_new_event; - // mark the current event as retrieved - m_new_event = false; - *p_dtm_event = m_event; - // return value indicates whether this value was already retrieved. - return was_new; -} - - -// ================================================================================================= -// Configuration functions (only for parameters not definitely determined by the BLE DTM standard). -// These functions return true if successful, false if value could not be set - - -/**@brief Function for configuring the output power for transmitter test. - This function may be called directly, or through dtm_cmd() specifying - DTM_PKT_VENDORSPECIFIC as payload, SET_TX_POWER as length, and the dBm value as frequency. - */ -bool dtm_set_txpower(uint32_t new_tx_power) -{ - // radio->TXPOWER register is 32 bits, low octet a signed value, upper 24 bits zeroed - int8_t new_power8 = (int8_t)(new_tx_power & 0xFF); - - // The two most significant bits are not sent in the 6 bit field of the DTM command. - // These two bits are 1's if and only if the tx_power is a negative number. - // All valid negative values have the fourth most significant bit as 1. - // All valid positive values have the fourth most significant bit as 0. - // By checking this bit, the two most significant bits can be determined. - new_power8 = (new_power8 & 0x30) != 0 ? (new_power8 | 0xC0) : new_power8; - - if (m_state > STATE_IDLE) - { - // radio must be idle to change the tx power - return false; - } - - m_tx_power = new_power8; - - return true; -} - - -/**@brief Function for selecting a timer resource. - * This function may be called directly, or through dtm_cmd() specifying - * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq - * - * @param[in] new_timer Timer id for the timer to use: 0, 1, or 2. - * - * @return true if the timer was successfully changed, false otherwise. - */ -bool dtm_set_timer(uint32_t new_timer) -{ - if (m_state > STATE_IDLE) - { - return false; - } - return dtm_hw_set_timer(&mp_timer, &m_timer_irq, new_timer); -} - -/// @} -#endif // NRF_MODULE_ENABLED(BLE_DTM) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h deleted file mode 100644 index 04066cbc2e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_dtm DTM - Direct Test Mode - * @{ - * @ingroup ble_sdk_lib - * @brief Module for testing RF/PHY using DTM commands. - */ - -#ifndef BLE_DTM_H__ -#define BLE_DTM_H__ - -#include -#include -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Configuration parameters. */ -#define DTM_BITRATE UARTE_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */ -#define DEFAULT_TX_POWER RADIO_TXPOWER_TXPOWER_0dBm /**< Default Transmission power using in the DTM module. */ -#define DEFAULT_TIMER NRF_TIMER0 /**< Default timer used for timing. */ -#define DEFAULT_TIMER_IRQn TIMER0_IRQn /**< IRQ used for timer. NOTE: MUST correspond to DEFAULT_TIMER. */ - -/**@brief BLE DTM command codes. */ -typedef uint32_t dtm_cmd_t; /**< DTM command type. */ - -#define LE_TEST_SETUP 0 /**< DTM command: Set PHY or modulation, configure upper two bits of length, - request matrix of supported features or request max values of parameters. */ -#define LE_RECEIVER_TEST 1 /**< DTM command: Start receive test. */ -#define LE_TRANSMITTER_TEST 2 /**< DTM command: Start transmission test. */ -#define LE_TEST_END 3 /**< DTM command: End test and send packet report. */ - -#define LE_TEST_SETUP_RESET 0 /**< DTM command parameter: Stop TX/RX, reset the packet length upper bits and set the PHY to 1Mbit. */ -#define LE_TEST_SETUP_SET_UPPER 1 /**< DTM command parameter: Set the upper two bits of the length field. */ -#define LE_TEST_SETUP_SET_PHY 2 /**< DTM command parameter: Select the PHY to be used for packets. */ -#define LE_TEST_SETUP_SELECT_MODULATION 3 /**< DTM command parameter: Select standard or stable modulation index. Stable modulation index is not supported. */ -#define LE_TEST_SETUP_READ_SUPPORTED 4 /**< DTM command parameter: Read the supported test case features. */ -#define LE_TEST_SETUP_READ_MAX 5 /**< DTM command parameter: Read the max supported time and length for packets. */ - -#define LE_PHY_1M 1 /**< DTM command parameter: Set PHY for future packets to use 1MBit PHY. */ -#define LE_PHY_2M 2 /**< DTM command parameter: Set PHY for future packets to use 2MBit PHY. */ -#define LE_PHY_LE_CODED_S8 3 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=8. */ -#define LE_PHY_LE_CODED_S2 4 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=2 */ - -// Configuration options used as parameter 2 -// when cmd == LE_TRANSMITTER_TEST and payload == DTM_PKT_VENDORSPECIFIC -// Configuration value, if any, is supplied in parameter 3 - -#define CARRIER_TEST 0 /**< Length=0 indicates a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ -#define CARRIER_TEST_STUDIO 1 /**< nRFgo Studio uses value 1 in length field, to indicate a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ -#define SET_TX_POWER 2 /**< Set transmission power, value -40..+4 dBm in steps of 4 */ -#define SELECT_TIMER 3 /**< Select on of the 16 MHz timers 0, 1 or 2 */ - -#define LE_PACKET_REPORTING_EVENT 0x8000 /**< DTM Packet reporting event, returned by the device to the tester. */ -#define LE_TEST_STATUS_EVENT_SUCCESS 0x0000 /**< DTM Status event, indicating success. */ -#define LE_TEST_STATUS_EVENT_ERROR 0x0001 /**< DTM Status event, indicating an error. */ - -#define DTM_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */ -#define DTM_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */ -#define DTM_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */ -#define DTM_PKT_0XFF 0x03 /**< Bit pattern 11111111 (Used only for coded PHY). */ -#define DTM_PKT_VENDORSPECIFIC 0x03 /**< Vendor specific PKT field value. Nordic: Continuous carrier test, or configuration. */ -#define DTM_PKT_TYPE_VENDORSPECIFIC 0xFF /**< Vendor specific packet type for internal use. */ - -// The pdu payload type for each bit pattern. Identical to the PKT value except pattern 0xFF which is 0x04. -#define DTM_PDU_TYPE_PRBS9 0x00 /**< PDU payload type for bit pattern PRBS9. */ -#define DTM_PDU_TYPE_0X0F 0x01 /**< PDU payload type for bit pattern 11110000 (LSB is the leftmost bit). */ -#define DTM_PDU_TYPE_0X55 0x02 /**< PDU payload type for bit pattern 10101010 (LSB is the leftmost bit). */ -#define DTM_PDU_TYPE_0XFF 0x04 /**< PDU payload type for bit pattern 11111111 (Used only for coded PHY). */ - -/**@brief Return codes from dtm_cmd(). */ -#define DTM_SUCCESS 0x00 /**< Indicate that the DTM function completed with success. */ -#define DTM_ERROR_ILLEGAL_CHANNEL 0x01 /**< Physical channel number must be in the range 0..39. */ -#define DTM_ERROR_INVALID_STATE 0x02 /**< Sequencing error: Command is not valid now. */ -#define DTM_ERROR_ILLEGAL_LENGTH 0x03 /**< Payload size must be in the range 0..37. */ -#define DTM_ERROR_ILLEGAL_CONFIGURATION 0x04 /**< Parameter out of range (legal range is function dependent). */ -#define DTM_ERROR_UNINITIALIZED 0x05 /**< DTM module has not been initialized by the application. */ - -/**@details The UART poll cycle in micro seconds. - * A baud rate of e.g. 19200 bits / second, and 8 data bits, 1 start/stop bit, no flow control, - * give the time to transmit a byte: 10 bits * 1/19200 = approx: 520 us. - * To ensure no loss of bytes, the UART should be polled every 260 us. - */ -#if DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud9600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/9600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud14400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/14400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud19200 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/19200/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud28800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/28800/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud38400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/38400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud57600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/57600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud76800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/768000/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud115200 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/115200/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud230400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/230400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud250000 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/250000/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud460800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/460800/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud921600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/921600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud1M -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/1e6/2)) -#else -// It is possible to find values that work for other baud rates, but the formula above is not -// guaranteed to work for all values. Suitable values may have to be found by trial and error. -#error "Unsupported baud rate set." -#endif - -// Note: DTM_PKT_VENDORSPECIFIC, is not a packet type -#define PACKET_TYPE_MAX DTM_PKT_0XFF /**< Highest value allowed as DTM Packet type. */ - -/** @brief BLE DTM event type. */ -typedef uint32_t dtm_event_t; /**< Type for handling DTM event. */ - -/** @brief BLE DTM frequency type. */ -typedef uint32_t dtm_freq_t; /**< Physical channel, valid range: 0..39. */ - -/**@brief BLE DTM packet types. */ -typedef uint32_t dtm_pkt_type_t; /**< Type for holding the requested DTM payload type.*/ - - -/**@brief Function for initializing or re-initializing DTM module - * - * @return DTM_SUCCESS on successful initialization of the DTM module. -*/ -uint32_t dtm_init(void); - - -/**@brief Function for giving control to dtmlib for handling timer and radio events. - * Will return to caller at 625us intervals or whenever another event than radio occurs - * (such as UART input). Function will put MCU to sleep between events. - * - * @return Time counter, incremented every 625 us. - */ -uint32_t dtm_wait(void); - - -/**@brief Function for calling when a complete command has been prepared by the Tester. - * - * @param[in] cmd One of the DTM_CMD values (bits 14:15 in the 16-bit UART format). - * @param[in] freq Phys. channel no - actual frequency = (2402 + freq * 2) MHz (bits 8:13 in - * the 16-bit UART format). - * @param[in] length Payload length, 0..37 (bits 2:7 in the 16-bit UART format). - * @param[in] payload One of the DTM_PKT values (bits 0:1 in the 16-bit UART format). - * - * @return DTM_SUCCESS or one of the DTM_ERROR_ values - */ -uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload); - - -/**@brief Function for reading the result of a DTM command - * - * @param[out] p_dtm_event Pointer to buffer for 16 bit event code according to DTM standard. - * - * @return true: new event, false: no event since last call, this event has been read earlier - */ -bool dtm_event_get(dtm_event_t * p_dtm_event); - - -/**@brief Function for configuring the timer to use. - * - * @note Must be called when no DTM test is running. - * - * @param[in] new_timer Index (0..2) of timer to be used by the DTM library - * - * @return true: success, new timer was selected, false: parameter error - */ -bool dtm_set_timer(uint32_t new_timer); - - -/**@brief Function for configuring the transmit power. - * - * @note Must be called when no DTM test is running. - * - * @param[in] new_tx_power New output level, +4..-40, in steps of 4. - * - * @return true: tx power setting changed, false: parameter error - */ -bool dtm_set_txpower(uint32_t new_tx_power); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DTM_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h deleted file mode 100644 index c63d155cc8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_dtm_hw Direct Test Mode HW - * @{ - * @ingroup ble_sdk_lib - * @brief Module contains hardware related function for testing RF/PHY using DTM commands. - */ - -#ifndef BLE_DTM_HW_H__ -#define BLE_DTM_HW_H__ - -#include -#include -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Function for selecting a timer resource. - * This function may be called directly, or through dtm_cmd() specifying - * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq - * - * @param[out] mp_timer Pointer to timer instance used in dtm source file. - * @param[out] m_timer_irq Pointer to timer interrupt related to mp_timer. - * @param[in] new_timer Timer id for the timer to use. - * - * @retval true if the timer was successfully changed. - * @retval false if the error occurs. - */ - -bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer); - - -/**@brief Function for turning off radio test. - * This function is platform depending. For now only nRF51 requieres this special function. - */ -void dtm_turn_off_test(void); - - -/**@brief Function for setting constant carrier in radio settings. - * This function is used to handle vendor specific command testing continous carrier without - * a modulated signal. - */ -void dtm_constant_carrier(void); - - -/**@brief Function for validating tx power and radio move settings. - * @param[in] m_tx_power TX power for transmission test. - * @param[in] m_radio_mode Radio mode value. - * - * @retval DTM_SUCCESS if input parameters values are correct. - * @retval DTM_ERROR_ILLEGAL_CONFIGURATION if input parameters values are not correct. - */ -uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode); - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DTM_HW_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c deleted file mode 100644 index 9f5f4b4d34..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "ble_dtm_hw.h" -#include "ble_dtm.h" -#include -#include -#include "nrf.h" - - -void dtm_turn_off_test() -{ -} - - -void dtm_constant_carrier() -{ -NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) | - (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos); -} - - -uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode) -{ - // Initializing code below is quite generic - for BLE, the values are fixed, and expressions - // are constant. Non-constant values are essentially set in radio_prepare(). - if (!(m_tx_power == RADIO_TXPOWER_TXPOWER_0dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Pos4dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg30dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg20dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg16dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg12dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg8dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg4dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Pos3dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg40dBm - ) || - - !( -#ifdef NRF52840_XXAA - m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit || - m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || -#endif //NRF52840_XXAA - m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || - m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit - ) - ) - { - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - return DTM_SUCCESS; -} - - -bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer) -{ - if (new_timer == 0) - { - *mp_timer = NRF_TIMER0; - *m_timer_irq = TIMER0_IRQn; - } - else if (new_timer == 1) - { - *mp_timer = NRF_TIMER1; - *m_timer_irq = TIMER1_IRQn; - } - else if (new_timer == 2) - { - *mp_timer = NRF_TIMER2; - *m_timer_irq = TIMER2_IRQn; - } -#ifndef NRF52810_XXAA - else if (new_timer == 3) - { - *mp_timer = NRF_TIMER3; - *m_timer_irq = TIMER3_IRQn; - } - else if (new_timer == 4) - { - *mp_timer = NRF_TIMER4; - *m_timer_irq = TIMER4_IRQn; - } -#endif //NRF52810_XXAA - else - { - // Parameter error: Only TIMER 0, 1, 2, 3 and 4 provided by nRF52 - return false; - } - // New timer has been selected: - return true; -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c deleted file mode 100644 index 41a4ccb4f6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_RACP) -#include "ble_racp.h" -#include - - -void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val) -{ - p_racp_val->opcode = 0xFF; - p_racp_val->operator = 0xFF; - p_racp_val->operand_len = 0; - p_racp_val->p_operand = NULL; - - if (data_len > 0) - { - p_racp_val->opcode = p_data[0]; - } - if (data_len > 1) - { - p_racp_val->operator = p_data[1]; //lint !e415 - } - if (data_len > 2) - { - p_racp_val->operand_len = data_len - 2; - p_racp_val->p_operand = (uint8_t*)&p_data[2]; //lint !e416 - } -} - - -uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data) -{ - uint8_t len = 0; - int i; - - if (p_data != NULL) - { - p_data[len++] = p_racp_val->opcode; - p_data[len++] = p_racp_val->operator; - - for (i = 0; i < p_racp_val->operand_len; i++) - { - p_data[len++] = p_racp_val->p_operand[i]; - } - } - - return len; -} -#endif // NRF_MODULE_ENABLED(BLE_RACP) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h deleted file mode 100644 index 14da8b281b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_racp Record Access Control Point - * @{ - * @ingroup ble_sdk_lib - * @brief Record Access Control Point library. - */ - -#ifndef BLE_RACP_H__ -#define BLE_RACP_H__ - -#include -#include -#include "nrf_ble.h" -#include "ble_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Record Access Control Point opcodes. */ -#define RACP_OPCODE_RESERVED 0 /**< Record Access Control Point opcode - Reserved for future use. */ -#define RACP_OPCODE_REPORT_RECS 1 /**< Record Access Control Point opcode - Report stored records. */ -#define RACP_OPCODE_DELETE_RECS 2 /**< Record Access Control Point opcode - Delete stored records. */ -#define RACP_OPCODE_ABORT_OPERATION 3 /**< Record Access Control Point opcode - Abort operation. */ -#define RACP_OPCODE_REPORT_NUM_RECS 4 /**< Record Access Control Point opcode - Report number of stored records. */ -#define RACP_OPCODE_NUM_RECS_RESPONSE 5 /**< Record Access Control Point opcode - Number of stored records response. */ -#define RACP_OPCODE_RESPONSE_CODE 6 /**< Record Access Control Point opcode - Response code. */ - -/**@brief Record Access Control Point operators. */ -#define RACP_OPERATOR_NULL 0 /**< Record Access Control Point operator - Null. */ -#define RACP_OPERATOR_ALL 1 /**< Record Access Control Point operator - All records. */ -#define RACP_OPERATOR_LESS_OR_EQUAL 2 /**< Record Access Control Point operator - Less than or equal to. */ -#define RACP_OPERATOR_GREATER_OR_EQUAL 3 /**< Record Access Control Point operator - Greater than or equal to. */ -#define RACP_OPERATOR_RANGE 4 /**< Record Access Control Point operator - Within range of (inclusive). */ -#define RACP_OPERATOR_FIRST 5 /**< Record Access Control Point operator - First record (i.e. oldest record). */ -#define RACP_OPERATOR_LAST 6 /**< Record Access Control Point operator - Last record (i.e. most recent record). */ -#define RACP_OPERATOR_RFU_START 7 /**< Record Access Control Point operator - Start of Reserved for Future Use area. */ - -/**@brief Record Access Control Point Operand Filter Type Value. */ -#define RACP_OPERAND_FILTER_TYPE_TIME_OFFSET 1 /**< Record Access Control Point Operand Filter Type Value - Time Offset- */ - -/**@brief Record Access Control Point response codes. */ -#define RACP_RESPONSE_RESERVED 0 /**< Record Access Control Point response code - Reserved for future use. */ -#define RACP_RESPONSE_SUCCESS 1 /**< Record Access Control Point response code - Successful operation. */ -#define RACP_RESPONSE_OPCODE_UNSUPPORTED 2 /**< Record Access Control Point response code - Unsupported op code received. */ -#define RACP_RESPONSE_INVALID_OPERATOR 3 /**< Record Access Control Point response code - Operator not valid for service. */ -#define RACP_RESPONSE_OPERATOR_UNSUPPORTED 4 /**< Record Access Control Point response code - Unsupported operator. */ -#define RACP_RESPONSE_INVALID_OPERAND 5 /**< Record Access Control Point response code - Operand not valid for service. */ -#define RACP_RESPONSE_NO_RECORDS_FOUND 6 /**< Record Access Control Point response code - No matching records found. */ -#define RACP_RESPONSE_ABORT_FAILED 7 /**< Record Access Control Point response code - Abort could not be completed. */ -#define RACP_RESPONSE_PROCEDURE_NOT_DONE 8 /**< Record Access Control Point response code - Procedure could not be completed. */ -#define RACP_RESPONSE_OPERAND_UNSUPPORTED 9 /**< Record Access Control Point response code - Unsupported operand. */ - -/**@brief Record Access Control Point value structure. */ -typedef struct -{ - uint8_t opcode; /**< Op Code. */ - uint8_t operator; /**< Operator. */ - uint8_t operand_len; /**< Length of the operand. */ - uint8_t * p_operand; /**< Pointer to the operand. */ -} ble_racp_value_t; - -/**@brief Function for decoding a Record Access Control Point write. - * - * @details This call decodes a write to the Record Access Control Point. - * - * @param[in] data_len Length of data in received write. - * @param[in] p_data Pointer to received data. - * @param[out] p_racp_val Pointer to decoded Record Access Control Point write. - * @note This does not do a data copy. It assumes the data pointed to by - * p_data is persistant until no longer needed. - */ -void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val); - -/**@brief Function for encoding a Record Access Control Point response. - * - * @details This call encodes a response from the Record Access Control Point response. - * - * @param[in] p_racp_val Pointer to Record Access Control Point to encode. - * @param[out] p_data Pointer to where encoded data is written. - * NOTE! It is calling routines respsonsibility to make sure. - * - * @return Length of encoded data. - */ -uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_RACP_H__ - -/** @} */ - diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c deleted file mode 100644 index dd0c43c97f..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c +++ /dev/null @@ -1,706 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "ble_advdata.h" -#include "ble_gap.h" -#include "ble_srv_common.h" -#include "sdk_common.h" - -// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. - -#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ -#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ -#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ - -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ - AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ -#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ -#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ -#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ -#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ - -// Types of LE Bluetooth Device Address AD type -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL - -static uint32_t ble_device_addr_encode(uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - ble_gap_addr_t device_addr; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Get BLE address. - #if (NRF_SD_BLE_API_VERSION >= 3) - err_code = sd_ble_gap_addr_get(&device_addr); - #else - err_code = sd_ble_gap_address_get(&device_addr); - #endif - VERIFY_SUCCESS(err_code); - - // Encode LE Bluetooth Device Address. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; - *p_offset += AD_TYPE_FIELD_SIZE; - memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); - *p_offset += BLE_GAP_ADDR_LEN; - if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) - { - p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; - } - else - { - p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; - } - *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; - - return NRF_SUCCESS; -} - -static uint32_t name_encode(const ble_advdata_t * p_advdata, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - uint16_t rem_adv_data_len; - uint16_t actual_length; - uint8_t adv_data_format; - - - // Validate parameters - if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Check for buffer overflow. - if ( (((*p_offset) + AD_DATA_OFFSET) > max_size) || - ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && - (((*p_offset) + AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) - { - return NRF_ERROR_DATA_SIZE; - } - - rem_adv_data_len = max_size - (*p_offset) - AD_DATA_OFFSET; - actual_length = rem_adv_data_len; - - // Get GAP device name and length - err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + AD_DATA_OFFSET], - &actual_length); - VERIFY_SUCCESS(err_code); - - // Check if device intend to use short name and it can fit available data size. - if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len)) - { - // Complete device name can fit, setting Complete Name in Adv Data. - adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; - } - else - { - // Else short name needs to be used. Or application has requested use of short name. - adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; - - // If application has set a preference on the short name size, it needs to be considered, - // else fit what can be fit. - if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && - (p_advdata->short_name_len <= rem_adv_data_len)) - { - // Short name fits available size. - actual_length = p_advdata->short_name_len; - } - // Else whatever can fit the data buffer will be packed. - else - { - actual_length = rem_adv_data_len; - } - } - - // There is only 1 byte intended to encode length which is (actual_length + AD_TYPE_FIELD_SIZE) - if (actual_length > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Complete name field in encoded data. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + actual_length); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = adv_data_format; - *p_offset += AD_TYPE_FIELD_SIZE; - *p_offset += actual_length; - - return NRF_SUCCESS; -} - - -static uint32_t appearance_encode(uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - uint16_t appearance; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Get GAP appearance field. - err_code = sd_ble_gap_appearance_get(&appearance); - VERIFY_SUCCESS(err_code); - - // Encode Length, AD Type and Appearance. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; - *p_offset += AD_TYPE_FIELD_SIZE; - *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); - - return NRF_SUCCESS; -} - -static uint32_t flags_encode(int8_t flags, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode flags. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; - *p_offset += AD_TYPE_FIELD_SIZE; - p_encoded_data[*p_offset] = flags; - *p_offset += AD_TYPE_FLAGS_DATA_SIZE; - - return NRF_SUCCESS; -} - -static uint32_t tx_power_level_encode(int8_t tx_power_level, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode TX Power Level. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; - *p_offset += AD_TYPE_FIELD_SIZE; - p_encoded_data[*p_offset] = tx_power_level; - *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; - - return NRF_SUCCESS; -} - - -static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, - uint8_t adv_type, - uint8_t uuid_size, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - int i; - bool is_heading_written = false; - uint16_t start_pos = *p_offset; - uint16_t length; - - for (i = 0; i < p_uuid_list->uuid_cnt; i++) - { - uint32_t err_code; - uint8_t encoded_size; - ble_uuid_t uuid = p_uuid_list->p_uuids[i]; - - // Find encoded uuid size. - err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); - VERIFY_SUCCESS(err_code); - - // Check size. - if (encoded_size == uuid_size) - { - uint8_t heading_bytes = (is_heading_written) ? 0 : AD_DATA_OFFSET; - - // Check for buffer overflow - if (((*p_offset) + encoded_size + heading_bytes) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - if (!is_heading_written) - { - // Write AD structure heading. - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = adv_type; - *p_offset += AD_TYPE_FIELD_SIZE; - is_heading_written = true; - } - - // Write UUID. - err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); - VERIFY_SUCCESS(err_code); - *p_offset += encoded_size; - } - } - - if (is_heading_written) - { - // Write length. - length = (*p_offset) - (start_pos + AD_LENGTH_FIELD_SIZE); - // There is only 1 byte intended to encode length - if (length > 0x00FF) - { - return NRF_ERROR_DATA_SIZE; - } - p_encoded_data[start_pos] = (uint8_t)length; - } - - return NRF_SUCCESS; -} - - -static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, - uint8_t adv_type_16, - uint8_t adv_type_128, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - - // Encode 16 bit UUIDs. - err_code = uuid_list_sized_encode(p_uuid_list, - adv_type_16, - sizeof(uint16_le_t), - p_encoded_data, - p_offset, - max_size); - VERIFY_SUCCESS(err_code); - - // Encode 128 bit UUIDs. - err_code = uuid_list_sized_encode(p_uuid_list, - adv_type_128, - sizeof(ble_uuid128_t), - p_encoded_data, - p_offset, - max_size); - VERIFY_SUCCESS(err_code); - - return NRF_SUCCESS; -} - - -static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) -{ - // Check Minimum Connection Interval. - if ((p_conn_int->min_conn_interval < 0x0006) || - ( - (p_conn_int->min_conn_interval > 0x0c80) && - (p_conn_int->min_conn_interval != 0xffff) - ) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Check Maximum Connection Interval. - if ((p_conn_int->max_conn_interval < 0x0006) || - ( - (p_conn_int->max_conn_interval > 0x0c80) && - (p_conn_int->max_conn_interval != 0xffff) - ) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. - if ((p_conn_int->min_conn_interval != 0xffff) && - (p_conn_int->max_conn_interval != 0xffff) && - (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Check parameters. - err_code = conn_int_check(p_conn_int); - VERIFY_SUCCESS(err_code); - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode Minimum and Maximum Connection Intervals. - *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); - *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); - - return NRF_SUCCESS; -} - - -static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; - - // Check for buffer overflow. - if (((*p_offset) + AD_DATA_OFFSET + data_size) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) - if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode Company Identifier. - *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); - - // Encode additional manufacturer specific data. - if (p_manuf_sp_data->data.size > 0) - { - if (p_manuf_sp_data->data.p_data == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); - *p_offset += p_manuf_sp_data->data.size; - } - - return NRF_SUCCESS; -} - -// Implemented only for 16-bit UUIDs -static uint32_t service_data_encode(const ble_advdata_t * p_advdata, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint8_t i; - - // Check parameter consistency. - if (p_advdata->p_service_data_array == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - - for (i = 0; i < p_advdata->service_data_count; i++) - { - ble_advdata_service_data_t * p_service_data; - uint32_t data_size; - - p_service_data = &p_advdata->p_service_data_array[i]; - // For now implemented only for 16-bit UUIDs - data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; - - // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) - if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode service 16-bit UUID. - *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); - - // Encode additional service data. - if (p_service_data->data.size > 0) - { - if (p_service_data->data.p_data == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); - *p_offset += p_service_data->data.size; - } - } - - return NRF_SUCCESS; -} - -uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, - uint8_t * const p_encoded_data, - uint16_t * const p_len) -{ - uint32_t err_code = NRF_SUCCESS; - uint16_t max_size = *p_len; - *p_len = 0; - - // Encode LE Bluetooth Device Address - if (p_advdata->include_ble_device_addr) - { - err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode appearance. - if (p_advdata->include_appearance) - { - err_code = appearance_encode(p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - //Encode Flags - if (p_advdata->flags != 0 ) - { - err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode TX power level. - if (p_advdata->p_tx_power_level != NULL) - { - err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'more available' uuid list. - if (p_advdata->uuids_more_available.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_more_available, - BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, - BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'complete' uuid list. - if (p_advdata->uuids_complete.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_complete, - BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, - BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'solicited service' uuid list. - if (p_advdata->uuids_solicited.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_solicited, - BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, - BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Slave Connection Interval Range. - if (p_advdata->p_slave_conn_int != NULL) - { - err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Manufacturer Specific Data. - if (p_advdata->p_manuf_specific_data != NULL) - { - err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Service Data. - if (p_advdata->service_data_count > 0) - { - err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. - if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) - { - err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - return err_code; -} - - -static uint32_t advdata_check(const ble_advdata_t * p_advdata) -{ - // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. - if ( - ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -static uint32_t srdata_check(const ble_advdata_t * p_srdata) -{ - // Flags shall not be included in the scan response data. - if (p_srdata->flags) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) -{ - uint32_t err_code; - uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE; - uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE; - uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; - uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; - uint8_t * p_encoded_advdata; - uint8_t * p_encoded_srdata; - - // Encode advertising data (if supplied). - if (p_advdata != NULL) - { - err_code = advdata_check(p_advdata); - VERIFY_SUCCESS(err_code); - - err_code = ble_advdata_encode(p_advdata, encoded_advdata, &len_advdata); - VERIFY_SUCCESS(err_code); - p_encoded_advdata = encoded_advdata; - } - else - { - p_encoded_advdata = NULL; - len_advdata = 0; - } - - // Encode scan response data (if supplied). - if (p_srdata != NULL) - { - err_code = srdata_check(p_srdata); - VERIFY_SUCCESS(err_code); - - err_code = ble_advdata_encode(p_srdata, encoded_srdata, &len_srdata); - VERIFY_SUCCESS(err_code); - p_encoded_srdata = encoded_srdata; - } - else - { - p_encoded_srdata = NULL; - len_srdata = 0; - } - - // Pass encoded advertising data and/or scan response data to the stack. - return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h deleted file mode 100644 index bf7d862497..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_sdk_lib_advdata Advertising and Scan Response Data Encoder - * @{ - * @ingroup ble_sdk_lib - * @brief Functions for encoding data in the Advertising and Scan Response Data format, - * and for passing the data to the stack. - */ - -#ifndef BLE_ADVDATA_H__ -#define BLE_ADVDATA_H__ - -#include -#include -#include -#include "nrf_ble.h" -#include "app_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ -#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ -#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ - -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ - AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ -#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ -#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ -#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ -#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ - - -/**@brief Security Manager TK value. */ -typedef struct -{ - uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value in little-endian format. */ -} ble_advdata_tk_value_t; - -/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside - * the advertising data. */ -typedef enum -{ - BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */ - BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */ - BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */ - BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ - BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ -} ble_advdata_le_role_t; - -/**@brief Advertising data name type. This enumeration contains the options available for the device name inside - * the advertising data. */ -typedef enum -{ - BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */ - BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */ - BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */ -} ble_advdata_name_type_t; - -/**@brief UUID list type. */ -typedef struct -{ - uint16_t uuid_cnt; /**< Number of UUID entries. */ - ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */ -} ble_advdata_uuid_list_t; - -/**@brief Connection interval range structure. */ -typedef struct -{ - uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */ - uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */ -} ble_advdata_conn_int_t; - -/**@brief Manufacturer specific data structure. */ -typedef struct -{ - uint16_t company_identifier; /**< Company identifier code. */ - uint8_array_t data; /**< Additional manufacturer specific data. */ -} ble_advdata_manuf_data_t; - -/**@brief Service data structure. */ -typedef struct -{ - uint16_t service_uuid; /**< Service UUID. */ - uint8_array_t data; /**< Additional service data. */ -} ble_advdata_service_data_t; - -/**@brief Advertising data structure. This structure contains all options and data needed for encoding and - * setting the advertising data. */ -typedef struct -{ - ble_advdata_name_type_t name_type; /**< Type of device name. */ - uint8_t short_name_len; /**< Length of short device name (if short type is specified). */ - bool include_appearance; /**< Determines if Appearance shall be included. */ - uint8_t flags; /**< Advertising data Flags field. */ - int8_t * p_tx_power_level; /**< TX Power Level field. */ - ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */ - ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */ - ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */ - ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */ - ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */ - ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */ - uint8_t service_data_count; /**< Number of Service data structures. */ - bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */ - ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */ - ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ - uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ -#if (NRF_SD_BLE_API_VERSION > 1) - ble_gap_lesc_oob_data_t * p_lesc_data; /**< LE Secure Connections OOB data. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ -#endif -} ble_advdata_t; - -/**@brief Function for encoding data in the Advertising and Scan Response data format - * (AD structures). - * - * @details This function encodes data into the Advertising and Scan Response data format - * (AD structures) based on the selections in the supplied structures. This function can be used to - * create a payload of Advertising packet or Scan Response packet, or a payload of NFC - * message intended for initiating the Out-of-Band pairing. - * - * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. - * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. - * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. - * \c out: Length of encoded data. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. - * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the - * provided buffer or some encoded AD structure is too long and its - * length cannot be encoded with one octet. - * - * @warning This API may override the application's request to use the long name and use a short name - * instead. This truncation will occur in case the long name does not fit the provided buffer size. - * The application can specify a preferred short name length if truncation is required. - * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name - * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni - * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. - * However, it should be noted that this is just a preference that the application can specify, and - * if the preference is too large to fit in the provided buffer, the name can be truncated further. - */ -uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, - uint8_t * const p_encoded_data, - uint16_t * const p_len); - -/**@brief Function for encoding and setting the advertising data and/or scan response data. - * - * @details This function encodes advertising data and/or scan response data based on the selections - * in the supplied structures, and passes the encoded data to the stack. - * - * @param[in] p_advdata Structure for specifying the content of the advertising data. - * Set to NULL if advertising data is not to be set. - * @param[in] p_srdata Structure for specifying the content of the scan response data. - * Set to NULL if scan response data is not to be set. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. - * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the - * advertising packet. The maximum size of the advertisement packet - * is @ref BLE_GAP_ADV_MAX_SIZE. - * - * @warning This API may override the application's request to use the long name and use a short name - * instead. This truncation will occur in case the long name does not fit the provided buffer size. - * The application can specify a preferred short name length if truncation is required. - * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name - * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni - * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. - * However, it should be noted that this is just a preference that the application can specify, and - * if the preference is too large to fit in the provided buffer, the name can be truncated further. - */ -uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_ADVDATA_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c deleted file mode 100644 index 3229571b31..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c +++ /dev/null @@ -1,572 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_CONN_PARAMS) -#include -#include "nrf.h" -#include "sdk_errors.h" -#include "ble_hci.h" -#include "ble_err.h" -#include "ble_conn_params.h" -#include "ble_srv_common.h" -#include "ble_conn_state.h" -#include "nrf_sdh_ble.h" -#include "app_timer.h" -#include "app_util.h" - - -#define NRF_BLE_CONN_PARAMS_N_INSTANCES NRF_SDH_BLE_PERIPHERAL_LINK_COUNT //!< The number of @ref ble_conn_params_instance_t instances kept by the conn_params module. - -#if (NRF_BLE_CONN_PARAMS_N_INSTANCES < 1) -#error Invalid NRF_SDH_BLE_PERIPHERAL_LINK_COUNT value. Set it in SDK config (nrf_sdh_ble). -#endif - -/** @brief Each peripheral link has such an instance associated with it. - */ -typedef struct -{ - uint16_t conn_handle; //!< The connection handle of this link. If this is @ref BLE_CONN_HANDLE_INVALID, the instance is free. - app_timer_id_t timer_id; //!< The ID of the timer associated with this link. - uint8_t update_count; //!< The number of times the connection parameters have been attempted negotiated on this link. - uint8_t params_ok; //!< Whether the current connection parameters on this link are acceptable according to the @p preferred_conn_params, and configured maximum deviations. - ble_gap_conn_params_t preferred_conn_params; //!< The desired connection parameters for this link. -} ble_conn_params_instance_t; - -static app_timer_t m_timer_data[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{{0}}}; //!< Data needed for timers. -static ble_conn_params_instance_t m_conn_params_instances[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{0}}; //!< Configuration data for each connection. -static ble_conn_params_init_t m_conn_params_config; //!< Configuration as provided by the application during intialization. -static ble_gap_conn_params_t m_preferred_conn_params; //!< The preferred connection parameters as specified during initialization. -//lint -esym(551, m_preferred_conn_params) "Not accessed" - - -/**@brief Function for retrieving the conn_params instance belonging to a conn_handle - * - * @params[in] conn_handle The connection handle to retrieve the instance of. - * - * @return A pointer to the instance, or NULL if no instance was found with that conn_handle. - */ -static ble_conn_params_instance_t * instance_get(uint16_t conn_handle) -{ - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - if (m_conn_params_instances[i].conn_handle == conn_handle) - { - return &m_conn_params_instances[i]; - } - } - //lint -restore - return NULL; -} - - -/**@brief Function for initializing an instance, and associating it with a conn_handle. - * - * @params[in] p_instance The instance to initialize and associate. - * @params[in] conn_handle The connection handle to associate with. - */ -static __INLINE void instance_claim(ble_conn_params_instance_t * p_instance, uint16_t conn_handle) -{ - p_instance->conn_handle = conn_handle; - p_instance->update_count = 0; - p_instance->preferred_conn_params = m_preferred_conn_params; -} - - -/**@brief Function for freeing an instance. - * - * @params[in] p_instance The instance to free. - */ -static __INLINE void instance_free(ble_conn_params_instance_t * p_instance) -{ - p_instance->conn_handle = BLE_CONN_HANDLE_INVALID; -} - - -/**@brief Function for validating a set of connection parameters against the preferred parameters. - * - * @param[in] p_preferred_conn_params The desired parameters. - * @param[in] p_actual_conn_params The parameters to validate. - * @param[in] max_slave_latency_err The amount of discrepancy in slave latency, in number of - * connection intervals, that will be accepted. - * @param[in] max_sup_timeout_err The amount of discrepancy in supervision timeout, in tens of - * milliseconds, that will be accepted. - * - * @return Whether the params in @p p_actual_conn_params are acceptable given the other parameters. - */ -static bool is_conn_params_ok(ble_gap_conn_params_t const * p_preferred_conn_params, - ble_gap_conn_params_t const * p_actual_conn_params, - uint16_t max_slave_latency_err, - uint16_t max_sup_timeout_err) -{ - uint32_t max_allowed_sl = p_preferred_conn_params->slave_latency + max_slave_latency_err; - uint32_t min_allowed_sl = p_preferred_conn_params->slave_latency - - MIN(max_slave_latency_err, p_preferred_conn_params->slave_latency); - uint32_t max_allowed_to = p_preferred_conn_params->conn_sup_timeout + max_sup_timeout_err; - uint32_t min_allowed_to = p_preferred_conn_params->conn_sup_timeout - - MIN(max_sup_timeout_err, p_preferred_conn_params->conn_sup_timeout); - - // Check if interval is within the acceptable range. - // NOTE: Using max_conn_interval in the received event data because this contains - // the client's connection interval. - if ((p_actual_conn_params->max_conn_interval < p_preferred_conn_params->min_conn_interval) - || (p_actual_conn_params->max_conn_interval > p_preferred_conn_params->max_conn_interval)) - { - return false; - } - - // Check if slave latency is within the acceptable deviation. - if ((p_actual_conn_params->slave_latency < min_allowed_sl) - || (p_actual_conn_params->slave_latency > max_allowed_sl)) - { - return false; - } - - // Check if supervision timeout is within the acceptable deviation. - if ((p_actual_conn_params->conn_sup_timeout < min_allowed_to) - || (p_actual_conn_params->conn_sup_timeout > max_allowed_to)) - { - return false; - } - - return true; -} - - -static void send_error_evt(ret_code_t err_code) -{ - if (m_conn_params_config.error_handler != NULL) - { - m_conn_params_config.error_handler(err_code); - } -} - - -/**@brief Function for sending a conn_param_update request on-air, and handling errors. - * - * @param[in] conn_handle Connection to send request on. - * @param[in] p_new_conn_params Connection parameters to request. - * - * @return Whether the request was successfully sent. - */ -static bool send_update_request(uint16_t conn_handle, ble_gap_conn_params_t * p_new_conn_params) -{ - ret_code_t err_code; - - err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_conn_params); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) // NRF_ERROR_BUSY means another conn_param_update request is pending. - { - send_error_evt(err_code); - } - - return (err_code == NRF_SUCCESS); -} - - -/**@brief Function called after conn_params_update_delay has happened. This is triggered by app_timer. - * - * @param[in] p_context Context identifying which connection this is for. - */ -static void update_timeout_handler(void * p_context) -{ - uint32_t conn_handle = (uint32_t)p_context; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Check if we have reached the maximum number of attempts - if (p_instance->update_count < m_conn_params_config.max_conn_params_update_count) - { - bool update_sent = send_update_request(conn_handle, &p_instance->preferred_conn_params); - if (update_sent) - { - p_instance->update_count++; - } - } - else - { - p_instance->update_count = 0; - - // Negotiation failed, disconnect automatically if this has been configured - if (m_conn_params_config.disconnect_on_fail) - { - ret_code_t err_code; - - err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) // NRF_ERROR_INVALID_STATE means disconnect is already in progress. - { - send_error_evt(err_code); - } - } - - // Notify the application that the procedure has failed - if (m_conn_params_config.evt_handler != NULL) - { - ble_conn_params_evt_t evt; - - evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED; - evt.conn_handle = conn_handle; - m_conn_params_config.evt_handler(&evt); - } - } - } -} - - -ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init) -{ - ret_code_t err_code; - - VERIFY_PARAM_NOT_NULL(p_init); - - m_conn_params_config = *p_init; - m_conn_params_config.p_conn_params = &m_preferred_conn_params; - - if (p_init->p_conn_params != NULL) - { - // Set the connection params in stack. - err_code = sd_ble_gap_ppcp_set(p_init->p_conn_params); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - m_preferred_conn_params = *p_init->p_conn_params; - } - else - { - // Get the (default) connection params from stack. - err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - } - - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - ble_conn_params_instance_t * p_instance = &m_conn_params_instances[i]; - - instance_free(p_instance); - p_instance->timer_id = &m_timer_data[i]; - - err_code = app_timer_create(&p_instance->timer_id, - APP_TIMER_MODE_SINGLE_SHOT, - update_timeout_handler); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - } - //lint -restore - - return NRF_SUCCESS; -} - - -ret_code_t ble_conn_params_stop(void) -{ - ret_code_t err_code; - - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - err_code = app_timer_stop(m_conn_params_instances[i].timer_id); - switch (err_code) - { - case NRF_SUCCESS: - /* do nothing */ - break; - - case NRF_ERROR_INVALID_STATE: - /* do nothing */ - break; - - case NRF_ERROR_NO_MEM: - return NRF_ERROR_BUSY; - - case NRF_ERROR_INVALID_PARAM: - /* fallthrough */ - default: - return NRF_ERROR_INTERNAL; - } - } - //lint -restore - return NRF_SUCCESS; -} - - -/**@brief Function for taking appropriate action based on the current state of connection parameters. - * - * @param[in] conn_handle Connection to handle. - * @param[in] p_instance Configuration for the connection. - */ -static void conn_params_negotiation(uint16_t conn_handle, ble_conn_params_instance_t * p_instance) - { - // Start negotiation if the received connection parameters are not acceptable - if (!p_instance->params_ok) - { - ret_code_t err_code; - uint32_t timeout_ticks; - - if (p_instance->update_count == 0) - { - // First connection parameter update - timeout_ticks = m_conn_params_config.first_conn_params_update_delay; - } - else - { - timeout_ticks = m_conn_params_config.next_conn_params_update_delay; - } - - err_code = app_timer_start(p_instance->timer_id, timeout_ticks, (void *)(uint32_t)conn_handle); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - } - else - { - p_instance->update_count = 0; - - // Notify the application that the procedure has succeeded - if (m_conn_params_config.evt_handler != NULL) - { - ble_conn_params_evt_t evt; - - evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED; - evt.conn_handle = conn_handle; - m_conn_params_config.evt_handler(&evt); - } - } -} - - -/**@brief Function for handling a connection event from the SoftDevice. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_connect(ble_evt_t const * p_ble_evt) -{ - uint8_t role = p_ble_evt->evt.gap_evt.params.connected.role; - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - - if (role != BLE_GAP_ROLE_PERIPH) - { - return; - } - - ble_conn_params_instance_t * p_instance = instance_get(BLE_CONN_HANDLE_INVALID); - - if (p_instance == NULL) - { - send_error_evt(NRF_ERROR_NO_MEM); - return; - } - - instance_claim(p_instance, conn_handle); - p_instance->params_ok = is_conn_params_ok(&p_instance->preferred_conn_params, - &p_ble_evt->evt.gap_evt.params.connected.conn_params, - NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, - NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); - - // Check if we shall handle negotiation on connect - if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID) - { - conn_params_negotiation(conn_handle, p_instance); - } -} - - -/**@brief Function for handling a disconnection event from the SoftDevice. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_disconnect(ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Stop timer if running - err_code = app_timer_stop(p_instance->timer_id); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - - instance_free(p_instance); - } -} - - -/**@brief Function for handling a GATT write event from the SoftDevice. - * - * @details To provide the start_on_notify_cccd_handle functionality. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_write(ble_evt_t const * p_ble_evt) -{ - ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; - - // Check if this is the correct CCCD - if ( - (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle) - && - (p_evt_write->len == 2) - ) - { - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Check if this is a 'start notification' - if (ble_srv_is_notification_enabled(p_evt_write->data)) - { - // Do connection parameter negotiation if necessary - conn_params_negotiation(conn_handle, p_instance); - } - else - { - ret_code_t err_code; - - // Stop timer if running - err_code = app_timer_stop(p_instance->timer_id); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - } - } - } -} - - -/**@brief Function for handling a connection parameter update event from the SoftDevice. - * - * @details This event means the peer central has changed the connection parameters or declined our - * request. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_conn_params_update(ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - p_instance->params_ok = is_conn_params_ok( - &p_instance->preferred_conn_params, - &p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params, - NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, - NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); - - conn_params_negotiation(conn_handle, p_instance); - } -} - - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connect(p_ble_evt); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnect(p_ble_evt); - break; - - case BLE_GATTS_EVT_WRITE: - on_write(p_ble_evt); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE: - on_conn_params_update(p_ble_evt); - break; - - default: - // No implementation needed. - break; - } -} - - -ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, - ble_gap_conn_params_t * p_new_params) -{ - ret_code_t err_code = BLE_ERROR_INVALID_CONN_HANDLE; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_new_params == NULL) - { - p_new_params = &m_preferred_conn_params; - } - - if (p_instance != NULL) - { - // Send request to central. - err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_params); - if (err_code == NRF_SUCCESS) - { - p_instance->params_ok = false; - p_instance->update_count = 1; - p_instance->preferred_conn_params = *p_new_params; - } - } - - return err_code; -} - -NRF_SDH_BLE_OBSERVER(m_ble_observer, BLE_CONN_PARAMS_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - -#endif //ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h deleted file mode 100644 index 0e2024c0eb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_conn_params Connection Parameters Negotiation - * @{ - * @ingroup ble_sdk_lib - * @brief Module for initiating and executing a connection parameters negotiation procedure. - */ - -#ifndef BLE_CONN_PARAMS_H__ -#define BLE_CONN_PARAMS_H__ - -#include -#include "nrf_ble.h" -#include "ble_srv_common.h" -#include "sdk_errors.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Connection Parameters Module event type. */ -typedef enum -{ - BLE_CONN_PARAMS_EVT_FAILED, //!< Negotiation procedure failed. - BLE_CONN_PARAMS_EVT_SUCCEEDED //!< Negotiation procedure succeeded. -} ble_conn_params_evt_type_t; - -/**@brief Connection Parameters Module event. */ -typedef struct -{ - ble_conn_params_evt_type_t evt_type; //!< Type of event. - uint16_t conn_handle; //!< Connection the event refers to. -} ble_conn_params_evt_t; - -/**@brief Connection Parameters Module event handler type. */ -typedef void (*ble_conn_params_evt_handler_t) (ble_conn_params_evt_t * p_evt); - -/**@brief Connection Parameters Module init structure. This contains all options and data needed for - * initialization of the connection parameters negotiation module. */ -typedef struct -{ - ble_gap_conn_params_t * p_conn_params; //!< Pointer to the connection parameters desired by the application. When calling ble_conn_params_init, if this parameter is set to NULL, the connection parameters will be fetched from host. - uint32_t first_conn_params_update_delay; //!< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (in number of timer ticks). - uint32_t next_conn_params_update_delay; //!< Time between each call to sd_ble_gap_conn_param_update after the first (in number of timer ticks). Recommended value 30 seconds as per BLUETOOTH SPECIFICATION Version 4.0. - uint8_t max_conn_params_update_count; //!< Number of attempts before giving up the negotiation. - uint16_t start_on_notify_cccd_handle; //!< If procedure is to be started when notification is started, set this to the handle of the corresponding CCCD. Set to BLE_GATT_HANDLE_INVALID if procedure is to be started on connect event. - bool disconnect_on_fail; //!< Set to TRUE if a failed connection parameters update shall cause an automatic disconnection, set to FALSE otherwise. - ble_conn_params_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Connection Parameters. - ble_srv_error_handler_t error_handler; //!< Function to be called in case of an error. -} ble_conn_params_init_t; - - -/**@brief Function for initializing the Connection Parameters module. - * - * @note If the negotiation procedure should be triggered when notification/indication of - * any characteristic is enabled by the peer, then this function must be called after - * having initialized the services. - * - * @param[in] p_init This contains information needed to initialize this module. - * - * @retval NRF_SUCCESS Successful initialization. - * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. - * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. - * @retval NRF_ERROR_NULL @p p_init was NULL. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init); - -/**@brief Function for stopping the Connection Parameters module. - * - * @details This function is intended to be used by the application to clean up the connection - * parameters update module. This will stop the connection parameters update timer if - * running, thereby preventing any impending connection parameters update procedure. This - * function must be called by the application when it needs to clean itself up (for - * example, before disabling the bluetooth SoftDevice) so that an unwanted timer expiry - * event can be avoided. - * - * @retval NRF_SUCCESS Successfully stopped module. - * @retval NRF_ERROR_BUSY Could not complete operation at this time. Try again later. - Note that some timers may have been disabled. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t ble_conn_params_stop(void); - -/**@brief Function for changing the current connection parameters to a new set. - * - * @details Use this function to change the connection parameters to a new set of parameter - * (ie different from the ones given at init of the module). - * This function is useful for scenario where most of the time the application - * needs a relatively big connection interval, and just sometimes, for a temporary - * period requires shorter connection interval, for example to transfer a higher - * amount of data. - * If the given parameters does not match the current connection's parameters - * this function initiates a new negotiation. - * - * @param[in] conn_handle The connection to change connection parameters on. - * @param[in] p_new_params This contains the new connections parameters to setup. - * - * @retval NRF_SUCCESS Successfully started Connection Parameter update procedure. - * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. - * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. - * @retval BLE_ERROR_INVALID_CONN_HANDLE The provided connection handle is invalid. - * @retval NRF_ERROR_INVALID_STATE The connection is not in a state where this operation can - * performed. - * @retval NRF_ERROR_BUSY Could not start operation at this time. Try again later. - * @retval NRF_ERROR_NO_MEM The SoftDevice lacks the memory to perform the action. - */ -ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, - ble_gap_conn_params_t * p_new_params); - -#ifdef __cplusplus -} -#endif - -#endif // BLE_CONN_PARAMS_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c deleted file mode 100644 index 47f1d7c9e6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c +++ /dev/null @@ -1,444 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "ble_conn_state.h" -#include -#include -#include -#include "nrf_ble.h" -#include "sdk_mapped_flags.h" -#include "app_error.h" -#include "nrf_sdh_ble.h" - - -#if defined(__CC_ARM) - #pragma push - #pragma anon_unions -#elif defined(__ICCARM__) - #pragma language=extended -#elif defined(__GNUC__) - /* anonymous unions are enabled by default */ -#endif - - -#define BLE_CONN_STATE_N_DEFAULT_FLAGS 5 /**< The number of flags kept for each connection, excluding user flags. */ -#define BLE_CONN_STATE_N_FLAGS (BLE_CONN_STATE_N_DEFAULT_FLAGS + BLE_CONN_STATE_N_USER_FLAGS) /**< The number of flags kept for each connection, including user flags. */ - -/**@brief Structure containing all the flag collections maintained by the Connection State module. - */ -typedef struct -{ - sdk_mapped_flags_t valid_flags; /**< Flags indicating which connection handles are valid. */ - sdk_mapped_flags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */ - sdk_mapped_flags_t central_flags; /**< Flags indicating in which connections the local device is the central. */ - sdk_mapped_flags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */ - sdk_mapped_flags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */ - sdk_mapped_flags_t user_flags[BLE_CONN_STATE_N_USER_FLAGS]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */ -} ble_conn_state_flag_collections_t; - - -/**@brief Structure containing the internal state of the Connection State module. - */ -typedef struct -{ - uint32_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */ - uint16_t valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */ - union - { - ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */ - sdk_mapped_flags_t flag_array[BLE_CONN_STATE_N_FLAGS]; /**< Flag collections as array to allow use of @ref sdk_mapped_flags_bulk_update_by_key() when setting all flags. */ - }; -} ble_conn_state_t; - - -#if defined(__CC_ARM) - #pragma pop -#elif defined(__ICCARM__) - /* leave anonymous unions enabled */ -#elif defined(__GNUC__) - /* anonymous unions are enabled by default */ -#endif - - -static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */ - - -/**@brief Function for resetting all internal memory to the values it had at initialization. - */ -void bcs_internal_state_reset(void) -{ - memset( &m_bcs, 0, sizeof(ble_conn_state_t) ); -} - - -/**@brief Function for activating a connection record. - * - * @param p_record The record to activate. - * @param conn_handle The connection handle to copy into the record. - * @param role The role of the connection. - * - * @return whether the record was activated successfully. - */ -static bool record_activate(uint16_t conn_handle) -{ - uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags); - - if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX) - { - m_bcs.valid_conn_handles[available_index] = conn_handle; - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.connected_flags, - conn_handle, - 1); - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.valid_flags, - conn_handle, - 1); - - return true; - } - - return false; -} - - -/**@brief Function for marking a connection record as invalid and resetting the values. - * - * @param p_record The record to invalidate. - */ -static void record_invalidate(uint16_t conn_handle) -{ - sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles, - m_bcs.flag_array, - BLE_CONN_STATE_N_FLAGS, - conn_handle, - 0); -} - - -/**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED. - * - * @param p_record The record of the connection to set as disconnected. - */ -static void record_set_disconnected(uint16_t conn_handle) -{ - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.connected_flags, - conn_handle, - 0); -} - - -/**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED - * connection status - */ -static void record_purge_disconnected() -{ - sdk_mapped_flags_key_list_t disconnected_list; - - disconnected_list = sdk_mapped_flags_key_list_get( - m_bcs.valid_conn_handles, - (~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags)); - - for (uint32_t i = 0; i < disconnected_list.len; i++) - { - record_invalidate(disconnected_list.flag_keys[i]); - } -} - - -/**@brief Function for checking if a user flag has been acquired. - * - * @param[in] flag_id Which flag to check. - * - * @return Whether the flag has been acquired. - */ -static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id) -{ - return ((m_bcs.acquired_flags & (1 << flag_id)) != 0); -} - - -/**@brief Function for marking a user flag as acquired. - * - * @param[in] flag_id Which flag to mark. - */ -static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id) -{ - m_bcs.acquired_flags |= (1 << flag_id); -} - - -void ble_conn_state_init(void) -{ - bcs_internal_state_reset(); -} - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - record_purge_disconnected(); - - if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) ) - { - // No more records available. Should not happen. - APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); - } -#if !defined (S112) - else - { - bool is_central = - (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL); - - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.central_flags, - p_ble_evt->evt.gap_evt.conn_handle, - is_central); - } -#endif // !defined (S112) - - break; - - case BLE_GAP_EVT_DISCONNECTED: - record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle); - break; - - case BLE_GAP_EVT_CONN_SEC_UPDATE: - sdk_mapped_flags_update_by_key( - m_bcs.valid_conn_handles, - &m_bcs.flags.encrypted_flags, - p_ble_evt->evt.gap_evt.conn_handle, - (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1)); - sdk_mapped_flags_update_by_key( - m_bcs.valid_conn_handles, - &m_bcs.flags.mitm_protected_flags, - p_ble_evt->evt.gap_evt.conn_handle, - (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2)); - break; - } -} - -NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_CONN_STATE_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - - -bool ble_conn_state_valid(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle); -} - - -uint8_t ble_conn_state_role(uint16_t conn_handle) -{ - uint8_t role = BLE_GAP_ROLE_INVALID; - - if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) ) - { - bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.central_flags, - conn_handle); -#if !defined (S112) - role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH; -#else - role = BLE_GAP_ROLE_PERIPH; - UNUSED_VARIABLE(central); -#endif // !defined (S112) - } - - return role; -} - - -ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle) -{ - ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID; - bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle); - - if (valid) - { - bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.connected_flags, - conn_handle); - - conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED; - } - - return conn_status; -} - - -bool ble_conn_state_encrypted(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.encrypted_flags, - conn_handle); -} - - -bool ble_conn_state_mitm_protected(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.mitm_protected_flags, - conn_handle); -} - - -uint32_t ble_conn_state_n_connections(void) -{ - return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags); -} - - -uint32_t ble_conn_state_n_centrals(void) -{ - return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -uint32_t ble_conn_state_n_peripherals(void) -{ - return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, - (m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, - (~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -uint8_t ble_conn_state_conn_idx(uint16_t conn_handle) -{ - uint8_t index; - if (sdk_mapped_flags_get_by_key_w_idx(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle, - &index)) - { - return index; - } - else - { - return BLE_CONN_STATE_MAX_CONNECTIONS; - } -} - - -ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void) -{ - for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0; - i < BLE_CONN_STATE_N_USER_FLAGS; - i++) - { - if ( !user_flag_is_acquired(i) ) - { - user_flag_acquire(i); - return i; - } - } - - return BLE_CONN_STATE_USER_FLAG_INVALID; -} - - -bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id) -{ - if (user_flag_is_acquired(flag_id)) - { - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.user_flags[flag_id], - conn_handle); - } - else - { - return false; - } -} - - -void ble_conn_state_user_flag_set(uint16_t conn_handle, - ble_conn_state_user_flag_id_t flag_id, - bool value) -{ - if (user_flag_is_acquired(flag_id)) - { - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.user_flags[flag_id], - conn_handle, - value); - } -} - - -sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id) -{ - if ( user_flag_is_acquired(flag_id) ) - { - return m_bcs.flags.user_flags[flag_id]; - } - else - { - return 0; - } -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h deleted file mode 100644 index 878b8d838a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h +++ /dev/null @@ -1,317 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file - * - * @defgroup ble_conn_state Connection state - * @ingroup ble_sdk_lib - * @{ - * @brief Module for storing data on BLE connections. - * - * @details This module stores certain states for each connection, which can be queried by - * connection handle. The module uses BLE events to keep the states updated. - * - * In addition to the preprogrammed states, this module can also keep track of a number of - * binary user states, or user flags. These are reset to 0 for new connections, but - * otherwise not touched by this module. - * - * This module uses the @ref sdk_mapped_flags module, with connection handles as keys and - * the connection states as flags. - * - * @note A connection handle is not immediately invalidated when it is disconnected. Certain states, - * such as the role, can still be queried until the next time a new connection is established - * to any device. - * - */ - -#ifndef BLE_CONN_STATE_H__ -#define BLE_CONN_STATE_H__ - -#include -#include -#include "nrf_ble.h" -#include "sdk_mapped_flags.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Connection handle statuses. - */ -typedef enum -{ - BLE_CONN_STATUS_INVALID, /**< The connection handle is invalid. */ - BLE_CONN_STATUS_DISCONNECTED, /**< The connection handle refers to a connection that has been disconnected, but not yet invalidated. */ - BLE_CONN_STATUS_CONNECTED, /**< The connection handle refers to an active connection. */ -} ble_conn_state_status_t; - -#define BLE_CONN_STATE_MAX_CONNECTIONS 20 /**< The maximum number of connections supported. */ -#define BLE_CONN_STATE_N_USER_FLAGS 24 /**< The number of available user flags. */ - - -/**@brief One ID for each user flag collection. - * - * @details These IDs are used to identify user flag collections in the API calls. - */ -typedef enum -{ - BLE_CONN_STATE_USER_FLAG0 = 0, - BLE_CONN_STATE_USER_FLAG1, - BLE_CONN_STATE_USER_FLAG2, - BLE_CONN_STATE_USER_FLAG3, - BLE_CONN_STATE_USER_FLAG4, - BLE_CONN_STATE_USER_FLAG5, - BLE_CONN_STATE_USER_FLAG6, - BLE_CONN_STATE_USER_FLAG7, - BLE_CONN_STATE_USER_FLAG8, - BLE_CONN_STATE_USER_FLAG9, - BLE_CONN_STATE_USER_FLAG10, - BLE_CONN_STATE_USER_FLAG11, - BLE_CONN_STATE_USER_FLAG12, - BLE_CONN_STATE_USER_FLAG13, - BLE_CONN_STATE_USER_FLAG14, - BLE_CONN_STATE_USER_FLAG15, - BLE_CONN_STATE_USER_FLAG16, - BLE_CONN_STATE_USER_FLAG17, - BLE_CONN_STATE_USER_FLAG18, - BLE_CONN_STATE_USER_FLAG19, - BLE_CONN_STATE_USER_FLAG20, - BLE_CONN_STATE_USER_FLAG21, - BLE_CONN_STATE_USER_FLAG22, - BLE_CONN_STATE_USER_FLAG23, - BLE_CONN_STATE_USER_FLAG_INVALID, -} ble_conn_state_user_flag_id_t; - - -/** - * @defgroup ble_conn_state_functions BLE connection state functions - * @{ - */ - - -/**@brief Function for initializing or resetting the module. - * - * @details This function sets all states to their default, removing all records of connection handles. - */ -void ble_conn_state_init(void); - - -/**@brief Function for querying whether a connection handle represents a valid connection. - * - * @details A connection might be valid and have a BLE_CONN_STATUS_DISCONNECTED status. - * Those connections are invalidated after a new connection occurs. - * - * @param[in] conn_handle Handle of the connection. - * - * @retval true If conn_handle represents a valid connection, thus a connection for which - we have a record. - * @retval false If conn_handle is @ref BLE_GAP_ROLE_INVALID, or if it has never been recorded. - */ -bool ble_conn_state_valid(uint16_t conn_handle); - - -/**@brief Function for querying the role of the local device in a connection. - * - * @param[in] conn_handle Handle of the connection to get the role for. - * - * @return The role of the local device in the connection (see @ref BLE_GAP_ROLES). - * If conn_handle is not valid, the function returns BLE_GAP_ROLE_INVALID. - */ -uint8_t ble_conn_state_role(uint16_t conn_handle); - - -/**@brief Function for querying the status of a connection. - * - * @param[in] conn_handle Handle of the connection. - * - * @return The status of the connection. - * If conn_handle is not valid, the function returns BLE_CONN_STATE_INVALID. - */ -ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle); - - -/**@brief Function for querying whether a connection is encrypted. - * - * @param[in] conn_handle Handle of connection to get the encryption state for. - * - * @retval true If the connection is encrypted. - * @retval false If the connection is not encrypted or conn_handle is invalid. - */ -bool ble_conn_state_encrypted(uint16_t conn_handle); - - -/**@brief Function for querying whether a connection encryption is protected from Man in the Middle - * attacks. - * - * @param[in] conn_handle Handle of connection to get the MITM state for. - * - * @retval true If the connection is encrypted with MITM protection. - * @retval false If the connection is not encrypted, or encryption is not MITM protected, or - * conn_handle is invalid. - */ -bool ble_conn_state_mitm_protected(uint16_t conn_handle); - - -/**@brief Function for querying the total number of connections. - * - * @return The total number of valid connections for which the module has a record. - */ -uint32_t ble_conn_state_n_connections(void); - - -/**@brief Function for querying the total number of connections in which the role of the local - * device is @ref BLE_GAP_ROLE_CENTRAL. - * - * @return The number of connections in which the role of the local device is - * @ref BLE_GAP_ROLE_CENTRAL. - */ -uint32_t ble_conn_state_n_centrals(void); - - -/**@brief Function for querying the total number of connections in which the role of the local - * device is @ref BLE_GAP_ROLE_PERIPH. - * - * @return The number of connections in which the role of the local device is - * @ref BLE_GAP_ROLE_PERIPH. - */ -uint32_t ble_conn_state_n_peripherals(void); - - -/**@brief Function for obtaining a list of all connection handles for which the module has a record. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record. - */ -sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void); - - -/**@brief Function for obtaining a list of connection handles in which the role of the local - * device is @ref BLE_GAP_ROLE_CENTRAL. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record and in which - * the role of local device is @ref BLE_GAP_ROLE_CENTRAL. - */ -sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void); - - -/**@brief Function for obtaining the handle for the connection in which the role of the local device - * is @ref BLE_GAP_ROLE_PERIPH. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record and in which - * the role of local device is @ref BLE_GAP_ROLE_PERIPH. - */ -sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void); - - -/**@brief Function for translating a connection handle to a value that can be used as an array index. - * - * @details Function for mapping connection handles onto the range <0 - MAX_CONNECTIONS>. - * - * @note The index will be the same as long as a connection is invalid. A subsequent connection with - * the same connection handle might have a different index. - * - * @param[in] conn_handle The connection for which to retrieve an index. - * - * @return An index unique to this connection. Or @ref BLE_CONN_STATE_MAX_CONNECTIONS if - * @p conn_handle refers to an invalid connection. - */ -uint8_t ble_conn_state_conn_idx(uint16_t conn_handle); - - -/**@brief Function for obtaining exclusive access to one of the user flag collections. - * - * @details The acquired collection contains one flag for each connection. These flags can be set - * and read individually for each connection. - * - * The state of user flags will not be modified by the connection state module, except to - * set it to 0 for a connection when that connection is invalidated. - * - * @return The ID of the acquired flag, or BLE_CONN_STATE_USER_FLAG_INVALID if none are available. - */ -ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void); - - -/**@brief Function for reading the value of a user flag. - * - * @param[in] conn_handle Handle of connection to get the flag state for. - * @param[in] flag_id Which flag to get the state for. - * - * @return The state of the flag. If conn_handle is invalid, the function returns false. - */ -bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id); - - -/**@brief Function for setting the value of a user flag. - * - * @param[in] conn_handle Handle of connection to set the flag state for. - * @param[in] flag_id Which flag to set the state for. - * @param[in] value Value to set the flag state to. - */ -void ble_conn_state_user_flag_set(uint16_t conn_handle, - ble_conn_state_user_flag_id_t flag_id, - bool value); - - -/**@brief Function for getting the state of a user flag for all connection handles. - * - * @details The returned collection can be used with the @ref sdk_mapped_flags API. The returned - * collection is a copy, so modifying it has no effect on the conn_state module. - * - * @param[in] flag_id Which flag to get states for. - * - * @return The collection of flag states. The collection is always all zeros when the flag_id is - * unregistered. - */ -sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id); - -/** @} */ -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif /* BLE_CONN_STATE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h deleted file mode 100644 index 762784c11a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2011 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! -* To maintain compliance with Nordic Semiconductor ASA’s Bluetooth profile -* qualification listings, this section of source code must not be modified. -*/ - -/** @file - * @brief Contains definition of ble_date_time structure. - */ - -/** @file - * - * @defgroup ble_sdk_srv_date_time BLE Date Time characteristic type - * @{ - * @ingroup ble_sdk_lib - * @brief Definition of ble_date_time_t type. - */ - -#ifndef BLE_DATE_TIME_H__ -#define BLE_DATE_TIME_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Date and Time structure. */ -typedef struct -{ - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hours; - uint8_t minutes; - uint8_t seconds; -} ble_date_time_t; - -static __INLINE uint8_t ble_date_time_encode(const ble_date_time_t * p_date_time, - uint8_t * p_encoded_data) -{ - uint8_t len = uint16_encode(p_date_time->year, p_encoded_data); - - p_encoded_data[len++] = p_date_time->month; - p_encoded_data[len++] = p_date_time->day; - p_encoded_data[len++] = p_date_time->hours; - p_encoded_data[len++] = p_date_time->minutes; - p_encoded_data[len++] = p_date_time->seconds; - - return len; -} - -static __INLINE uint8_t ble_date_time_decode(ble_date_time_t * p_date_time, - const uint8_t * p_encoded_data) -{ - uint8_t len = sizeof(uint16_t); - - p_date_time->year = uint16_decode(p_encoded_data); - p_date_time->month = p_encoded_data[len++]; - p_date_time->day = p_encoded_data[len++]; - p_date_time->hours = p_encoded_data[len++]; - p_date_time->minutes = p_encoded_data[len++]; - p_date_time->seconds = p_encoded_data[len++]; - - return len; -} - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DATE_TIME_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h deleted file mode 100644 index 3b35773e0b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_sdk_lib_gatt_db GATT Database Service Structure - * @{ - * @ingroup ble_sdk_lib - */ - -#ifndef BLE_GATT_DB_H__ -#define BLE_GATT_DB_H__ - -#include -#include "nrf_ble.h" -#include "ble_gattc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_GATT_DB_MAX_CHARS 6 /**< The maximum number of characteristics present in a service record. */ - -/**@brief Structure for holding the characteristic and the handle of its CCCD present on a server. - */ -typedef struct -{ - ble_gattc_char_t characteristic; /**< Structure containing information about the characteristic. */ - uint16_t cccd_handle; /**< CCCD Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a CCCD is not present at the server. */ - uint16_t ext_prop_handle; /**< Extended Properties Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if an Extended Properties descriptor is not present at the server. */ - uint16_t user_desc_handle; /**< User Description Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a User Description descriptor is not present at the server. */ - uint16_t report_ref_handle; /**< Report Reference Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a Report Reference descriptor is not present at the server. */ -} ble_gatt_db_char_t; - -/**@brief Structure for holding information about the service and the characteristics present on a - * server. - */ -typedef struct -{ - ble_uuid_t srv_uuid; /**< UUID of the service. */ - uint8_t char_count; /**< Number of characteristics present in the service. */ - ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ - ble_gatt_db_char_t charateristics[BLE_GATT_DB_MAX_CHARS]; /**< Array of information related to the characteristics present in the service. This list can extend further than one. */ -} ble_gatt_db_srv_t; - - -#ifdef __cplusplus -} -#endif - -#endif /* BLE_GATT_DB_H__ */ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h deleted file mode 100644 index ca259f1450..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! -* To maintain compliance with Nordic Semiconductor ASA’s Bluetooth profile -* qualification listings, this section of source code must not be modified. -*/ - -#ifndef BLE_SENSOR_LOCATION_H__ -#define BLE_SENSOR_LOCATION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BLE_SENSOR_LOCATION_OTHER = 0 , /**<-- Other */ - BLE_SENSOR_LOCATION_TOP_OF_SHOE = 1 , /**<-- Top of shoe */ - BLE_SENSOR_LOCATION_IN_SHOE = 2 , /**<-- In shoe */ - BLE_SENSOR_LOCATION_HIP = 3 , /**<-- Hip */ - BLE_SENSOR_LOCATION_FRONT_WHEEL = 4 , /**<-- Front Wheel */ - BLE_SENSOR_LOCATION_LEFT_CRANK = 5 , /**<-- Left Crank */ - BLE_SENSOR_LOCATION_RIGHT_CRANK = 6 , /**<-- Right Crank */ - BLE_SENSOR_LOCATION_LEFT_PEDAL = 7 , /**<-- Left Pedal */ - BLE_SENSOR_LOCATION_RIGHT_PEDAL = 8 , /**<-- Right Pedal */ - BLE_SENSOR_LOCATION_FRONT_HUB = 9 , /**<-- Front Hub */ - BLE_SENSOR_LOCATION_REAR_DROPOUT = 10, /**<-- Rear Dropout */ - BLE_SENSOR_LOCATION_CHAINSTAY = 11, /**<-- Chainstay */ - BLE_SENSOR_LOCATION_REAR_WHEEL = 12, /**<-- Rear Wheel */ - BLE_SENSOR_LOCATION_REAR_HUB = 13, /**<-- Rear Hub */ -}ble_sensor_location_t; - -#define BLE_NB_MAX_SENSOR_LOCATIONS 14 - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_SENSOR_LOCATION_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c deleted file mode 100644 index db90cc0693..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! - * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile - * qualification listings, this section of source code must not be modified. - */ - -#include "ble_srv_common.h" -#include -#include "nordic_common.h" -#include "app_error.h" -#include "nrf_ble.h" - -bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data) -{ - uint16_t cccd_value = uint16_decode(p_encoded_data); - return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); -} - -bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data) -{ - uint16_t cccd_value = uint16_decode(p_encoded_data); - return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0); -} - -uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, - const ble_srv_report_ref_t * p_report_ref) -{ - uint8_t len = 0; - - p_encoded_buffer[len++] = p_report_ref->report_id; - p_encoded_buffer[len++] = p_report_ref->report_type; - - APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN); - return len; -} - - -void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii) -{ - p_utf8->length = (uint16_t)strlen(p_ascii); - p_utf8->p_str = (uint8_t *)p_ascii; -} - - -/**@brief Function for setting security requirements of a characteristic. - * - * @param[in] level required security level. - * @param[out] p_perm Characteristic security requirements. - * - * @return encoded security level and security mode. - */ -static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) -{ - - - BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); - switch (level) - { - case SEC_NO_ACCESS: - BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); - break; - case SEC_OPEN: - BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); - break; - case SEC_JUST_WORKS: - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); - break; - case SEC_MITM: - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); - break; - case SEC_SIGNED: - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); - break; - case SEC_SIGNED_MITM: - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); - break; - } - return; -} - - -uint32_t characteristic_add(uint16_t service_handle, - ble_add_char_params_t * p_char_props, - ble_gatts_char_handles_t * p_char_handle) -{ - ble_gatts_char_md_t char_md; - ble_gatts_attr_t attr_char_value; - ble_uuid_t char_uuid; - ble_gatts_attr_md_t attr_md; - ble_gatts_attr_md_t user_descr_attr_md; - ble_gatts_attr_md_t cccd_md; - - if (p_char_props->uuid_type == 0) - { - char_uuid.type = BLE_UUID_TYPE_BLE; - } - else - { - char_uuid.type = p_char_props->uuid_type; - } - char_uuid.uuid = p_char_props->uuid; - - memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t)); - set_security_req(p_char_props->read_access, &attr_md.read_perm); - set_security_req(p_char_props->write_access, & attr_md.write_perm); - attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0); - attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0); - attr_md.vlen = (p_char_props->is_var_len ? 1 : 0); - attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - - - memset(&char_md, 0, sizeof(ble_gatts_char_md_t)); - if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1)) - { - - memset(&cccd_md, 0, sizeof(cccd_md)); - set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - - cccd_md.vloc = BLE_GATTS_VLOC_STACK; - - char_md.p_cccd_md = &cccd_md; - } - char_md.char_props = p_char_props->char_props; - char_md.char_ext_props = p_char_props->char_ext_props; - - memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t)); - attr_char_value.p_uuid = &char_uuid; - attr_char_value.p_attr_md = &attr_md; - attr_char_value.max_len = p_char_props->max_len; - if (p_char_props->p_init_value != NULL) - { - attr_char_value.init_len = p_char_props->init_len; - attr_char_value.p_value = p_char_props->p_init_value; - } - if (p_char_props->p_user_descr != NULL) - { - memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t)); - char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size; - char_md.char_user_desc_size = p_char_props->p_user_descr->size; - char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc; - - char_md.p_user_desc_md = &user_descr_attr_md; - - set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm); - set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm); - - user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0); - user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0); - user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0); - user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - } - if (p_char_props->p_presentation_format != NULL) - { - char_md.p_char_pf = p_char_props->p_presentation_format; - } - return sd_ble_gatts_characteristic_add(service_handle, - &char_md, - &attr_char_value, - p_char_handle); -} - - -uint32_t descriptor_add(uint16_t char_handle, - ble_add_descr_params_t * p_descr_props, - uint16_t * p_descr_handle) -{ - ble_gatts_attr_t descr_params; - ble_uuid_t desc_uuid; - ble_gatts_attr_md_t attr_md; - - memset(&descr_params, 0, sizeof(descr_params)); - if (p_descr_props->uuid_type == 0) - { - desc_uuid.type = BLE_UUID_TYPE_BLE; - } - else - { - desc_uuid.type = p_descr_props->uuid_type; - } - desc_uuid.uuid = p_descr_props->uuid; - descr_params.p_uuid = &desc_uuid; - - set_security_req(p_descr_props->read_access, &attr_md.read_perm); - set_security_req(p_descr_props->write_access,&attr_md.write_perm); - - attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0); - attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0); - attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0); - attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - descr_params.p_attr_md = &attr_md; - - descr_params.init_len = p_descr_props->init_len; - descr_params.init_offs = p_descr_props->init_offs; - descr_params.max_len = p_descr_props->max_len; - descr_params.p_value = p_descr_props->p_value; - - return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle); -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h deleted file mode 100644 index a63ed2d41b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h +++ /dev/null @@ -1,409 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_sdk_srv_common Common service definitions - * @{ - * @ingroup ble_sdk_srv - * @brief Constants, type definitions, and functions that are common to all services. - */ - -#ifndef BLE_SRV_COMMON_H__ -#define BLE_SRV_COMMON_H__ - -#include -#include -#include "ble_types.h" -#include "app_util.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_gatt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @defgroup UUID_SERVICES Service UUID definitions - * @{ */ -#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ -#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ -#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ -#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ -#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */ -#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ -#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ -#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ -#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ -#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ -#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ -#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ -#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ -#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ -#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ -#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ -#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ -#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ -#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */ -#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/ -#define BLE_UUID_CGM_SERVICE 0x181F /**< Continuous Glucose Monitoring service UUID*/ -#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/ -#define BLE_UUID_OTS_SERVICE 0x1825 /**< Object Transfer Service UUID*/ - -/** @} */ - -/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions - * @{ */ -#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */ -#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */ -#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */ -#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */ -#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */ -#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */ -#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */ -#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */ -#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */ -#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */ -#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */ -#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */ -#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */ -#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */ -#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */ -#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */ -#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */ -#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */ -#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */ -#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */ -#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */ -#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */ -#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */ -#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */ -#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */ -#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */ -#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */ -#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */ -#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */ -#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */ -#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */ -#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */ -#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */ -#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */ -#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */ -#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */ -#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */ -#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */ -#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */ -#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */ -#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */ -#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */ -#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */ -#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */ -#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */ -#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */ -#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */ -#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */ -#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */ -#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */ -#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */ -#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */ -#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */ -#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */ -#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */ -#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */ -#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */ -#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */ -#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */ -#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */ -#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */ -#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */ -#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */ -#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */ -#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */ -#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */ -#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */ -#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */ -#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */ -#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */ -#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */ -#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */ -#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */ -#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */ -#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */ -#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/ -#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/ -#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/ -#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/ -#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/ -#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/ -#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/ -#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/ -#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/ -#define BLE_UUID_OTS_FEATURES 0x2ABD /**< OTS Service, feature characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_NAME 0x2ABE /**< OTS Service, Object Name characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_TYPE 0x2ABF /**< OTS Service, Object Type characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_SIZE 0x2AC0 /**< OTS Service, Object Size characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_FIRST_CREATED 0x2AC1 /**< OTS Service, Object First Created characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_LAST_MODIFIED 0x2AC2 /**< OTS Service, Object Last Modified characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_ID 0x2AC3 /**< OTS Service, Object ID characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_PROPERTIES 0x2AC4 /**< OTS Service, Object Properties characteristic UUID*/ -#define BLE_UUID_OTS_OACP 0x2AC5 /**< OTS Service, Object Action Control Point characteristic UUID*/ -#define BLE_UUID_OTS_OLCP 0x2AC6 /**< OTS Service, Object List Control Point characteristic UUID*/ -#define BLE_UUID_OTS_LF 0x2AC7 /**< OTS Service, Object List Filter characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_CHANGED 0x2AC8 /**< OTS Service, Object Changed characteristic UUID*/ - - - - -/** @} */ - -/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values - * @{ */ -#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */ -#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */ -#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */ -/** @} */ - -#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */ -#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */ - -/**@brief Type definition for error handler function that will be called in case of an error in - * a service or a service library module. */ -typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error); - - - -/**@brief Value of a Report Reference descriptor. - * - * @details This is mapping information that maps the parent characteristic to the Report ID(s) and - * Report Type(s) defined within a Report Map characteristic. - */ -typedef struct -{ - uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */ - uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */ -} ble_srv_report_ref_t; - -/**@brief UTF-8 string data type. - * - * @note The type can only hold a pointer to the string data (i.e. not the actual data). - */ -typedef struct -{ - uint16_t length; /**< String length. */ - uint8_t * p_str; /**< String data. */ -} ble_srv_utf8_str_t; - - -/**@brief Security settings structure. - * @details This structure contains the security options needed during initialization of the - * service. - */ -typedef struct -{ - ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ - ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ -} ble_srv_security_mode_t; - -/**@brief Security settings structure. - * @details This structure contains the security options needed during initialization of the - * service. It can be used when the characteristics contains a CCCD. - */ -typedef struct -{ - ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */ - ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ - ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ -} ble_srv_cccd_security_mode_t; - -/**@brief Function for decoding a CCCD value, and then testing if notification is - * enabled. - * - * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. - * - * @retval TRUE If notification is enabled. - * @retval FALSE Otherwise. - */ -bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data); - - -/**@brief Function for decoding a CCCD value, and then testing if indication is - * enabled. - * - * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. - * - * @retval TRUE If indication is enabled. - * @retval FALSE Otherwise. - */ -bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data); - - -/**@brief Function for encoding a Report Reference Descriptor. - * - * @param[in] p_encoded_buffer The buffer of the encoded data. - * @param[in] p_report_ref Report Reference value to be encoded. - * - * @return Length of the encoded data. - */ -uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, - const ble_srv_report_ref_t * p_report_ref); - -/**@brief Function for making a UTF-8 structure refer to an ASCII string. - * - * @param[out] p_utf8 UTF-8 structure to be set. - * @param[in] p_ascii ASCII string to be referred to. - */ -void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii); - - -/**@brief Security Access enumeration. - * @details This enumeration gives the possible requirements for accessing a characteristic value. - */ -typedef enum -{ - SEC_NO_ACCESS = 0, /**< Not possible to access. */ - SEC_OPEN = 1, /**< Access open. */ - SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */ - SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */ - SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */ - SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */ -}security_req_t; - - -/**@brief Characteristic User Descriptor parameters. - * @details This structure contains the parameters for User Descriptor. - */ -typedef struct -{ - uint16_t max_size; /**< Maximum size of the user descriptor*/ - uint16_t size; /**< Size of the user descriptor*/ - uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/ - bool is_var_len; /**< Indicates if the user descriptor has variable length.*/ - ble_gatt_char_props_t char_props; /**< user descriptor properties.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - security_req_t read_access; /**< Security requirement for reading the user descriptor.*/ - security_req_t write_access; /**< Security requirement for writing the user descriptor.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ -}ble_add_char_user_desc_t; - - -/**@brief Add characteristic parameters structure. - * @details This structure contains the parameters needed to use the @ref characteristic_add function. - */ -typedef struct -{ - uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/ - uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ - uint16_t max_len; /**< Maximum length of the characteristic value.*/ - uint16_t init_len; /**< Initial length of the characteristic value.*/ - uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/ - bool is_var_len; /**< Indicates if the characteristic value has variable length.*/ - ble_gatt_char_props_t char_props; /**< Characteristic properties.*/ - ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic extended properties.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - security_req_t read_access; /**< Security requirement for reading the characteristic value.*/ - security_req_t write_access; /**< Security requirement for writing the characteristic value.*/ - security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ - ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/ - ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/ -} ble_add_char_params_t; - - -/**@brief Add descriptor parameters structure. - * @details This structure contains the parameters needed to use the @ref descriptor_add function. - */ -typedef struct -{ - uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/ - uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - bool is_var_len; /**< Indicates if the descriptor value has variable length.*/ - security_req_t read_access; /**< Security requirement for reading the descriptor value.*/ - security_req_t write_access; /**< Security requirement for writing the descriptor value.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ - uint16_t init_len; /**< Initial descriptor value length in bytes. */ - uint16_t init_offs; /**< Initial descriptor value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ - uint16_t max_len; /**< Maximum descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ - uint8_t* p_value; /**< Pointer to the value of the descriptor*/ -} ble_add_descr_params_t; - - -/**@brief Function for adding a characteristic to a given service. - * - * If no pointer is given for the initial value, - * the initial length parameter will be ignored and the initial length will be 0. - * - * @param[in] service_handle Handle of the service to which the characteristic is to be added. - * @param[in] p_char_props Information needed to add the characteristic. - * @param[out] p_char_handle Handle of the added characteristic. - * - * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. - */ -uint32_t characteristic_add(uint16_t service_handle, - ble_add_char_params_t * p_char_props, - ble_gatts_char_handles_t * p_char_handle); - - -/**@brief Function for adding a characteristic's descriptor to a given characteristic. - * - * @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. - * @param[in] p_descr_props Information needed to add the descriptor. - * @param[out] p_descr_handle Handle of the added descriptor. - * - * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. - */ -uint32_t descriptor_add(uint16_t char_handle, - ble_add_descr_params_t * p_descr_props, - uint16_t * p_descr_handle); - - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_SRV_COMMON_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c deleted file mode 100644 index baa42956fa..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c +++ /dev/null @@ -1,552 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_GATT) - -#include "nrf_ble_gatt.h" - -#define NRF_LOG_MODULE_NAME ble_gatt -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - - -#define L2CAP_HDR_LEN 4 //!< Length of a L2CAP header, in bytes. - - -STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE <= 251); -STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN <= 255); - - -/**@brief Initialize a link's parameters to defaults. */ -static void link_init(nrf_ble_gatt_link_t * p_link) -{ - p_link->att_mtu_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_link->att_mtu_effective = BLE_GATT_ATT_MTU_DEFAULT; - p_link->att_mtu_exchange_pending = false; - p_link->att_mtu_exchange_requested = false; -#if !defined (S112) - p_link->data_length_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; - p_link->data_length_effective = BLE_GATT_ATT_MTU_DEFAULT + L2CAP_HDR_LEN; -#endif // !defined (S112) -} - -/**@brief Start a data length update request. - * @details This function is called to request a data length update upon connection. - * When the peer requests a data length update, sd_ble_gap_data_length_update() - * is called directly in response to the BLE_GAP_EVT_DATA_LENGTH_UPDATE event in - * on_data_length_update_evt(). - */ -#if !defined (S112) -static void data_length_update(uint16_t conn_handle, nrf_ble_gatt_t const * p_gatt) -{ - NRF_LOG_DEBUG("Requesting to update data length to %u on connection 0x%x.", - p_gatt->links[conn_handle].data_length_desired, conn_handle); - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = p_gatt->links[conn_handle].data_length_desired, - .max_tx_octets = p_gatt->links[conn_handle].data_length_desired, - .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO, - .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO, - }; - - ret_code_t err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gap_data_length_update() (request)" - " on connection 0x%x returned unexpected value 0x%x.", - conn_handle, err_code); - } -} -#endif // !defined (S112) - - -/**@brief Handle a connected event. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_connected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - // Update the link desired settings to reflect the current global settings. -#if !defined (S112) - p_link->data_length_desired = p_gatt->data_length; -#endif // !defined (S112) - switch (p_ble_evt->evt.gap_evt.params.connected.role) - { - case BLE_GAP_ROLE_PERIPH: - p_link->att_mtu_desired = p_gatt->att_mtu_desired_periph; - break; -#if !defined (S112) - case BLE_GAP_ROLE_CENTRAL: - p_link->att_mtu_desired = p_gatt->att_mtu_desired_central; - break; -#endif // !defined (S112) - default: - // Ignore. - break; - } - - // Begin an ATT MTU exchange if necessary. - if (p_link->att_mtu_desired > p_link->att_mtu_effective) - { - NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x.", - p_link->att_mtu_desired, conn_handle); - - err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, p_link->att_mtu_desired); - - if (err_code == NRF_SUCCESS) - { - p_link->att_mtu_exchange_requested = true; - } - else if (err_code == NRF_ERROR_BUSY) - { - p_link->att_mtu_exchange_pending = true; - NRF_LOG_DEBUG("sd_ble_gattc_exchange_mtu_request()" - " on connection 0x%x returned busy, will retry.", conn_handle); - } - else - { - NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request()" - " returned unexpected value 0x%x.", - err_code); - } - } - -#if !defined (S112) - // Send a data length update request if necessary. - if (p_link->data_length_desired > p_link->data_length_effective) - { - data_length_update(conn_handle, p_gatt); - } -#endif // !defined (S112) -} - - -static void on_disconnected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - // Reset connection parameters. - link_init(&p_gatt->links[p_ble_evt->evt.gap_evt.conn_handle]); -} - - -/**@brief Handle a BLE_GATTC_EVT_EXCHANGE_MTU_RSP event. - * - * @details The effective ATT MTU is set to the lowest between what we requested and the peer's - * response. This events concludes the ATT MTU exchange. An event is sent to the user - * and a data length update procedure is started if necessary. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_exchange_mtu_rsp_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; - uint16_t server_rx_mtu = p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu; - - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - // Determine the lowest MTU between our own desired MTU and the peer's. - // The MTU may not be less than BLE_GATT_ATT_MTU_DEFAULT. - p_link->att_mtu_effective = MIN(server_rx_mtu, p_link->att_mtu_desired); - p_link->att_mtu_effective = MAX(p_link->att_mtu_effective, BLE_GATT_ATT_MTU_DEFAULT); - - NRF_LOG_DEBUG("ATT MTU updated to %u bytes on connection 0x%x (response).", - p_link->att_mtu_effective, conn_handle); - - // Trigger an event indicating that the ATT MTU size has changed. - // Send an event to the application only if an ATT MTU exchange was requested. - if ((p_gatt->evt_handler != NULL) && (p_link->att_mtu_exchange_requested)) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, - .conn_handle = conn_handle, - .params.att_mtu_effective = p_link->att_mtu_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } - - p_link->att_mtu_exchange_requested = false; - p_link->att_mtu_exchange_pending = false; -} - - -/**@brief Handle a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_exchange_mtu_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; - uint16_t client_mtu = p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; - - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - NRF_LOG_DEBUG("Peer on connection 0x%x requested an ATT MTU of %u bytes.", - conn_handle, client_mtu); - - client_mtu = MAX(client_mtu, BLE_GATT_ATT_MTU_DEFAULT); - p_link->att_mtu_effective = MIN(client_mtu, p_link->att_mtu_desired); - p_link->att_mtu_exchange_pending = false; - - NRF_LOG_DEBUG("Updating ATT MTU to %u bytes (desired: %u) on connection 0x%x.", - p_link->att_mtu_effective, p_link->att_mtu_desired, conn_handle); - - err_code = sd_ble_gatts_exchange_mtu_reply(conn_handle, p_link->att_mtu_desired); - - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gatts_exchange_mtu_reply() returned unexpected value 0x%x.", - err_code); - } - - // If an ATT_MTU exchange was requested to the peer, defer sending - // the data length update request and the event to the application until - // the response for that request is received. - if (p_link->att_mtu_exchange_requested) - { - return; - } - - // The ATT MTU exchange has finished. Send an event to the application. - if (p_gatt->evt_handler != NULL) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, - .conn_handle = conn_handle, - .params.att_mtu_effective = p_link->att_mtu_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } -} - - -/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE event. - * - * @details Update the connection data length and send an event to the user. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -#if !defined (S112) -static void on_data_length_update_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ble_gap_evt_t const gap_evt = p_ble_evt->evt.gap_evt; - uint16_t const conn_handle = gap_evt.conn_handle; - - // Update the connection data length. - p_gatt->links[conn_handle].data_length_effective = - gap_evt.params.data_length_update.effective_params.max_tx_octets; - - NRF_LOG_DEBUG("Data length updated to %u on connection 0x%0x.", - p_gatt->links[conn_handle].data_length_effective, - conn_handle); - - NRF_LOG_DEBUG("max_rx_octets: %u", - gap_evt.params.data_length_update.effective_params.max_rx_octets); - NRF_LOG_DEBUG("max_tx_octets: %u", - gap_evt.params.data_length_update.effective_params.max_tx_octets); - NRF_LOG_DEBUG("max_rx_time: %u", - gap_evt.params.data_length_update.effective_params.max_rx_time_us); - NRF_LOG_DEBUG("max_tx_time: %u", - gap_evt.params.data_length_update.effective_params.max_tx_time_us); - - if (p_gatt->evt_handler != NULL) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED, - .conn_handle = conn_handle, - .params.data_length = p_gatt->links[conn_handle].data_length_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } -} -#endif // !defined (S112) - - -/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. - * - *@details Reply with a sd_ble_gap_data_length_update() call, using the minimum between the - * link's preferred data length, and what requested by the peer. - * The link preferred data length is set to the global preferred data length - * upon connection and can be overridden by calling nrf_ble_gatt_data_length_set(). - * The default is NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN. - * - *@note The SoftDevice will not send any BLE_GAP_EVT_DATA_LENGTH_UPDATE events on this side. - * Therefore, the connection data length is updated immediately and an event is sent - * to the user. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -#if !defined (S112) -static void on_data_length_update_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - - ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; - nrf_ble_gatt_link_t * p_link = &p_gatt->links[p_gap_evt->conn_handle]; - - uint8_t const data_length_peer = - p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; - - NRF_LOG_DEBUG("Peer on connection 0x%x requested a data length of %u bytes.", - p_gap_evt->conn_handle, data_length_peer); - - uint8_t const data_length = MIN(p_link->data_length_desired, data_length_peer); - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = data_length, - .max_tx_octets = data_length, - }; - - NRF_LOG_DEBUG("Updating data length to %u bytes on connection 0x%x.", - data_length, p_gap_evt->conn_handle); - - err_code = sd_ble_gap_data_length_update(p_gap_evt->conn_handle, &dlp, NULL); - - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gap_data_length_update() (reply)" - " returned unexpected value 0x%x.", - err_code); - } -} -#endif // !defined (S112) - - -ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - p_gatt->evt_handler = evt_handler; - p_gatt->att_mtu_desired_periph = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_gatt->data_length = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; - - for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++) - { - link_init(&p_gatt->links[i]); - } - - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->att_mtu_desired_periph = desired_mtu; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->att_mtu_desired_central = desired_mtu; - return NRF_SUCCESS; -} - - -uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle) -{ - if ((p_gatt == NULL) || (conn_handle >= NRF_BLE_GATT_LINK_COUNT)) - { - return 0; - } - - return p_gatt->links[conn_handle].att_mtu_effective; -} - -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, - uint16_t conn_handle, - uint8_t data_length) -{ - ret_code_t err_code; - - if (p_gatt == NULL) - { - return NRF_ERROR_NULL; - } - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - p_gatt->data_length = MIN(data_length, NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN); - return NRF_SUCCESS; - } - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->links[conn_handle].data_length_desired = data_length; - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = data_length, - .max_tx_octets = data_length, - }; - - err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); - return err_code; -} -#endif // !defined (S112) - - -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, - uint16_t conn_handle, - uint8_t * p_data_length) -{ - if ((p_gatt == NULL) || (p_data_length == NULL)) - { - return NRF_ERROR_NULL; - } - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - *p_data_length = p_gatt->data_length; - return NRF_SUCCESS; - } - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return NRF_ERROR_INVALID_PARAM; - } - - *p_data_length = p_gatt->links[conn_handle].data_length_effective; - return NRF_SUCCESS; -} -#endif // !defined (S112) - - -void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - nrf_ble_gatt_t * p_gatt = (nrf_ble_gatt_t *)p_context; - uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return; - } - - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connected_evt(p_gatt, p_ble_evt); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected_evt(p_gatt, p_ble_evt); - break; - - case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: - on_exchange_mtu_rsp_evt(p_gatt, p_ble_evt); - break; - - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - on_exchange_mtu_request_evt(p_gatt, p_ble_evt); - break; -#if !defined (S112) - case BLE_GAP_EVT_DATA_LENGTH_UPDATE: - on_data_length_update_evt(p_gatt, p_ble_evt); - break; - - case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: - on_data_length_update_request_evt(p_gatt, p_ble_evt); - break; -#endif // !defined (S112) - default: - break; - } - - if (p_gatt->links[conn_handle].att_mtu_exchange_pending) - { - ret_code_t err_code; - - err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, - p_gatt->links[conn_handle].att_mtu_desired); - - if (err_code == NRF_SUCCESS) - { - p_gatt->links[conn_handle].att_mtu_exchange_pending = false; - p_gatt->links[conn_handle].att_mtu_exchange_requested = true; - - NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x (retry).", - p_gatt->links[conn_handle].att_mtu_desired, conn_handle); - } - else if (err_code != NRF_ERROR_BUSY) - { - NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned unexpected value 0x%x.", - err_code); - } - } -} - -#endif //NRF_BLE_GATT_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h deleted file mode 100644 index 300efeb9ee..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup nrf_ble_gatt GATT module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for negotiating and keeping track of GATT connection parameters and updating the data length. - */ - -#ifndef NRF_BLE_GATT_H__ -#define NRF_BLE_GATT_H__ - -#include -#include -#include -#include "nrf_ble.h" -#include "ble_gatt.h" -#include "sdk_config.h" -#include "sdk_errors.h" -#include "app_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a nrf_ble_gatt instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define NRF_BLE_GATT_DEF(_name) \ -static nrf_ble_gatt_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - NRF_BLE_GATT_BLE_OBSERVER_PRIO, \ - nrf_ble_gatt_on_ble_evt, &_name) - -/**@brief The maximum number of peripheral and central connections combined. - * This value is based on what is configured in the SoftDevice handler sdk_config. - */ -#define NRF_BLE_GATT_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT) - - -/**@brief GATT module event types. */ -typedef enum -{ - NRF_BLE_GATT_EVT_ATT_MTU_UPDATED = 0xA77, //!< The ATT_MTU size was updated. - NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED = 0xDA7A, //!< The data length was updated. -} nrf_ble_gatt_evt_id_t; - -/**@brief GATT module event. */ -typedef struct -{ - nrf_ble_gatt_evt_id_t evt_id; //!< Event ID. - uint16_t conn_handle; //!< Connection handle on which the event happened. - union - { - uint16_t att_mtu_effective; //!< Effective ATT_MTU. -#if !defined (S112) - uint8_t data_length; //!< Data length value. -#endif // !defined (S112) - } params; -} nrf_ble_gatt_evt_t; - -// Forward declaration of the nrf_ble_gatt_t type. -typedef struct nrf_ble_gatt_s nrf_ble_gatt_t; - -/**@brief GATT module event handler type. - * - * The GATT module calls a function of this type when a parameter value is changed. - */ -typedef void (*nrf_ble_gatt_evt_handler_t) (nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt); - -/**@brief GATT information for each connection. */ -typedef struct -{ - uint16_t att_mtu_desired; //!< Requested ATT_MTU size (in bytes). - uint16_t att_mtu_effective; //!< Effective ATT_MTU size (in bytes). - bool att_mtu_exchange_pending; //!< Indicates that an ATT_MTU exchange request is pending (the call to @ref sd_ble_gattc_exchange_mtu_request returned @ref NRF_ERROR_BUSY). - bool att_mtu_exchange_requested; //!< Indicates that an ATT_MTU exchange request was made. -#if !defined (S112) - uint8_t data_length_desired; //!< Desired data length (in bytes). - uint8_t data_length_effective; //!< Requested data length (in bytes). -#endif // !defined (S112) -} nrf_ble_gatt_link_t; - - -/**@brief GATT structure that contains status information for the GATT module. */ -struct nrf_ble_gatt_s -{ - uint16_t att_mtu_desired_periph; //!< Requested ATT_MTU size for the next peripheral connection that is established. - uint16_t att_mtu_desired_central; //!< Requested ATT_MTU size for the next central connection that is established. - uint8_t data_length; //!< Data length to use for the next connection that is established. - nrf_ble_gatt_link_t links[NRF_BLE_GATT_LINK_COUNT]; //!< GATT related information for all active connections. - nrf_ble_gatt_evt_handler_t evt_handler; //!< GATT event handler. -}; - - -/**@brief Function for initializing the GATT module. - * - * @param[in] evt_handler Event handler. - * @param[out] p_gatt Pointer to the GATT structure. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - */ -ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler); - - -/**@brief Function for setting the ATT_MTU size for the next connection that is established as peripheral. - * - * @param[in] p_gatt Pointer to the GATT structure. - * @param[in] desired_mtu Requested ATT_MTU size. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than - * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller than - * @ref BLE_GATT_ATT_MTU_DEFAULT. - */ -ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); - - -/**@brief Function for setting the ATT_MTU size for the next connection that is established as central. - * - * @param[in,out] p_gatt Pointer to the GATT structure. - * @param[in] desired_mtu Requested ATT_MTU size. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than - * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller - * than @ref BLE_GATT_ATT_MTU_DEFAULT. - */ -ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); - - -/**@brief Function for setting the data length for a connection. - * - * @details If @p conn_handle is a handle to an existing connection, a data length update - * request is sent on that connection. - * If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, a data length update request - * is sent on the next connection that is established after the ATT_MTU - * exchange has completed. If no ATT_MTU exchange procedure is carried - * out (for example, if a default ATT_MTU size is used), the data length - * is not changed. - */ -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, - uint16_t conn_handle, - uint8_t data_length); -#endif // !defined (S112) - -/**@brief Function for retrieving the data length of a connection. - * - * @details If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, the function retrieves the data - * length that will be requested for the next connection. - * If @p conn_handle is a handle to an existing connection, the function retrieves - * the effective data length that was negotiated for that connection. - * - * @param[in,out] p_gatt Pointer to the GATT structure. - * @param[in] conn_handle The connection for which to retrieve the data length, or - * @ref BLE_CONN_HANDLE_INVALID to retrieve the requested data length - * for the next connection. - * @param[out] p_data_length The connection data length. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt or @p p_data_length is NULL. - * @retval NRF_ERROR_INVALID_PARAM If @p conn_handle is larger than @ref NRF_BLE_GATT_LINK_COUNT. - */ -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, - uint16_t conn_handle, - uint8_t * p_data_length); -#endif // !defined (S112) - -/**@brief Function for handling BLE stack events. - * - * @details This function handles events from the BLE stack that are of interest to the module. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Pointer to the GATT structure. - */ -void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); - - -/**@brief Function for getting the current ATT_MTU size for a given connection. - * - * @param[in] p_gatt Pointer to the GATT structure. - * @param[in] conn_handle Connection handle of the connection. - * - * @return ATT_MTU size for the given connection. - * @retval 0 If @p p_gatt is NULL or if @p conn_handle is larger than - * the supported maximum number of connections. - */ -uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle); - - -#ifdef __cplusplus -} -#endif - -#endif // NRF_BLE_GATT_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c deleted file mode 100644 index cafd24eca2..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c +++ /dev/null @@ -1,447 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_QWR) -#include -#include "nrf_ble_qwr.h" -#include "nrf_ble.h" -#include "ble_srv_common.h" - - -#define NRF_BLE_QWR_INITIALIZED 0xDE // Non-zero value used to make sure the given structure has been initialized by the module. -#define MODULE_INITIALIZED (p_qwr->initialized == NRF_BLE_QWR_INITIALIZED) -#include "sdk_macros.h" - -ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_init_t const * p_qwr_init) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_PARAM_NOT_NULL(p_qwr_init); - if (MODULE_INITIALIZED) - { - return NRF_ERROR_INVALID_STATE; - } - - memset(p_qwr->attr_handles, 0, sizeof(p_qwr->attr_handles)); - p_qwr->nb_registered_attr = 0; - p_qwr->error_handler = p_qwr_init->error_handler; - p_qwr->is_user_mem_reply_pending = false; - p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; - p_qwr->initialized = NRF_BLE_QWR_INITIALIZED; - p_qwr->mem_buffer = p_qwr_init->mem_buffer; - p_qwr->callback = p_qwr_init->callback; - p_qwr->nb_written_handles = 0; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_MODULE_INITIALIZED(); - - if (p_qwr->nb_registered_attr == NRF_BLE_QWR_ATTR_LIST_SIZE) - { - return (NRF_ERROR_NO_MEM); - } - - if (attr_handle == BLE_GATT_HANDLE_INVALID) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_qwr->attr_handles[p_qwr->nb_registered_attr] = attr_handle; - p_qwr->nb_registered_attr++; - - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, - uint16_t attr_handle, - uint8_t * p_mem, - uint16_t * p_len) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_PARAM_NOT_NULL(p_mem); - VERIFY_PARAM_NOT_NULL(p_len); - VERIFY_MODULE_INITIALIZED(); - - uint16_t i = 0; - uint16_t handle = BLE_GATT_HANDLE_INVALID; - uint16_t val_len = 0; - uint16_t val_offset = 0; - uint16_t cur_len = 0; - - do - { - handle = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - - if (handle == BLE_GATT_HANDLE_INVALID) - { - break; - } - - i += sizeof(uint16_t); - val_offset = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - i += sizeof(uint16_t); - val_len = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - i += sizeof(uint16_t); - - if (handle == attr_handle) - { - cur_len = val_offset + val_len; - if (cur_len <= *p_len) - { - memcpy((p_mem + val_offset), &(p_qwr->mem_buffer.p_mem[i]), val_len); - } - else - { - return NRF_ERROR_NO_MEM; - } - } - - i += val_len; - } - while (i < p_qwr->mem_buffer.len); - - *p_len = cur_len; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, - uint16_t conn_handle) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_MODULE_INITIALIZED(); - p_qwr->conn_handle = conn_handle; - return NRF_SUCCESS; -} - - -/**@brief checks if a user_mem_reply is pending, if so attempts to send it. - * - * @param[in] p_qwr QWR structure. - */ -static void user_mem_reply(nrf_ble_qwr_t * p_qwr) -{ - if (p_qwr->is_user_mem_reply_pending) - { - ret_code_t err_code = sd_ble_user_mem_reply(p_qwr->conn_handle, &p_qwr->mem_buffer); - if (err_code == NRF_SUCCESS) - { - p_qwr->is_user_mem_reply_pending = false; - } - else if (err_code == NRF_ERROR_BUSY) - { - p_qwr->is_user_mem_reply_pending = true; - } - else - { - p_qwr->error_handler(err_code); - } - } -} - - -/**@brief Handle a user memory request event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_common_evt User_mem_request event to be handled. - */ -static void on_user_mem_request(nrf_ble_qwr_t * p_qwr, - ble_common_evt_t const * p_common_evt) -{ - if (p_common_evt->conn_handle == p_qwr->conn_handle) - { - if (p_common_evt->params.user_mem_request.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) - { - p_qwr->is_user_mem_reply_pending = true; - user_mem_reply(p_qwr); - } - } -} - - -/**@brief Handle a user memory release event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_common_evt User_mem_release event to be handled. - */ -static void on_user_mem_release(nrf_ble_qwr_t * p_qwr, - ble_common_evt_t const * p_common_evt) -{ - if (p_common_evt->conn_handle == p_qwr->conn_handle) - { - if (p_common_evt->params.user_mem_release.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) - { - // Cancel the current operation. - p_qwr->nb_written_handles = 0; - } - } -} - - -/**@brief Handle a prepare write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write WRITE event to be handled. - */ -static void on_prepare_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - - uint32_t i; - - for (i = 0; i < p_qwr->nb_written_handles; i++) - { - if (p_qwr->written_attr_handles[i] == p_evt_write->handle) - { - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - break; - } - } - - if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) - { - for (i = 0; i < p_qwr->nb_registered_attr; i++) - { - if (p_qwr->attr_handles[i] == p_evt_write->handle) - { - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - p_qwr->written_attr_handles[p_qwr->nb_written_handles++] = p_evt_write->handle; - break; - } - } - } - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Cancel the current operation. - p_qwr->nb_written_handles = 0; - - // Report error to application. - p_qwr->error_handler(err_code); - } - -} - - -/**@brief Handle an execute write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write EXEC WRITE event to be handled. - */ -static void on_execute_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - - if (p_qwr->nb_written_handles == 0) - { - auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - return; - } - - for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) - { - nrf_ble_qwr_evt_t evt; - uint16_t ret_val; - - evt.evt_type = NRF_BLE_QWR_EVT_AUTH_REQUEST; - evt.attr_handle = p_qwr->written_attr_handles[i]; - ret_val = p_qwr->callback(p_qwr, &evt); - if (ret_val != BLE_GATT_STATUS_SUCCESS) - { - auth_reply.params.write.gatt_status = ret_val; - } - } - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - - // If the execute has not been rejected by any of the registered applications, propagate execute write event to all written handles. */ - if (auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) - { - for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) - { - nrf_ble_qwr_evt_t evt; - evt.evt_type = NRF_BLE_QWR_EVT_EXECUTE_WRITE; - evt.attr_handle = p_qwr->written_attr_handles[i]; - /*lint -e534 -save "Ignoring return value of function" */ - p_qwr->callback(p_qwr, &evt); - /*lint -restore*/ - - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - } - } - p_qwr->nb_written_handles = 0; -} - - -/**@brief Handle a cancel write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write EXEC WRITE event to be handled. - */ -static void on_cancel_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - p_qwr->nb_written_handles = 0; -} - - -/**@brief Handle a rw_authorize_request event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_gatts_evt RW_authorize_request event to be handled. - */ -static void on_rw_authorize_request(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_t const * p_gatts_evt) -{ - if (p_gatts_evt->conn_handle != p_qwr->conn_handle) - { - return; - } - - ble_gatts_evt_rw_authorize_request_t const * p_auth_req = &p_gatts_evt->params.authorize_request; - if (p_auth_req->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) - { - return; - } - - switch (p_auth_req->request.write.op) - { - case BLE_GATTS_OP_PREP_WRITE_REQ: - on_prepare_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_PREP_WRITE_REQ - - case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: - on_execute_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_EXEC_WRITE_REQ_NOW - - case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: - on_cancel_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL - - default: - // No implementation needed. - break; - } -} - - -void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_context); - VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); - - nrf_ble_qwr_t * p_qwr = (nrf_ble_qwr_t *)p_context; - - VERIFY_MODULE_INITIALIZED_VOID(); - - if (p_ble_evt->evt.common_evt.conn_handle == p_qwr->conn_handle) - { - user_mem_reply(p_qwr); - } - switch (p_ble_evt->header.evt_id) - { - case BLE_EVT_USER_MEM_REQUEST: - on_user_mem_request(p_qwr, &p_ble_evt->evt.common_evt); - break; // BLE_EVT_USER_MEM_REQUEST - - case BLE_EVT_USER_MEM_RELEASE: - on_user_mem_release(p_qwr, &p_ble_evt->evt.common_evt); - break; // BLE_EVT_USER_MEM_REQUEST - - case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: - on_rw_authorize_request(p_qwr, &p_ble_evt->evt.gatts_evt); - break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST - - case BLE_GAP_EVT_DISCONNECTED: - if (p_ble_evt->evt.gap_evt.conn_handle == p_qwr->conn_handle) - { - p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; - p_qwr->nb_written_handles = 0; - } - break; // BLE_GAP_EVT_DISCONNECTED - - default: - break; - } - -} -#endif // NRF_MODULE_ENABLED(NRF_BLE_QWR) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h deleted file mode 100644 index 7453730e00..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup nrf_ble_qwr Queued Writes module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for handling Queued Write operations. - * - * @details This module handles prepare write, execute write, and cancel write - * commands. It also manages memory requests related to these operations. - * - * @note The application must propagate BLE stack events to this module by calling - * @ref nrf_ble_qwr_on_ble_evt(). - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NRF_BLE_QUEUED_WRITES_H__ -#define NRF_BLE_QUEUED_WRITES_H__ - -#include -#include "nordic_common.h" -#include "sdk_common.h" -#include "nrf_ble.h" -#include "ble_srv_common.h" - -/**@brief Macro for defining a nrf_ble_qwr instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define NRF_BLE_QWR_DEF(_name) \ -static nrf_ble_qwr_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - NRF_BLE_QWR_BLE_OBSERVER_PRIO, \ - nrf_ble_qwr_on_ble_evt, &_name) - -#ifndef NRF_BLE_QWR_ATTR_LIST_SIZE -#define NRF_BLE_QWR_ATTR_LIST_SIZE 10 //!< Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. -#endif - -#define NRF_BLE_QWR_REJ_REQUEST_ERR_CODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 0 //!< Error code used by the module to reject prepare write requests on non-registered attributes. - - -/**@brief Queued Writes module event types. */ -typedef enum -{ - NRF_BLE_QWR_EVT_EXECUTE_WRITE, //!< Event that indicates that an execute write command was received for a registered handle and that the received data was actually written and is now ready. - NRF_BLE_QWR_EVT_AUTH_REQUEST, //!< Event that indicates that an execute write command was received for a registered handle and that the write request must now be accepted or rejected. -} nrf_ble_qwr_evt_type_t; - -/**@brief Queued Writes module events. */ -typedef struct -{ - nrf_ble_qwr_evt_type_t evt_type; //!< Type of the event. - uint16_t attr_handle; //!< Handle of the attribute to which the event relates. -} nrf_ble_qwr_evt_t; - -// Forward declaration of the nrf_ble_qwr_t type. -struct nrf_ble_qwr_t; - -/**@brief Queued Writes module event handler type. - * - * If the provided event is of type @ref NRF_BLE_QWR_EVT_AUTH_REQUEST, - * this function must accept or reject the execute write request by returning - * one of the @ref BLE_GATT_STATUS_CODES.*/ -typedef uint16_t (* nrf_ble_qwr_evt_handler_t) (struct nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_evt_t * p_evt); - -/**@brief Queued Writes structure. - * @details This structure contains status information for the Queued Writes module. */ -typedef struct nrf_ble_qwr_t -{ - uint8_t initialized; //!< Flag that indicates whether the module has been initialized. - uint16_t attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of handles for registered attributes, for which the module accepts and handles prepare write operations. - uint8_t nb_registered_attr; //!< Number of registered attributes. - uint16_t written_attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of attribute handles that have been written to during the current prepare write or execute write operation. - uint8_t nb_written_handles; //!< Number of attributes that have been written to during the current prepare write or execute write operation. - ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. - ble_srv_error_handler_t error_handler; //!< Error handler. - bool is_user_mem_reply_pending; //!< Flag that indicates whether a mem_reply is pending (because a previous attempt returned busy). - uint16_t conn_handle; //!< Connection handle. - nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. -} nrf_ble_qwr_t; - -/**@brief Queued Writes init structure. - * @details This structure contains all information - * that is needed to initialize the Queued Writes module. */ -typedef struct -{ - ble_srv_error_handler_t error_handler; //!< Error handler. - ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. - nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. -} nrf_ble_qwr_init_t; - - -/**@brief Function for initializing the Queued Writes module. - * - * @details Call this function in the main entry of your application to - * initialize the Queued Writes module. It must be called only once with a - * given Queued Writes structure. - * - * @param[out] p_qwr Queued Writes structure. This structure must be - * supplied by the application. It is initialized by this function - * and is later used to identify the particular Queued Writes instance. - * @param[in] p_qwr_init Initialization structure. - * - * @retval NRF_SUCCESS If the Queued Writes module was initialized successfully. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has already been initialized. - */ -ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_init_t const * p_qwr_init); - - -/**@brief Function for registering an attribute with the Queued Writes module. - * - * @details Call this function for each attribute that you want to enable for - * Queued Writes (thus a series of prepare write and execute write operations). - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] attr_handle Handle of the attribute to register. - * - * @retval NRF_SUCCESS If the registration was successful. - * @retval NRF_ERROR_NO_MEM If no more memory is available to add this registration. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle); - - -/**@brief Function for handling BLE stack events. - * - * @details Handles all events from the BLE stack that are of interest to the Queued Writes module. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Queued Writes structure. - */ -void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); - - -/**@brief Function for retrieving the received data for a given attribute. - * - * @details Call this function after receiving an @ref NRF_BLE_QWR_EVT_AUTH_REQUEST - * event to retrieve a linear copy of the data that was received for the given attribute. - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] attr_handle Handle of the attribute. - * @param[out] p_mem Pointer to the application buffer where the received data will be copied. - * @param[in,out] p_len Input: length of the input buffer. Output: length of the received data. - * - * - * @retval NRF_SUCCESS If the data was retrieved and stored successfully. - * @retval NRF_ERROR_NO_MEM If the provided buffer was smaller than the received data. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, - uint16_t attr_handle, - uint8_t * p_mem, - uint16_t * p_len); - - -/**@brief Function for assigning a connection handle to a given instance of the Queued Writes module. - * - * @details Call this function when a link with a peer has been established to - * associate this link to the instance of the module. This makes it - * possible to handle several links and associate each link to a particular - * instance of this module. - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] conn_handle Connection handle to be associated with the given Queued Writes instance. - * - * @retval NRF_SUCCESS If the assignment was successful. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, - uint16_t conn_handle); - -#ifdef __cplusplus -} -#endif - -#endif // NRF_BLE_QUEUED_WRITES_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c deleted file mode 100644 index 4d6d43111a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c +++ /dev/null @@ -1,568 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "gatt_cache_manager.h" - -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "id_manager.h" -#include "gatts_cache_manager.h" -#include "peer_database.h" -#include "pm_mutex.h" - - -// The number of registered event handlers. -#define GCM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - -// GATT Cache Manager event handler in Peer Manager. -extern void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt); - -// GATT Cache Manager events' handlers. -// The number of elements in this array is GCM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t m_evt_handlers[] = -{ - pm_gcm_evt_handler -}; - -static bool m_module_initialized; -static uint8_t m_db_update_in_progress_mutex; /**< Mutex indicating whether a local DB write operation is ongoing. */ -static ble_conn_state_user_flag_id_t m_flag_local_db_update_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB update procedure. */ -static ble_conn_state_user_flag_id_t m_flag_local_db_apply_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB apply procedure. */ -static ble_conn_state_user_flag_id_t m_flag_service_changed_pending; /**< Flag ID for flag collection to keep track of which connections need to be sent a service changed indication. */ -static ble_conn_state_user_flag_id_t m_flag_service_changed_sent; /**< Flag ID for flag collection to keep track of which connections have been sent a service changed indication and are waiting for a handle value confirmation. */ - - -/**@brief Function for resetting the module variable(s) of the GSCM module. - * - * @param[out] The instance to reset. - */ -static void internal_state_reset() -{ - m_module_initialized = false; -} - - -static void evt_send(pm_evt_t * p_gcm_evt) -{ - p_gcm_evt->peer_id = im_peer_id_get_by_conn_handle(p_gcm_evt->conn_handle); - - for (uint32_t i = 0; i < GCM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_gcm_evt); - } -} - - -/**@brief Function for checking a write event for whether a CCCD was written during the write - * operation. - * - * @param[in] p_write_evt The parameters of the write event. - * - * @return Whether the write was on a CCCD. - */ -static bool cccd_written(ble_gatts_evt_write_t const * p_write_evt) -{ - return ( (p_write_evt->op == BLE_GATTS_OP_WRITE_REQ) - && (p_write_evt->uuid.type == BLE_UUID_TYPE_BLE) - && (p_write_evt->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) - ); -} - - -/**@brief Function for sending an PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .conn_handle = conn_handle, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - evt_send(&error_evt); -} - - -/**@brief Function for performing the local DB update procedure in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static void local_db_apply_in_evt(uint16_t conn_handle) -{ - bool set_procedure_as_pending = false; - ret_code_t err_code; - pm_evt_t event = - { - .conn_handle = conn_handle, - }; - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - return; - } - - err_code = gscm_local_db_cache_apply(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLIED; - - evt_send(&event); - break; - - case NRF_ERROR_BUSY: - set_procedure_as_pending = true; - break; - - case NRF_ERROR_INVALID_DATA: - event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED; - - evt_send(&event); - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - /* Do nothing */ - break; - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_apply_pending, set_procedure_as_pending); -} - - -/**@brief Function for asynchronously starting a DB update procedure. - * - * @note This procedure can only be started asynchronously. - * - * @param[in] conn_handle The connection to perform the procedure on. - * @param[in] update Whether to perform the procedure. - */ -static __INLINE void local_db_update(uint16_t conn_handle, bool update) -{ - ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_update_pending, update); -} - - -/**@brief Function for performing the local DB update procedure in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static bool local_db_update_in_evt(uint16_t conn_handle) -{ - bool set_procedure_as_pending = false; - bool success = false; - ret_code_t err_code = gscm_local_db_cache_update(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - success = true; - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - /* Do nothing */ - break; - - case NRF_ERROR_BUSY: - set_procedure_as_pending = true; - break; - - case NRF_ERROR_STORAGE_FULL: - { - pm_evt_t event = - { - .evt_id = PM_EVT_STORAGE_FULL, - .conn_handle = conn_handle, - }; - - evt_send(&event); - break; - } - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - local_db_update(conn_handle, set_procedure_as_pending); - - return success; -} - - -/**@brief Function for sending a service changed indication in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static void service_changed_send_in_evt(uint16_t conn_handle) -{ - bool sc_pending_state = true; - bool sc_sent_state = false; - ret_code_t err_code = gscm_service_changed_ind_send(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - { - pm_evt_t event = - { - .evt_id = PM_EVT_SERVICE_CHANGED_IND_SENT, - .conn_handle = conn_handle, - }; - - sc_sent_state = true; - - evt_send(&event); - break; - } - - case NRF_ERROR_BUSY: - // Do nothing. - break; - - case NRF_ERROR_INVALID_STATE: - // CCCDs not enabled. Drop indication. - // Fallthrough. - - case NRF_ERROR_NOT_SUPPORTED: - // Service changed not supported. Drop indication. - sc_pending_state = false; - gscm_db_change_notification_done(im_peer_id_get_by_conn_handle(conn_handle)); - break; - - case BLE_ERROR_GATTS_SYS_ATTR_MISSING: - local_db_apply_in_evt(conn_handle); - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - // Do nothing. - break; - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, sc_pending_state); - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, sc_sent_state); -} - - -/**@brief Function for checking all flags for one id, and handling the ones that are set. - * - * @param[in] flag_id The flag id to check flags for. - */ -static void pending_flags_check(ble_conn_state_user_flag_id_t flag_id) -{ - // Quickly check if any flags are set. - if (sdk_mapped_flags_any_set(ble_conn_state_user_flag_collection(flag_id))) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - // Check each flag. - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - uint16_t conn_handle = conn_handle_list.flag_keys[i]; - if (ble_conn_state_user_flag_get(conn_handle, flag_id)) - { - // This flag is set. Handle depending on which flags we are checking. - if (flag_id == m_flag_local_db_apply_pending) - { - local_db_apply_in_evt(conn_handle); - } - else if (flag_id == m_flag_local_db_update_pending) - { - if (pm_mutex_lock(&m_db_update_in_progress_mutex, 0)) - { - if (local_db_update_in_evt(conn_handle)) - { - // Successfully started writing to flash. - return; - } - else - { - pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); - } - } - } - else if (flag_id == m_flag_service_changed_pending) - { - if (!ble_conn_state_user_flag_get(conn_handle, m_flag_service_changed_sent)) - { - service_changed_send_in_evt(conn_handle); - } - } - } - } - } -} - - -static __INLINE void apply_pending_flags_check(void) -{ - pending_flags_check(m_flag_local_db_apply_pending); -} - - -static __INLINE void update_pending_flags_check(void) -{ - pending_flags_check(m_flag_local_db_update_pending); -} - - -static __INLINE void service_changed_pending_flags_check(void) -{ - pending_flags_check(m_flag_service_changed_pending); -} - - -/**@brief Callback function for events from the ID Manager module. - * This function is registered in the ID Manager module. - * - * @param[in] p_event The event from the ID Manager module. - */ -void gcm_im_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_BONDED_PEER_CONNECTED: - local_db_apply_in_evt(p_event->conn_handle); - if (gscm_service_changed_ind_needed(p_event->conn_handle)) - { - ble_conn_state_user_flag_set(p_event->conn_handle, m_flag_service_changed_pending, true); - } - break; - default: - break; - } -} - - -/**@brief Callback function for events from the Peer Database module. - * This handler is extern in Peer Database. - * - * @param[in] p_event The event from the Security Dispatcher module. - */ -void gcm_pdb_evt_handler(pm_evt_t * p_event) -{ - if ( p_event->evt_id == PM_EVT_PEER_DATA_UPDATE_SUCCEEDED - && p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - switch (p_event->params.peer_data_update_succeeded.data_id) - { - case PM_PEER_DATA_ID_BONDING: - { - uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); - - if (conn_handle != BLE_CONN_HANDLE_INVALID) - { - local_db_update(conn_handle, true); - } - break; - } - - case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: - { - ret_code_t err_code; - pm_peer_data_flash_t peer_data; - - err_code = pdb_peer_data_ptr_get(p_event->peer_id, - PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - &peer_data); - - if (err_code == NRF_SUCCESS) - { - if (*peer_data.p_service_changed_pending) - { - uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); - if (conn_handle != BLE_CONN_HANDLE_INVALID) - { - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, true); - service_changed_pending_flags_check(); - } - } - } - break; - } - - case PM_PEER_DATA_ID_GATT_LOCAL: - pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); - // Expecting a call to update_pending_flags_check() immediately. - break; - - default: - /* No action */ - break; - } - } - - update_pending_flags_check(); -} - - -ret_code_t gcm_init() -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - m_flag_local_db_update_pending = ble_conn_state_user_flag_acquire(); - m_flag_local_db_apply_pending = ble_conn_state_user_flag_acquire(); - m_flag_service_changed_pending = ble_conn_state_user_flag_acquire(); - m_flag_service_changed_sent = ble_conn_state_user_flag_acquire(); - - if ((m_flag_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID)) - { - return NRF_ERROR_INTERNAL; - } - - pm_mutex_init(&m_db_update_in_progress_mutex, 1); - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -/**@brief Callback function for BLE events from the SoftDevice. - * - * @param[in] p_ble_evt The BLE event from the SoftDevice. - */ -void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - local_db_apply_in_evt(conn_handle); - break; - - case BLE_GATTS_EVT_SC_CONFIRM: - { - pm_evt_t event = - { - .evt_id = PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, - .peer_id = im_peer_id_get_by_conn_handle(conn_handle), - .conn_handle = conn_handle, - }; - - gscm_db_change_notification_done(event.peer_id); - - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, false); - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, false); - evt_send(&event); - break; - } - - case BLE_GATTS_EVT_WRITE: - if (cccd_written(&p_ble_evt->evt.gatts_evt.params.write)) - { - local_db_update(conn_handle, true); - update_pending_flags_check(); - } - break; - } - - apply_pending_flags_check(); - service_changed_pending_flags_check(); -} - - -ret_code_t gcm_local_db_cache_update(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - local_db_update(conn_handle, true); - update_pending_flags_check(); - - return NRF_SUCCESS; -} - - -void gcm_local_database_has_changed(void) -{ - gscm_local_database_has_changed(); - - sdk_mapped_flags_key_list_t conn_handles = ble_conn_state_conn_handles(); - - for (uint16_t i = 0; i < conn_handles.len; i++) - { - if (im_peer_id_get_by_conn_handle(conn_handles.flag_keys[i]) == PM_PEER_ID_INVALID) - { - ble_conn_state_user_flag_set(conn_handles.flag_keys[i], m_flag_service_changed_pending, true); - } - } - - service_changed_pending_flags_check(); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h deleted file mode 100644 index 5ea1bcde1c..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef GATT_CACHE_MANAGER_H__ -#define GATT_CACHE_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** - * @cond NO_DOXYGEN - * @defgroup gatt_cache_manager GATT Cache Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT - * attributes. - */ - - -/**@brief Function for initializing the GATT Cache Manager module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t gcm_init(void); - - -/**@brief Function for dispatching SoftDevice events to the GATT Cache Manager module. - * - * @param[in] p_ble_evt The SoftDevice event. - */ -void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt); - - -/**@brief Function for triggering local GATT database data to be stored persistently. - * - * @details Values are retrieved from SoftDevice and written to persistent storage. - * - * @note This operation happens asynchronously, so any errors are reported as events. - * - * @note This function is only needed when you want to override the regular functionality of the - * module, e.g. to immediately store to flash instead of waiting for the native logic to - * perform the update. - * - * @param[in] conn_handle Connection handle to perform update on. - * - * @retval NRF_SUCCESS Store operation started. - */ -ret_code_t gcm_local_db_cache_update(uint16_t conn_handle); - - -/**@brief Function for manually informing that the local database has changed. - * - * @details This causes a service changed notification to be sent to all bonded peers that - * subscribe to it. - */ -void gcm_local_database_has_changed(void); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* GATT_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c deleted file mode 100644 index b2d2aa6f52..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c +++ /dev/null @@ -1,340 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "gatts_cache_manager.h" - -#include -#include "ble_gap.h" -#include "ble_err.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_database.h" -#include "id_manager.h" - - -// Syntactic sugar, two spoons. -#define SYS_ATTR_SYS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS) -#define SYS_ATTR_USR (BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS) -#define SYS_ATTR_BOTH (SYS_ATTR_SYS | SYS_ATTR_USR) - -static bool m_module_initialized; -static pm_peer_id_t m_current_sc_store_peer_id; - - -/**@brief Function for resetting the module variable(s) of the GSCM module. - */ -static void internal_state_reset() -{ - m_module_initialized = false; - m_current_sc_store_peer_id = PM_PEER_ID_INVALID; -} - - -//lint -save -e550 -/**@brief Function for storing service_changed_pending = true to flash for all peers, in sequence. - * - * This function aborts if it gets @ref NRF_ERROR_BUSY when trying to store. A subsequent call will - * continue where the last call was aborted. - */ -static void service_changed_pending_set(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret_code_t err_code; - // Use a uint32_t to enforce 4-byte alignment. - static const uint32_t service_changed_pending = true; - - //lint -save -e65 -e64 - pm_peer_data_const_t peer_data = - { - .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - .length_words = PM_SC_STATE_N_WORDS(), - .p_service_changed_pending = (bool*)&service_changed_pending, - }; - //lint -restore - - err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); - while ((m_current_sc_store_peer_id != PM_PEER_ID_INVALID) && (err_code != NRF_ERROR_BUSY)) - { - m_current_sc_store_peer_id = pdb_next_peer_id_get(m_current_sc_store_peer_id); - err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); - } -} -//lint -restore - - - -/**@brief Event handler for events from the Peer Database module. - * This function is extern in Peer Database. - * - * @param[in] p_event The event that has happend with peer id and flags. - */ -void gscm_pdb_evt_handler(pm_evt_t * p_event) -{ - if (m_current_sc_store_peer_id != PM_PEER_ID_INVALID) - { - service_changed_pending_set(); - } -} - - -ret_code_t gscm_init() -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t gscm_local_db_cache_update(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - ret_code_t err_code; - - if (peer_id == PM_PEER_ID_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - else - { - pm_peer_data_t peer_data; - uint16_t n_bufs = 1; - bool retry_with_bigger_buffer = false; - - do - { - retry_with_bigger_buffer = false; - - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, n_bufs++, &peer_data); - if (err_code == NRF_SUCCESS) - { - pm_peer_data_local_gatt_db_t * p_local_gatt_db = peer_data.p_local_gatt_db; - - p_local_gatt_db->flags = SYS_ATTR_BOTH; - - err_code = sd_ble_gatts_sys_attr_get(conn_handle, &p_local_gatt_db->data[0], &p_local_gatt_db->len, p_local_gatt_db->flags); - - if (err_code == NRF_SUCCESS) - { - err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, peer_id); - } - else - { - if (err_code == NRF_ERROR_DATA_SIZE) - { - // The sys attributes are bigger than the requested write buffer. - retry_with_bigger_buffer = true; - } - else if (err_code == NRF_ERROR_NOT_FOUND) - { - // There are no sys attributes in the GATT db, so nothing needs to be stored. - err_code = NRF_SUCCESS; - } - - ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL); - if (err_code_release != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - } - } - else if (err_code == NRF_ERROR_INVALID_PARAM) - { - // The sys attributes are bigger than the entire write buffer. - err_code = NRF_ERROR_DATA_SIZE; - } - } while (retry_with_bigger_buffer); - } - - return err_code; -} - - -ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - ret_code_t err_code; - pm_peer_data_flash_t peer_data; - uint8_t const * p_sys_attr_data = NULL; - uint16_t sys_attr_len = 0; - uint32_t sys_attr_flags = (SYS_ATTR_BOTH); - bool all_attributes_applied = true; - - if (peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data); - if (err_code == NRF_SUCCESS) - { - pm_peer_data_local_gatt_db_t const * p_local_gatt_db; - - p_local_gatt_db = peer_data.p_local_gatt_db; - p_sys_attr_data = p_local_gatt_db->data; - sys_attr_len = p_local_gatt_db->len; - sys_attr_flags = p_local_gatt_db->flags; - } - } - - do - { - err_code = sd_ble_gatts_sys_attr_set(conn_handle, p_sys_attr_data, sys_attr_len, sys_attr_flags); - - if (err_code == NRF_ERROR_NO_MEM) - { - err_code = NRF_ERROR_BUSY; - } - else if (err_code == NRF_ERROR_INVALID_STATE) - { - err_code = NRF_SUCCESS; - } - else if (err_code == NRF_ERROR_INVALID_DATA) - { - all_attributes_applied = false; - - if (sys_attr_flags & SYS_ATTR_USR) - { - // Try setting only system attributes. - sys_attr_flags = SYS_ATTR_SYS; - } - else if (p_sys_attr_data || sys_attr_len) - { - // Try reporting that none exist. - p_sys_attr_data = NULL; - sys_attr_len = 0; - sys_attr_flags = SYS_ATTR_BOTH; - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - } - } while (err_code == NRF_ERROR_INVALID_DATA); - - if (!all_attributes_applied) - { - err_code = NRF_ERROR_INVALID_DATA; - } - - return err_code; -} - -void gscm_local_database_has_changed(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - m_current_sc_store_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - service_changed_pending_set(); -} - - -bool gscm_service_changed_ind_needed(uint16_t conn_handle) -{ - ret_code_t err_code; - bool service_changed_state; - pm_peer_data_flash_t peer_data; - - peer_data.p_service_changed_pending = &service_changed_state; - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data); - - if (err_code != NRF_SUCCESS) - { - return false; - } - - return *peer_data.p_service_changed_pending; -} - - -ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle) -{ - static uint16_t start_handle; - const uint16_t end_handle = 0xFFFF; - ret_code_t err_code; - - err_code = sd_ble_gatts_initial_user_handle_get(&start_handle); - - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - do - { - err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle); - if (err_code == BLE_ERROR_INVALID_ATTR_HANDLE) - { - start_handle += 1; - } - } while (err_code == BLE_ERROR_INVALID_ATTR_HANDLE); - - return err_code; -} - - -void gscm_db_change_notification_done(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - // Use a uint32_t to enforce 4-byte alignment. - static const uint32_t service_changed_pending = false; - - //lint -save -e65 -e64 - pm_peer_data_const_t peer_data = - { - .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - .length_words = PM_SC_STATE_N_WORDS(), - .p_service_changed_pending = (bool*)&service_changed_pending, - }; - //lint -restore - - // Don't need to check return code, because all error conditions can be ignored. - //lint -save -e550 - (void) pdb_raw_store(peer_id, &peer_data, NULL); - //lint -restore -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h deleted file mode 100644 index a463344d28..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef GATTS_CACHE_MANAGER_H__ -#define GATTS_CACHE_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** - * @cond NO_DOXYGEN - * @defgroup gatts_cache_manager GATT Server Cache Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT - * attributes pertaining to the GATT server role of the local device. - */ - - -/**@brief Function for initializing the GATT Server Cache Manager module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t gscm_init(void); - - -/**@brief Function for triggering local GATT database data to be stored persistently. Values are - * retrieved from the SoftDevice and written to persistent storage. - * - * @param[in] conn_handle Connection handle to perform update on. - * - * @retval NRF_SUCCESS Store operation started. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a - * bonded peer. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. - * @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with - * this GATT database. - * @retval NRF_ERROR_STORAGE_FULL No room in persistent_storage. Free up space; the - * operation will be automatically reattempted after the - * next FDS garbage collection procedure. - */ -ret_code_t gscm_local_db_cache_update(uint16_t conn_handle); - - -/**@brief Function for applying stored local GATT database data to the SoftDevice. Values are - * retrieved from persistent storage and given to the SoftDevice. - * - * @param[in] conn_handle Connection handle to apply values to. - * - * @retval NRF_SUCCESS Store operation started. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a - * bonded peer. - * @retval NRF_ERROR_INVALID_DATA The stored data was rejected by the SoftDevice, which - * probably means that the local database has changed. The - * system part of the sys_attributes was attempted applied, - * so service changed indications can be sent to subscribers. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. - * @return An unexpected return value from an internal function call. - */ -ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle); - - -/**@brief Function for storing the fact that the local database has changed, for all currently - * bonded peers. - * - * @note This will cause a later call to @ref gscm_service_changed_ind_needed to return true for - * a connection with a currently bonded peer. - */ -void gscm_local_database_has_changed(void); - - -/**@brief Function for checking if a service changed indication should be sent. - * - * @param[in] conn_handle The connection to check. - * - * @return true if a service changed indication should be sent, false if not. - */ -bool gscm_service_changed_ind_needed(uint16_t conn_handle); - - -/**@brief Function for sending a service changed indication to a connected peer. - * - * @param[in] conn_handle The connection to send the indication on. - * - * @retval NRF_SUCCESS Indication sent or not needed. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection. - * @retval NRF_ERROR_BUSY Unable to send indication at this time. Reattempt later. - * @retval BLE_ERROR_GATTS_SYS_ATTR_MISSING Information missing. Apply local cache, then reattempt. - * @retval NRF_ERROR_INVALID_PARAM From @ref sd_ble_gatts_service_changed. Unexpected. - * @retval NRF_ERROR_NOT_SUPPORTED Service changed characteristic is not present. - * @retval NRF_ERROR_INVALID_STATE Service changed cannot be indicated to this peer - * because the peer has not subscribed to it. - * @retval NRF_ERROR_INTERNAL An unexpected error happened. - */ -ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle); - - -/**@brief Function for specifying that a peer has been made aware of the latest local database - * change. - * - * @note After calling this, a later call to @ref gscm_service_changed_ind_needed will to return - * false for this peer unless @ref gscm_local_database_has_changed is called again. - * - * @param[in] peer_id The connection to send the indication on. - */ -void gscm_db_change_notification_done(pm_peer_id_t peer_id); - -/** @} - * @endcond -*/ - - -#ifdef __cplusplus -} -#endif - -#endif /* GATTS_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c deleted file mode 100644 index dd1b5c0bd9..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c +++ /dev/null @@ -1,1065 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "id_manager.h" - -#include -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_database.h" -#include "peer_data_storage.h" -#include "nrf_soc.h" - - -#define IM_MAX_CONN_HANDLES (20) -#define IM_NO_INVALID_CONN_HANDLES (0xFF) -#define IM_ADDR_CLEARTEXT_LENGTH (3) -#define IM_ADDR_CIPHERTEXT_LENGTH (3) - -// The number of registered event handlers. -#define IM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Identity Manager event handlers in Peer Manager and GATT Cache Manager. -extern void pm_im_evt_handler(pm_evt_t * p_event); -extern void gcm_im_evt_handler(pm_evt_t * p_event); - -// Identity Manager events' handlers. -// The number of elements in this array is IM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_im_evt_handler, - gcm_im_evt_handler -}; - - -typedef struct -{ - pm_peer_id_t peer_id; - uint16_t conn_handle; - ble_gap_addr_t peer_address; -} im_connection_t; - -static bool m_module_initialized; -static im_connection_t m_connections[IM_MAX_CONN_HANDLES]; -static ble_conn_state_user_flag_id_t m_conn_state_user_flag_id; - -static uint8_t m_wlisted_peer_cnt; -static pm_peer_id_t m_wlisted_peers[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - -#if (NRF_SD_BLE_API_VERSION <= 2) - static ble_gap_addr_t m_current_id_addr; -#endif - - -static void internal_state_reset() -{ - m_conn_state_user_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; - - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - m_connections[i].conn_handle = BLE_CONN_HANDLE_INVALID; - } -} - - -/**@brief Function for sending an event to all registered event handlers. - * - * @param[in] p_event The event to distribute. - */ -static void evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < IM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - -/**@brief Function finding a free position in m_connections. - * - * @detail All connection handles in the m_connections array are checked against the connection - * state module. The index of the first one that is not a connection handle for a current - * connection is returned. This position in the array can safely be used for a new connection. - * - * @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free - position exists. - */ -uint8_t get_free_connection() -{ - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - // Query the connection state module to check if the - // connection handle does not belong to a valid connection. - if (!ble_conn_state_user_flag_get(m_connections[i].conn_handle, m_conn_state_user_flag_id)) - { - return i; - } - } - // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. - return IM_NO_INVALID_CONN_HANDLES; -} - - -/**@brief Function finding a particular connection handle m_connections. - * - * @param[in] conn_handle The handle to find. - * - * @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the - * handle was not found. - */ -uint8_t get_connection_by_conn_handle(uint16_t conn_handle) -{ - if (ble_conn_state_user_flag_get(conn_handle, m_conn_state_user_flag_id)) - { - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - if (m_connections[i].conn_handle == conn_handle) - { - return i; - } - } - } - // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. - return IM_NO_INVALID_CONN_HANDLES; -} - - -/**@brief Function for registering a new connection instance. - * - * @param[in] conn_handle The handle of the new connection. - * @param[in] p_ble_addr The address used to connect. - * - * @return Either the index of the new connection in the array or IM_NO_INVALID_CONN_HANDLES if no - * free position exists. - */ -uint8_t new_connection(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) -{ - uint8_t conn_index = IM_NO_INVALID_CONN_HANDLES; - - if ((p_ble_addr != NULL) && (conn_handle != BLE_CONN_HANDLE_INVALID)) - { - ble_conn_state_user_flag_set(conn_handle, m_conn_state_user_flag_id, true); - - conn_index = get_connection_by_conn_handle(conn_handle); - if (conn_index == IM_NO_INVALID_CONN_HANDLES) - { - conn_index = get_free_connection(); - } - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - m_connections[conn_index].conn_handle = conn_handle; - m_connections[conn_index].peer_id = PM_PEER_ID_INVALID; - m_connections[conn_index].peer_address = *p_ble_addr; - } - } - return conn_index; -} - - -/**@brief Function checking the validity of an IRK - * - * @detail An all-zero IRK is not valid. This function will check if a given IRK is valid. - * - * @param[in] p_irk The IRK for which the validity is going to be checked. - * - * @retval true The IRK is valid. - * @retval false The IRK is invalid. - */ -bool is_valid_irk(ble_gap_irk_t const * p_irk) -{ - NRF_PM_DEBUG_CHECK(p_irk != NULL); - - for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++) - { - if (p_irk->irk[i] != 0) - { - return true; - } - } - return false; -} - - -/**@brief Function for comparing two addresses to determine if they are identical - * - * @note The address type need to be identical, as well as every bit in the address itself. - * - * @param[in] p_addr1 The first address to be compared. - * @param[in] p_addr2 The second address to be compared. - * - * @retval true The addresses are identical. - * @retval false The addresses are not identical. - */ -bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2) -{ - // @note emdi: use NRF_PM_DEBUG_CHECK ? - if ((p_addr1 == NULL) || (p_addr2 == NULL)) - { - return false; - } - - // Check that the addr type is identical, return false if it is not - if (p_addr1->addr_type != p_addr2->addr_type) - { - return false; - } - - // Check if the addr bytes are is identical - return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0); -} - - -void im_ble_evt_handler(ble_evt_t const * ble_evt) -{ - ble_gap_evt_t gap_evt; - pm_peer_id_t bonded_matching_peer_id; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) - { - // Nothing to do. - return; - } - - gap_evt = ble_evt->evt.gap_evt; - bonded_matching_peer_id = PM_PEER_ID_INVALID; - - if ( gap_evt.params.connected.peer_addr.addr_type - != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - /* Search the database for bonding data matching the one that triggered the event. - * Public and static addresses can be matched on address alone, while resolvable - * random addresses can be resolved agains known IRKs. Non-resolvable random addresses - * are never matching because they are not longterm form of identification. - */ - - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - pds_peer_data_iterate_prepare(); - - switch (gap_evt.params.connected.peer_addr.addr_type) - { - case BLE_GAP_ADDR_TYPE_PUBLIC: - case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: - { - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (addr_compare(&gap_evt.params.connected.peer_addr, - &peer_data.p_bonding_data->peer_ble_id.id_addr_info)) - { - bonded_matching_peer_id = peer_id; - break; - } - } - } - break; - - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: - { - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_address_resolve(&gap_evt.params.connected.peer_addr, - &peer_data.p_bonding_data->peer_ble_id.id_info)) - { - bonded_matching_peer_id = peer_id; - break; - } - } - } - break; - - default: - NRF_PM_DEBUG_CHECK(false); - break; - } - } - - uint8_t new_index = new_connection(gap_evt.conn_handle, - &gap_evt.params.connected.peer_addr); - UNUSED_VARIABLE(new_index); - - if (bonded_matching_peer_id != PM_PEER_ID_INVALID) - { - im_new_peer_id(gap_evt.conn_handle, bonded_matching_peer_id); - - // Send a bonded peer event - pm_evt_t im_evt; - im_evt.conn_handle = gap_evt.conn_handle; - im_evt.peer_id = bonded_matching_peer_id; - im_evt.evt_id = PM_EVT_BONDED_PEER_CONNECTED; - evt_send(&im_evt); - } -} - - -/**@brief Function to compare two sets of bonding data to check if they belong to the same device. - * @note Invalid irks will never match even though they are identical. - * - * @param[in] p_bonding_data1 First bonding data for comparison - * @param[in] p_bonding_data2 Second bonding data for comparison - * - * @return True if the input matches, false if it does not. - */ -bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, - pm_peer_data_bonding_t const * p_bonding_data2) -{ - NRF_PM_DEBUG_CHECK(p_bonding_data1 != NULL); - NRF_PM_DEBUG_CHECK(p_bonding_data2 != NULL); - - ble_gap_addr_t const * p_addr1 = &p_bonding_data1->peer_ble_id.id_addr_info; - ble_gap_addr_t const * p_addr2 = &p_bonding_data2->peer_ble_id.id_addr_info; - - bool duplicate_irk = ((memcmp(p_bonding_data1->peer_ble_id.id_info.irk, - p_bonding_data2->peer_ble_id.id_info.irk, - BLE_GAP_SEC_KEY_LEN) == 0) - && is_valid_irk(&p_bonding_data1->peer_ble_id.id_info) - && is_valid_irk(&p_bonding_data2->peer_ble_id.id_info)); - - bool duplicate_addr = addr_compare(p_addr1, p_addr2); - - bool id_addrs = ((p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - && (p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)); - - return (duplicate_addr && id_addrs) || (duplicate_irk && !id_addrs); -} - - -pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, - pm_peer_id_t peer_id_skip) -{ - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data_duplicate; - - NRF_PM_DEBUG_CHECK(p_bonding_data != NULL); - - pds_peer_data_iterate_prepare(); - - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data_duplicate)) - { - if ( (peer_id != peer_id_skip) - && im_is_duplicate_bonding_data(p_bonding_data, - peer_data_duplicate.p_bonding_data)) - { - return peer_id; - } - } - return PM_PEER_ID_INVALID; -} - - -ret_code_t im_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - m_conn_state_user_flag_id = ble_conn_state_user_flag_acquire(); - if (m_conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - #if (NRF_SD_BLE_API_VERSION <= 2) - ret_code_t ret_code = sd_ble_gap_address_get(&m_current_id_addr); - if (ret_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - #endif - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle) -{ - uint8_t conn_index; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - conn_index = get_connection_by_conn_handle(conn_handle); - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - return m_connections[conn_index].peer_id; - } - - return PM_PEER_ID_INVALID; -} - - -ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) -{ - uint8_t conn_index; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_ble_addr != NULL); - - conn_index = get_connection_by_conn_handle(conn_handle); - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - *p_ble_addr = m_connections[conn_index].peer_address; - return NRF_SUCCESS; - } - - return NRF_ERROR_NOT_FOUND; -} - - -bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, - ble_gap_master_id_t const * p_master_id2) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_master_id1 != NULL); - NRF_PM_DEBUG_CHECK(p_master_id2 != NULL); - - if (!im_master_id_is_valid(p_master_id1)) - { - return false; - } - - if (p_master_id1->ediv != p_master_id2->ediv) - { - return false; - } - - return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0); -} - - -pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id) -{ - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_master_id != NULL); - - pds_peer_data_iterate_prepare(); - - // For each stored peer, check if the master_id matches p_master_id - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->own_ltk.master_id) || - im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->peer_ltk.master_id)) - { - // If a matching master ID is found then return the peer ID. - return peer_id; - } - } - - // If no matching master ID is found return PM_PEER_ID_INVALID. - return PM_PEER_ID_INVALID; -} - - -uint16_t im_conn_handle_get(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - if (peer_id == m_connections[i].peer_id) - { - return m_connections[i].conn_handle; - } - } - return BLE_CONN_HANDLE_INVALID; -} - - -bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (p_master_id->ediv != 0) - { - return true; - } - - for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++) - { - if (p_master_id->rand[i] != 0) - { - return true; - } - } - return false; -} - - -/**@brief Function to set the peer ID associated with a connection handle. - * - * @param[in] conn_handle The connection handle. - * @param[in] peer_id The peer ID to associate with @c conn_handle. - */ -static void peer_id_set(uint16_t conn_handle, pm_peer_id_t peer_id) -{ - uint8_t conn_index = get_connection_by_conn_handle(conn_handle); - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - m_connections[conn_index].peer_id = peer_id; - } -} - - -void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - peer_id_set(conn_handle, peer_id); -} - - -ret_code_t im_peer_free(pm_peer_id_t peer_id) -{ - uint16_t conn_handle; - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - conn_handle = im_conn_handle_get(peer_id); - ret = pdb_peer_free(peer_id); - - if ((conn_handle != BLE_CONN_HANDLE_INVALID) && (ret == NRF_SUCCESS)) - { - peer_id_set(conn_handle, PM_PEER_ID_INVALID); - } - return ret; -} - - -/**@brief Given a list of peers, loads their GAP address and IRK into the provided buffers. - */ -static ret_code_t peers_id_keys_get(pm_peer_id_t const * p_peers, - uint32_t peer_cnt, - ble_gap_addr_t * p_gap_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_gap_irks, - uint32_t * p_irk_cnt) -{ - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - pm_peer_data_t peer_data; - - uint32_t const buf_size = sizeof(bond_data); - - bool copy_addrs = false; - bool copy_irks = false; - - NRF_PM_DEBUG_CHECK(p_peers != NULL); - - // One of these two has to be provided. - NRF_PM_DEBUG_CHECK((p_gap_addrs != NULL) || (p_gap_irks != NULL)); - - if ((p_gap_addrs != NULL) && (p_addr_cnt != NULL)) - { - NRF_PM_DEBUG_CHECK((*p_addr_cnt) >= peer_cnt); - - copy_addrs = true; - *p_addr_cnt = 0; - } - - if ((p_gap_irks != NULL) && (p_irk_cnt != NULL)) - { - NRF_PM_DEBUG_CHECK((*p_irk_cnt) >= peer_cnt); - - copy_irks = true; - *p_irk_cnt = 0; - } - - memset(&peer_data, 0x00, sizeof(peer_data)); - peer_data.p_bonding_data = &bond_data; - - // Read through flash memory and look for peers ID keys. - - for (uint32_t i = 0; i < peer_cnt; i++) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, - &peer_data, &buf_size); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data coulnd't be found in flash or peer ID is not valid. - return NRF_ERROR_NOT_FOUND; - } - - uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; - - if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && - (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) - { - // The address shared by the peer during bonding can't be used for whitelisting. - return BLE_ERROR_GAP_INVALID_BLE_ADDR; - } - - // Copy the GAP address. - if (copy_addrs) - { - memcpy(&p_gap_addrs[i], &bond_data.peer_ble_id.id_addr_info, sizeof(ble_gap_addr_t)); - (*p_addr_cnt)++; - } - - // Copy the IRK. - if (copy_irks) - { - memcpy(&p_gap_irks[i], bond_data.peer_ble_id.id_info.irk, BLE_GAP_SEC_KEY_LEN); - (*p_irk_cnt)++; - } - } - - return NRF_SUCCESS; -} - - -ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - #if (NRF_SD_BLE_API_VERSION >= 3) - - ret_code_t ret; - pm_peer_data_t peer_data; - pm_peer_data_bonding_t bond_data; - - ble_gap_id_key_t keys[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; - ble_gap_id_key_t const * key_ptrs[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; - - if ((p_peers == NULL) || (peer_cnt == 0)) - { - // Clear the device identities list. - return sd_ble_gap_device_identities_set(NULL, NULL, 0); - } - - peer_data.p_bonding_data = &bond_data; - uint32_t const buf_size = sizeof(bond_data); - - memset(keys, 0x00, sizeof(keys)); - for (uint32_t i = 0; i < BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; i++) - { - key_ptrs[i] = &keys[i]; - } - - for (uint32_t i = 0; i < peer_cnt; i++) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, - &peer_data, &buf_size); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data coulnd't be found in flash or peer ID is not valid. - return NRF_ERROR_NOT_FOUND; - } - - uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; - - if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && - (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) - { - // The address shared by the peer during bonding can't be whitelisted. - return BLE_ERROR_GAP_INVALID_BLE_ADDR; - } - - // Copy data to the buffer. - memcpy(&keys[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - } - - return sd_ble_gap_device_identities_set(key_ptrs, NULL, peer_cnt); - - #else - - return NRF_ERROR_NOT_SUPPORTED; - - #endif -} - - -#if (NRF_SD_BLE_API_VERSION <= 2) - -static ret_code_t address_set_v2(uint8_t cycle_mode, ble_gap_addr_t * p_addr) -{ - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - ret_code_t ret = sd_ble_gap_address_set(cycle_mode, p_addr); - - switch (ret) - { - case NRF_SUCCESS: - case NRF_ERROR_BUSY: - case NRF_ERROR_INVALID_STATE: - case NRF_ERROR_INVALID_PARAM: // If cycle_mode is not AUTO or NONE. - case BLE_ERROR_GAP_INVALID_BLE_ADDR: // If the GAP address is not valid. - return ret; - - default: - return NRF_ERROR_INTERNAL; - } -} - -#endif - - -ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ret_code_t ret; - ble_gap_addr_t current_addr; - - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - (void) sd_ble_gap_address_get(¤t_addr); - - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, (ble_gap_addr_t *)p_addr); - if (ret != NRF_SUCCESS) - { - return ret; - } - - if ( current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE - || current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - // If currently using privacy, it must be re-enabled. - // We force AUTO when privacy is enabled. - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, ¤t_addr); - if (ret != NRF_SUCCESS) - { - return ret; - } - } - - memcpy(&m_current_id_addr, p_addr, sizeof(ble_gap_addr_t)); - - return NRF_SUCCESS; - - #else - - return sd_ble_gap_addr_set(p_addr); - - #endif -} - - -ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr) -{ - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - #if (NRF_SD_BLE_API_VERSION <= 2) - memcpy(p_addr, &m_current_id_addr, sizeof(ble_gap_addr_t)); - return NRF_SUCCESS; - #else - return sd_ble_gap_addr_get(p_addr); - #endif -} - - -ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ret_code_t ret; - ble_gap_addr_t privacy_addr; - ble_gap_irk_t current_irk; - ble_opt_t privacy_options; - ble_opt_t current_privacy_options; - - NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); - - privacy_addr.addr_type = p_privacy_params->private_addr_type; - privacy_options.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; - privacy_options.gap_opt.privacy.interval_s = p_privacy_params->private_addr_cycle_s; - current_privacy_options.gap_opt.privacy.p_irk = ¤t_irk; - - // Can not fail. - (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); - (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_options); - - if (p_privacy_params->privacy_mode == BLE_GAP_PRIVACY_MODE_OFF) - { - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, &m_current_id_addr); - } - else - { - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &privacy_addr); - } - - if (ret != NRF_SUCCESS) - { - // Restore previous settings. - (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); - } - - // NRF_ERROR_BUSY, - // NRF_ERROR_INVALID_STATE, - // NRF_ERROR_INVALID_PARAM, if address type is not valid. - return ret; - - #else - - return sd_ble_gap_privacy_set(p_privacy_params); - - #endif -} - - -ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ble_gap_addr_t cur_addr; - ble_opt_t cur_privacy_opt; - - NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); - NRF_PM_DEBUG_CHECK(p_privacy_params->p_device_irk != NULL); - - cur_privacy_opt.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; - - // Can not fail. - (void) sd_ble_gap_address_get(&cur_addr); - - if ( cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE - || cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - p_privacy_params->private_addr_type = cur_addr.addr_type; - } - else - { - p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - } - - // Can not fail. - (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &cur_privacy_opt); - - p_privacy_params->private_addr_cycle_s = cur_privacy_opt.gap_opt.privacy.interval_s; - - return NRF_SUCCESS; - - #else - - return sd_ble_gap_privacy_get(p_privacy_params); - - #endif -} - - -/* Create a whitelist for the user using the cached list of peers. - * This whitelist is meant to be provided by the application to the Advertising module. - */ -ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt) -{ - // One of the two buffers has to be provided. - NRF_PM_DEBUG_CHECK((p_addrs != NULL) || (p_irks != NULL)); - NRF_PM_DEBUG_CHECK((p_addr_cnt != NULL) || (p_irk_cnt != NULL)); - - if (((p_addr_cnt != NULL) && (m_wlisted_peer_cnt > *p_addr_cnt)) || - ((p_irk_cnt != NULL) && (m_wlisted_peer_cnt > *p_irk_cnt))) - { - // The size of the cached list of peers is larger than the provided buffers. - return NRF_ERROR_NO_MEM; - } - - // NRF_SUCCESS or - // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. - // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. - return peers_id_keys_get(m_wlisted_peers, m_wlisted_peer_cnt, - p_addrs, p_addr_cnt, - p_irks, p_irk_cnt); -} - - -/* Copies the peers to whitelist into a local cache. - * The cached list will be used by im_whitelist_get() to retrieve the active whitelist. - * For SoftDevices 3x, also loads the peers' GAP addresses and whitelists them using - * sd_ble_gap_whitelist_set(). - */ -ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - // Clear the cache of whitelisted peers. - memset(m_wlisted_peers, 0x00, sizeof(m_wlisted_peers)); - - if ((p_peers == NULL) || (peer_cnt == 0)) - { - // Clear the current whitelist. - m_wlisted_peer_cnt = 0; - #if (NRF_SD_BLE_API_VERSION >= 3) - // NRF_SUCCESS, or - // BLE_GAP_ERROR_WHITELIST_IN_USE - return sd_ble_gap_whitelist_set(NULL, 0); - #else - // The cached list of whitelisted peers is already cleared; nothing to do. - return NRF_SUCCESS; - #endif - } - - // @todo emdi: should not ever cache more than BLE_GAP_WHITELIST_ADDR_MAX_COUNT... - - // Copy the new whitelisted peers. - m_wlisted_peer_cnt = peer_cnt; - memcpy(m_wlisted_peers, p_peers, sizeof(pm_peer_id_t) * peer_cnt); - - #if (NRF_SD_BLE_API_VERSION >= 3) - - ret_code_t ret; - uint32_t wlist_addr_cnt = 0; - - ble_gap_addr_t const * addr_ptrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_addr_t addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - - memset(addrs, 0x00, sizeof(addrs)); - - // Fetch GAP addresses for these peers, but don't fetch IRKs. - ret = peers_id_keys_get(p_peers, peer_cnt, addrs, &wlist_addr_cnt, NULL, NULL); - - if (ret != NRF_SUCCESS) - { - // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. - // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. - return ret; - } - - for (uint32_t i = 0; i < BLE_GAP_WHITELIST_ADDR_MAX_COUNT; i++) - { - addr_ptrs[i] = &addrs[i]; - } - - // NRF_ERROR_DATA_SIZE, if peer_cnt > BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - // BLE_ERROR_GAP_WHITELIST_IN_USE, if a whitelist is in use. - return sd_ble_gap_whitelist_set(addr_ptrs, peer_cnt); - - #else - - return NRF_SUCCESS; - - #endif -} - - -/**@brief Function for calculating the ah() hash function described in Bluetooth core specification - * 4.2 section 3.H.2.2.2. - * - * @detail BLE uses a hash function to calculate the first half of a resolvable address - * from the second half of the address and an irk. This function will use the ECB - * periferal to hash these data acording to the Bluetooth core specification. - * - * @note The ECB expect little endian input and output. - * This function expect big endian and will reverse the data as necessary. - * - * @param[in] p_k The key used in the hash function. - * For address resolution this is should be the irk. - * The array must have a length of 16. - * @param[in] p_r The rand used in the hash function. For generating a new address - * this would be a random number. For resolving a resolvable address - * this would be the last half of the address being resolved. - * The array must have a length of 3. - * @param[out] p_local_hash The result of the hash operation. For address resolution this - * will match the first half of the address being resolved if and only - * if the irk used in the hash function is the same one used to generate - * the address. - * The array must have a length of 16. - */ -void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash) -{ - nrf_ecb_hal_data_t ecb_hal_data; - - for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++) - { - ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i]; - } - - memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH); - - for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++) - { - ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i]; - } - - // Can only return NRF_SUCCESS. - (void) sd_ecb_block_encrypt(&ecb_hal_data); - - for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++) - { - p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i]; - } -} - - -bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH]; - uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH]; - uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH]; - - if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - { - return false; - } - - memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH); - memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH); - ah(p_irk->irk, prand, local_hash); - - return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h deleted file mode 100644 index 1350a4a853..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h +++ /dev/null @@ -1,327 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_ID_MANAGER_H__ -#define PEER_ID_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup id_manager ID Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for keeping track of peer identities - * (IRK and peer address). - */ - - -/**@brief Function for initializing the Identity manager. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an error occurred. - */ -ret_code_t im_init(void); - - -/**@brief Function for dispatching SoftDevice events to the ID Manager module. - * - * @param[in] p_ble_evt The SoftDevice event. - */ -void im_ble_evt_handler(ble_evt_t const * p_ble_evt); - - -/**@brief Function for getting the corresponding peer ID from a connection handle. - * - * @param[in] conn_handle The connection handle. - * - * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. - */ -pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle); - - -/**@brief Function for getting the corresponding peer ID from a master ID (EDIV and rand). - * - * @param[in] p_master_id The master ID. - * - * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. - */ -pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id); - - -/**@brief Function for getting the corresponding connection handle from a peer ID. - * - * @param[in] peer_id The peer ID. - * - * @return The corresponding connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be - * resolved. - */ -uint16_t im_conn_handle_get(pm_peer_id_t peer_id); - - -/**@brief Function for comparing two master ids - * @note Two invalid master IDs will not match. - * - * @param[in] p_master_id1 First master id for comparison - * @param[in] p_master_id2 Second master id for comparison - * - * @return True if the input matches, false if it does not. - */ -bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, - ble_gap_master_id_t const * p_master_id2); - - -/**@brief Function for getting the BLE address used by the peer when connecting. - * - * @param[in] conn_handle The connection handle. - * @param[out] p_ble_addr The BLE address used by the peer when the connection specified by - * conn_handle was established. - * - * @retval NRF_SUCCESS The address was found and copied. - * @retval BLE_ERROR_CONN_HANDLE_INVALID conn_handle does not refer to an active connection. - * @retval NRF_ERROR_NULL p_ble_addr was NULL. - */ -ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr); - - -/**@brief Function for checking if a master ID is valid or invalid - * - * @param[in] p_master_id The master ID. - * - * @retval true The master id is valid. - * @retval false The master id is invalid (i.e. all zeros). - */ -bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id); - - -/**@brief Function for checking if two pieces of bonding data correspond to the same peer. - * - * @param[in] p_bonding_data1 The first piece of bonding data to check. - * @param[in] p_bonding_data2 The second piece of bonding data to check. - * - * @retval true The bonding data correspond to the same peer. - * @retval false The bonding data do not correspond to the same peer. - */ -bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, - pm_peer_data_bonding_t const * p_bonding_data2); - - -/**@brief Function for finding if we are already bonded to a peer. - * - * @param[in] p_bonding_data The bonding data to check. - * @param[in] peer_id_skip Optional peer to ignore when searching for duplicates. - * - * @return An existing peer ID for the peer, or PM_PEER_ID_INVALID if none was found. - */ -pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, - pm_peer_id_t peer_id_skip); - - -/**@brief Function for reporting that a new peer ID has been allocated for a specified connection. - * - * @param[in] conn_handle The connection. - * @param[in] peer_id The new peer ID. - */ -void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id); - - -/**@brief Function for deleting all of a peer's data from flash and disassociating it from any - * connection handles it is associated with. - * - * @param[in] peer_id The peer to free. - * - * @return Any error code returned by @ref pdb_peer_free. - */ -ret_code_t im_peer_free(pm_peer_id_t peer_id); - - -/**@brief Function to set the local Bluetooth identity address. - * - * @details The local Bluetooth identity address is the address that identifies this device to other - * peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are - * running. - * - * @note This address will be distributed to the peer during bonding. - * If the address changes, the address stored in the peer device will not be valid and the - * ability to reconnect using the old address will be lost. - * - * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC - * upon being enabled. The address is a random number populated during the IC manufacturing - * process and remains unchanged for the lifetime of each IC. - * - * @param[in] p_addr Pointer to address structure. - * - * @retval NRF_SUCCESS Address successfully set. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the GAP address is invalid. - * @retval NRF_ERROR_BUSY Could not process at this time. Process SoftDevice events - * and retry. - * @retval NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, - * scanning, or while in a connection. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr); - - -/**@brief Function to get the local Bluetooth identity address. - * - * @note This will always return the identity address irrespective of the privacy settings, - * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. - * - * @param[out] p_addr Pointer to address structure to be filled in. - * - * @retval NRF_SUCCESS If the address was successfully retrieved. - */ -ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr); - - -/**@brief Function to set privacy settings. - * - * @details Privacy settings cannot be set while advertising, scanning, or while in a connection. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If privacy options were set successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the address type is not valid. - * @retval NRF_ERROR_BUSY If the request could not be processed at this time. - * Process SoftDevice events and retry. - * @retval NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while BLE roles using - * privacy are enabled. - */ -ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params); - - -/**@brief Function to retrieve the current privacy settings. - * - * @details The privacy settings returned include the current device irk as well. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS Successfully retrieved privacy settings. - * @retval NRF_ERROR_NULL @c p_privacy_params is NULL. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params); - - -/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). - * - * @details This function will use the ECB peripheral to resolve a resolvable address. - * This can be used to resolve the identity of a device distributing a random - * resolvable address based on any IRKs you have received earlier. If an address is - * resolved by an IRK, the device distributing the address must also know the IRK. - * - * @param[in] p_addr A random resolvable address. - * @param[in] p_irk An identity resolution key (IRK). - * - * @retval true The irk used matched the one used to create the address. - * @retval false The irk used did not match the one used to create the address, or an argument was - * NULL. - */ -bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - - -/**@brief Function for setting / clearing the whitelist. - * - * @param p_peers The peers to whitelist. Pass NULL to clear the whitelist. - * @param peer_cnt The number of peers to whitelist. Pass zero to clear the whitelist. - * - * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. - * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is in use. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used - * for whitelisting. - * @retval NRF_ERROR_NOT_FOUND If any peer or its data could not be found. - * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - */ -ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t const peer_cnt); - - -/**@brief Retrieves the current whitelist, set by a previous call to @ref im_whitelist_set. - * - * @param[out] A buffer where to copy the GAP addresses. - * @param[inout] In: the size of the @p p_addrs buffer. - * Out: the number of address copied into the buffer. - * @param[out] A buffer where to copy the IRKs. - * @param[inout] In: the size of the @p p_irks buffer. - * Out: the number of IRKs copied into the buffer. - * - * @retval NRF_SUCCESS If the whitelist was successfully retreived. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used for - * whitelisting. - * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers - * can not be found anymore. It might have been deleted in - * the meanwhile. - * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. - */ -ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt); - - -/**@brief Set the device identities list. - */ -ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_ID_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c deleted file mode 100644 index aa25bf29fa..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c +++ /dev/null @@ -1,685 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_data_storage.h" - -#include -#include -#include "sdk_errors.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_id.h" -#include "fds.h" - - -// Macro for verifying that the peer id is within a valid range. -#define VERIFY_PEER_ID_IN_RANGE(id) VERIFY_FALSE((id >= PM_PEER_ID_N_AVAILABLE_IDS), \ - NRF_ERROR_INVALID_PARAM) - -// Macro for verifying that the peer data id is withing a valid range. -#define VERIFY_PEER_DATA_ID_IN_RANGE(id) VERIFY_TRUE(peer_data_id_is_valid(id), \ - NRF_ERROR_INVALID_PARAM) - -// The number of registered event handlers. -#define PDS_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Peer Data Storage event handler in Peer Database. -extern void pdb_pds_evt_handler(pm_evt_t *); - -// Peer Data Storage events' handlers. -// The number of elements in this array is PDS_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pdb_pds_evt_handler, -}; - -static bool m_module_initialized = false; -static bool m_peer_delete_queued = false; -static bool m_peer_delete_ongoing = false; - -// A token used for Flash Data Storage searches. -static fds_find_token_t m_fds_ftok; - - -// Function for dispatching events to all registered event handlers. -static void pds_evt_send(pm_evt_t * p_event) -{ - p_event->conn_handle = BLE_CONN_HANDLE_INVALID; - - for (uint32_t i = 0; i < PDS_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -// Function to convert peer IDs to file IDs. -static uint16_t peer_id_to_file_id(pm_peer_id_t peer_id) -{ - return (uint16_t)(peer_id + PEER_ID_TO_FILE_ID); -} - - -// Function to convert peer data id to type id. -static pm_peer_id_t file_id_to_peer_id(uint16_t file_id) -{ - return (pm_peer_id_t)(file_id + FILE_ID_TO_PEER_ID); -} - - -// Function to convert peer data IDs to record keys. -static uint16_t peer_data_id_to_record_key(pm_peer_data_id_t peer_data_id) -{ - return (uint16_t)(peer_data_id + DATA_ID_TO_RECORD_KEY); -} - - -// Function to convert record keys to peer data IDs. -static pm_peer_data_id_t record_key_to_peer_data_id(uint16_t record_key) -{ - return (pm_peer_data_id_t)(record_key + RECORD_KEY_TO_DATA_ID); -} - - -// Function for checking whether a file ID is relevant for the Peer Manager. -static bool file_id_within_pm_range(uint16_t file_id) -{ - return ((PDS_FIRST_RESERVED_FILE_ID <= file_id) - && (file_id <= PDS_LAST_RESERVED_FILE_ID)); -} - - -// Function for checking whether a record key is relevant for the Peer Manager. -static bool record_key_within_pm_range(uint16_t record_key) -{ - return ((PDS_FIRST_RESERVED_RECORD_KEY <= record_key) - && (record_key <= PDS_LAST_RESERVED_RECORD_KEY)); -} - - -static bool peer_data_id_is_valid(pm_peer_data_id_t data_id) -{ - return ((data_id == PM_PEER_DATA_ID_BONDING) || - (data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING) || - (data_id == PM_PEER_DATA_ID_GATT_LOCAL) || - (data_id == PM_PEER_DATA_ID_GATT_REMOTE) || - (data_id == PM_PEER_DATA_ID_PEER_RANK) || - (data_id == PM_PEER_DATA_ID_APPLICATION)); -} - - -/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] peer_id The peer the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(pm_peer_id_t peer_id, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .peer_id = peer_id, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - pds_evt_send(&error_evt); -} - - -// Function for deleting all data beloning to a peer. -// These operations will be sent to FDS one at a time. -static void peer_data_delete() -{ - ret_code_t ret; - pm_peer_id_t peer_id; - uint16_t file_id; - fds_record_desc_t desc; - fds_find_token_t ftok; - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - peer_id = peer_id_get_next_deleted(PM_PEER_ID_INVALID); - - while ( (peer_id != PM_PEER_ID_INVALID) - && (fds_record_find_in_file(peer_id_to_file_id(peer_id), &desc, &ftok) - == FDS_ERR_NOT_FOUND)) - { - peer_id_free(peer_id); - peer_id = peer_id_get_next_deleted(peer_id); - } - - if (!m_peer_delete_ongoing && (peer_id != PM_PEER_ID_INVALID)) - { - m_peer_delete_ongoing = true; - - file_id = peer_id_to_file_id(peer_id); - ret = fds_file_delete(file_id); - - if (ret == FDS_ERR_NO_SPACE_IN_QUEUES) - { - m_peer_delete_queued = true; - } - else if (ret != NRF_SUCCESS) - { - m_peer_delete_ongoing = false; - - send_unexpected_error(peer_id, ret); - } - } -} - - -static ret_code_t peer_data_find(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - fds_record_desc_t * const p_desc) -{ - ret_code_t ret; - fds_find_token_t ftok; - - NRF_PM_DEBUG_CHECK(peer_id < PM_PEER_ID_N_AVAILABLE_IDS); - NRF_PM_DEBUG_CHECK(peer_data_id_is_valid(data_id)); - NRF_PM_DEBUG_CHECK(p_desc != NULL); - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - - uint16_t file_id = peer_id_to_file_id(peer_id); - uint16_t record_key = peer_data_id_to_record_key(data_id); - - ret = fds_record_find(file_id, record_key, p_desc, &ftok); - - if (ret != FDS_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - return NRF_SUCCESS; -} - - -static void peer_ids_load() -{ - fds_record_desc_t record_desc; - fds_flash_record_t record; - fds_find_token_t ftok; - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - - uint16_t const record_key = peer_data_id_to_record_key(PM_PEER_DATA_ID_BONDING); - - while (fds_record_find_by_key(record_key, &record_desc, &ftok) == FDS_SUCCESS) - { - pm_peer_id_t peer_id; - - // It is safe to ignore the return value since the descriptor was - // just obtained and also 'record' is different from NULL. - (void)fds_record_open(&record_desc, &record); - peer_id = file_id_to_peer_id(record.p_header->file_id); - (void)fds_record_close(&record_desc); - - (void)peer_id_allocate(peer_id); - } -} - - -static void fds_evt_handler(fds_evt_t const * const p_fds_evt) -{ - pm_evt_t pds_evt = - { - .peer_id = file_id_to_peer_id(p_fds_evt->write.file_id) - }; - - switch (p_fds_evt->id) - { - case FDS_EVT_WRITE: - case FDS_EVT_UPDATE: - case FDS_EVT_DEL_RECORD: - if ( file_id_within_pm_range(p_fds_evt->write.file_id) - || record_key_within_pm_range(p_fds_evt->write.record_key)) - { - pds_evt.params.peer_data_update_succeeded.data_id - = record_key_to_peer_data_id(p_fds_evt->write.record_key); - pds_evt.params.peer_data_update_succeeded.action - = (p_fds_evt->id == FDS_EVT_DEL_RECORD) ? PM_PEER_DATA_OP_DELETE - : PM_PEER_DATA_OP_UPDATE; - pds_evt.params.peer_data_update_succeeded.token = p_fds_evt->write.record_id; - - if (p_fds_evt->result == FDS_SUCCESS) - { - pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; - pds_evt.params.peer_data_update_succeeded.flash_changed = true; - } - else - { - pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED; - pds_evt.params.peer_data_update_failed.error = p_fds_evt->result; - } - - pds_evt_send(&pds_evt); - } - break; - - case FDS_EVT_DEL_FILE: - if ( file_id_within_pm_range(p_fds_evt->del.file_id) - && (p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY)) - { - if (p_fds_evt->result == FDS_SUCCESS) - { - pds_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED; - peer_id_free(pds_evt.peer_id); - } - else - { - pds_evt.evt_id = PM_EVT_PEER_DELETE_FAILED; - } - - m_peer_delete_queued = false; - m_peer_delete_ongoing = false; - - peer_data_delete(); - - pds_evt_send(&pds_evt); - } - break; - - case FDS_EVT_GC: - pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTED; - pds_evt.peer_id = PM_PEER_ID_INVALID; - - pds_evt_send(&pds_evt); - break; - - default: - // No action. - break; - } - - if (m_peer_delete_queued) - { - m_peer_delete_queued = false; - peer_data_delete(); - } -} - - -ret_code_t pds_init() -{ - ret_code_t ret; - - // Check for re-initialization if debugging. - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - ret = fds_register(fds_evt_handler); - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - ret = fds_init(); - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_STORAGE_FULL; - } - - peer_id_init(); - peer_ids_load(); - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_data, - uint32_t const * const p_buf_len) -{ - ret_code_t ret; - fds_record_desc_t rec_desc; - fds_flash_record_t rec_flash; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_data != NULL); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - ret = peer_data_find(peer_id, data_id, &rec_desc); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - // Shouldn't fail, unless the record was deleted in the meanwhile or the CRC check has failed. - ret = fds_record_open(&rec_desc, &rec_flash); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - p_data->data_id = data_id; - p_data->length_words = rec_flash.p_header->length_words; - - // If p_buf_len is NULL, provide a pointer to data in flash, otherwise, - // check that the buffer is large enough and copy the data in flash into the buffer. - if (p_buf_len == NULL) - { - // The cast is necessary because if no buffer is provided, we just copy the pointer, - // but in that case it should be considered a pointer to const data by the caller, - // since it is a pointer to data in flash. - p_data->p_all_data = (void*)rec_flash.p_data; - } - else - { - uint32_t const data_len_bytes = (p_data->length_words * sizeof(uint32_t)); - - if ((*p_buf_len) >= data_len_bytes) - { - memcpy(p_data->p_all_data, rec_flash.p_data, data_len_bytes); - } - else - { - return NRF_ERROR_NO_MEM; - } - } - - // Shouldn't fail unless the record was already closed, in which case it can be ignored. - (void)fds_record_close(&rec_desc); - - return NRF_SUCCESS; -} - - -void pds_peer_data_iterate_prepare(void) -{ - memset(&m_fds_ftok, 0x00, sizeof(fds_find_token_t)); -} - - -bool pds_peer_data_iterate(pm_peer_data_id_t data_id, - pm_peer_id_t * const p_peer_id, - pm_peer_data_flash_t * const p_data) -{ - ret_code_t ret; - uint16_t rec_key; - fds_record_desc_t rec_desc; - fds_flash_record_t rec_flash; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_id != NULL); - NRF_PM_DEBUG_CHECK(p_data != NULL); - - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - rec_key = peer_data_id_to_record_key(data_id); - - if (fds_record_find_by_key(rec_key, &rec_desc, &m_fds_ftok) != NRF_SUCCESS) - { - return false; - } - - ret = fds_record_open(&rec_desc, &rec_flash); - - if (ret != NRF_SUCCESS) - { - // It can only happen if the record was deleted after the call to fds_record_find_by_key(), - // before we could open it, or if CRC support was enabled in Flash Data Storage at compile - // time and the CRC check failed. - return false; - } - - p_data->data_id = data_id; - p_data->length_words = rec_flash.p_header->length_words; - p_data->p_all_data = rec_flash.p_data; - - *p_peer_id = file_id_to_peer_id(rec_flash.p_header->file_id); - - (void)fds_record_close(&rec_desc); - - return true; -} - - -ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t * p_prepare_token) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - NRF_PM_DEBUG_CHECK(p_prepare_token != NULL); - - VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); - - ret = fds_reserve((fds_reserve_token_t*)p_prepare_token, p_peer_data->length_words); - - switch (ret) - { - case FDS_SUCCESS: - return NRF_SUCCESS; - - case FDS_ERR_RECORD_TOO_LARGE: - return NRF_ERROR_INVALID_LENGTH; - - case FDS_ERR_NO_SPACE_IN_FLASH: - return NRF_ERROR_STORAGE_FULL; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(prepare_token != PDS_PREPARE_TOKEN_INVALID); - - ret = fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); - - if (ret != FDS_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - return NRF_SUCCESS; -} - - -ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t prepare_token, - pm_store_token_t * p_store_token) -{ - ret_code_t ret; - fds_record_t rec; - fds_record_desc_t rec_desc; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); - - // Prepare the record to be stored in flash. - rec.file_id = peer_id_to_file_id(peer_id); - rec.key = peer_data_id_to_record_key(p_peer_data->data_id); - rec.data.p_data = (void*)p_peer_data->p_all_data; - rec.data.length_words = p_peer_data->length_words; - - ret = peer_data_find(peer_id, p_peer_data->data_id, &rec_desc); - - if (ret == NRF_ERROR_NOT_FOUND) - { - // No previous data exists in flash. - if (prepare_token == PDS_PREPARE_TOKEN_INVALID) - { - // No space was previously reserved. - ret = fds_record_write(&rec_desc, &rec); - } - else - { - // Space for this record was previously reserved. - ret = fds_record_write_reserved(&rec_desc, &rec, (fds_reserve_token_t*)&prepare_token); - } - } - else // NRF_SUCCESS - { - if (prepare_token != PDS_PREPARE_TOKEN_INVALID) - { - (void)fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); - } - - // Update existing record. - ret = fds_record_update(&rec_desc, &rec); - } - - switch (ret) - { - case FDS_SUCCESS: - if (p_store_token != NULL) - { - // Update the store token. - (void)fds_record_id_from_desc(&rec_desc, (uint32_t*)p_store_token); - } - return NRF_SUCCESS; - - case FDS_ERR_BUSY: - case FDS_ERR_NO_SPACE_IN_QUEUES: - return NRF_ERROR_BUSY; - - case FDS_ERR_NO_SPACE_IN_FLASH: - return NRF_ERROR_STORAGE_FULL; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - ret_code_t ret; - fds_record_desc_t record_desc; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - ret = peer_data_find(peer_id, data_id, &record_desc); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - ret = fds_record_delete(&record_desc); - - switch (ret) - { - case FDS_SUCCESS: - return NRF_SUCCESS; - - case FDS_ERR_NO_SPACE_IN_QUEUES: - return NRF_ERROR_BUSY; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -pm_peer_id_t pds_peer_id_allocate(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_allocate(PM_PEER_ID_INVALID); -} - - -ret_code_t pds_peer_id_free(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - VERIFY_PEER_ID_IN_RANGE(peer_id); - - (void)peer_id_delete(peer_id); - peer_data_delete(); - - return NRF_SUCCESS; -} - - -bool pds_peer_id_is_allocated(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_is_allocated(peer_id); -} - - -pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_get_next_used(prev_peer_id); -} - - -pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_get_next_deleted(prev_peer_id); -} - - -uint32_t pds_peer_count_get(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_n_ids(); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h deleted file mode 100644 index 2138a3b61d..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_DATA_STORAGE_H__ -#define PEER_DATA_STORAGE_H__ - - -#include -#include "sdk_errors.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup peer_data_storage Peer Data Storage - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides a Peer Manager-specific API - * to the persistent storage. - * - * @details This module uses Flash Data Storage (FDS) to interface with persistent storage. - */ - -#define PDS_PREPARE_TOKEN_INVALID (0) /**< Invalid value for prepare token. */ -#define PDS_FIRST_RESERVED_FILE_ID (0xC000) /**< The beginning of the range of file IDs reserved for Peer Manager. */ -#define PDS_LAST_RESERVED_FILE_ID (0xFFFE) /**< The end of the range of file IDs reserved for Peer Manager. */ -#define PDS_FIRST_RESERVED_RECORD_KEY (0xC000) /**< The beginning of the range of record keys reserved for Peer Manager. */ -#define PDS_LAST_RESERVED_RECORD_KEY (0xFFFE) /**< The end of the range of record keys reserved for Peer Manager. */ - -#define PEER_ID_TO_FILE_ID ( PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting a @ref pm_peer_id_t to an FDS file ID. -#define FILE_ID_TO_PEER_ID (-PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting an FDS file ID to a @ref pm_peer_id_t. -#define DATA_ID_TO_RECORD_KEY ( PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting a @ref pm_peer_data_id_t to an FDS record ID. -#define RECORD_KEY_TO_DATA_ID (-PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting an FDS record ID to a @ref pm_peer_data_id_t. - - -/**@brief Function for initializing the module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_STORAGE_FULL If no flash pages were available for use. - * @retval NRF_ERROR_INTERNAL If the module couldn't register with the flash filesystem. - */ -ret_code_t pds_init(void); - - -/**@brief Function for reading peer data in flash. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to retrieve. - * @param[out] p_data The peer data. May not be @c NULL. - * @param[in] p_buf_len Length of the provided buffer, in bytes. Pass @c NULL to only copy - * a pointer to the data in flash. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. - * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. - */ -ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_data, - uint32_t const * const p_buf_len); - - -/**@brief Function to prepare iterating over peer data in flash using @ref pds_peer_data_iterate. - * Call this function once each time before iterating using @ref pds_peer_data_iterate. - */ -void pds_peer_data_iterate_prepare(void); - - -/**@brief Function for iterating peers' data in flash. - * Always call @ref pds_peer_data_iterate_prepare before starting iterating. - * - * @param[in] data_id The peer data to iterate over. - * @param[out] p_peer_id The peer the data belongs to. - * @param[out] p_data The peer data in flash. - * - * @retval true If the operation was successful. - * @retval false If the data was not found in flash, or another error occurred. - */ -bool pds_peer_data_iterate(pm_peer_data_id_t data_id, - pm_peer_id_t * const p_peer_id, - pm_peer_data_flash_t * const p_data); - - -/**@brief Function for reserving space in flash to store data. - * - * @param[in] p_peer_data The data to be stored in flash. Only data length and type (ID) are - * relevant for this operation. May not be @c NULL. - * @param[out] p_prepare_token A token identifying the reserved space. May not be @c NULL. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the data ID in @p p_peer_data is invalid. - * @retval NRF_ERROR_INVALID_LENGTH If data length exceeds the maximum allowed length. - * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t * p_prepare_token); - - -/**@brief Function for undoing a previous call to @ref pds_space_reserve. - * - * @param[in] prepare_token A token identifying the reservation to cancel. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token); - - -/**@brief Function for storing peer data in flash. If the same piece of data already exists for the - * given peer, it will be updated. This operation is asynchronous. - * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED - * event. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] p_peer_data The peer data. May not be @c NULL. - * @param[in] prepare_token A token identifying the reservation made in flash to store the data. - * Pass @ref PDS_PREPARE_TOKEN_INVALID if no space was reserved. - * @param[out] p_store_token A token identifying this particular store operation. The token can be - * used to identify events pertaining to this operation. Pass @p NULL - * if not used. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or the data ID in @p_peer_data are invalid. - * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. This can only happen if - * @p p_prepare_token is @ref PDS_PREPARE_TOKEN_INVALID. - * @retval NRF_ERROR_BUSY If the flash filesystem was busy. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t prepare_token, - pm_store_token_t * p_store_token); - - -/**@brief Function for deleting peer data in flash. This operation is asynchronous. - * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED - * event. - * - * @param[in] peer_id The peer the data belongs to - * @param[in] data_id The data to delete. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. - * @retval NRF_ERROR_BUSY If the flash filesystem was busy. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for claiming an unused peer ID. - * - * @retval PM_PEER_ID_INVALID If no peer ID was available. - */ -pm_peer_id_t pds_peer_id_allocate(void); - - -/**@brief Function for freeing a peer ID and deleting all data associated with it in flash. - * - * @param[in] peer_id The ID of the peer to free. - * - * @retval NRF_SUCCESS The operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id is invalid. - */ -ret_code_t pds_peer_id_free(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is in use. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true @p peer_id is in use. - * @retval false @p peer_id is free. - */ -bool pds_peer_id_is_allocated(pm_peer_id_t peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The first ordinary peer ID If @p prev_peer_id is @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID If @p prev_peer_id is the last ordinary peer ID or the module - * is not initialized. - */ -pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. - * Can be used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID pending deletion. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module - * is not initialized. - */ -pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pds_peer_count_get(void); - - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_DATA_STORAGE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c deleted file mode 100644 index 9216136959..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c +++ /dev/null @@ -1,831 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_database.h" - -#include -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_data_storage.h" -#include "pm_buffer.h" - - -/**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer. - * - * @param[in] data_id The data ID to verify. - */ -// @note emdi: could this maybe be a function? -#define VERIFY_DATA_ID_WRITE_BUF(data_id) \ -do \ -{ \ - if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \ - { \ - return NRF_ERROR_INVALID_PARAM; \ - } \ -} while (0) - - -// The number of registered event handlers. -#define PDB_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Peer Database event handlers in other Peer Manager submodules. -extern void pm_pdb_evt_handler(pm_evt_t * p_event); -extern void sm_pdb_evt_handler(pm_evt_t * p_event); -extern void gscm_pdb_evt_handler(pm_evt_t * p_event); -extern void gcm_pdb_evt_handler(pm_evt_t * p_event); - -// Peer Database events' handlers. -// The number of elements in this array is PDB_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_pdb_evt_handler, - sm_pdb_evt_handler, - gscm_pdb_evt_handler, - gcm_pdb_evt_handler, -}; - - -/**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written - * or cancelled. - */ -typedef struct -{ - pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */ - pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */ - pm_prepare_token_t prepare_token; /**< Token given by Peer Data Storage if room in flash has been reserved. */ - pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. This is used as the check for whether such an operation has been successfully requested. */ - uint8_t n_bufs; /**< The number of buffer blocks containing peer data. */ - uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */ - uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */ - uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */ -} pdb_buffer_record_t; - - -static bool m_module_initialized; -static pm_buffer_t m_write_buffer; /**< The state of the write buffer. */ -static pdb_buffer_record_t m_write_buffer_records[PM_FLASH_BUFFERS]; /**< The available write buffer records. */ -static uint32_t m_n_pending_writes; /**< The number of pending (Not yet successfully requested in Peer Data Storage) store operations. */ - - - -/**@brief Function for invalidating a record of a write buffer allocation. - * - * @param[in] p_record The record to invalidate. - */ -static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record) -{ - p_record->peer_id = PM_PEER_ID_INVALID; - p_record->data_id = PM_PEER_DATA_ID_INVALID; - p_record->buffer_block_id = PM_BUFFER_INVALID_ID; - p_record->store_busy = false; - p_record->store_flash_full = false; - p_record->n_bufs = 0; - p_record->prepare_token = PDS_PREPARE_TOKEN_INVALID; - p_record->store_token = PM_STORE_TOKEN_INVALID; -} - - -/**@brief Function for finding a record of a write buffer allocation. - * - * @param[in] peer_id The peer ID in the record. - * @param[inout] p_index In: The starting index, out: The index of the record - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, uint32_t * p_index) -{ - for (uint32_t i = *p_index; i < PM_FLASH_BUFFERS; i++) - { - if ((m_write_buffer_records[i].peer_id == peer_id)) - { - *p_index = i; - return &m_write_buffer_records[i]; - } - } - return NULL; -} - - -/**@brief Function for finding a record of a write buffer allocation. - * - * @param[in] peer_id The peer ID in the record. - * @param[in] data_id The data ID in the record. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id) -{ - uint32_t index = 0; - pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); - - while ((p_record != NULL) && ( (p_record->data_id != data_id) - || (p_record->store_busy) - || (p_record->store_flash_full) - || (p_record->store_token != PM_STORE_TOKEN_INVALID))) - { - index++; - p_record = write_buffer_record_find_next(peer_id, &index); - } - - return p_record; -} - - -/**@brief Function for finding a record of a write buffer allocation that has been sent to be stored. - * - * @param[in] store_token The store token received when store was called for the record. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_stored(pm_store_token_t store_token) -{ - for (int i = 0; i < PM_FLASH_BUFFERS; i++) - { - if (m_write_buffer_records[i].store_token == store_token) - { - return &m_write_buffer_records[i]; - } - } - return NULL; -} - - -/**@brief Function for finding an available record for write buffer allocation. - * - * @return A pointer to the available record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_unused(void) -{ - return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID); -} - - -/**@brief Function for gracefully deactivating a write buffer record. - * - * @details This function will first release any buffers, then invalidate the record. - * - * @param[inout] p_write_buffer_record The record to release. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record) -{ - for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - - write_buffer_record_invalidate(p_write_buffer_record); -} - - -/**@brief Function for claiming and activating a write buffer record. - * - * @param[out] pp_write_buffer_record The claimed record. - * @param[in] peer_id The peer ID this record should have. - * @param[in] data_id The data ID this record should have. - */ -static void write_buffer_record_acquire(pdb_buffer_record_t ** pp_write_buffer_record, - pm_peer_id_t peer_id, - pm_peer_data_id_t data_id) -{ - if (pp_write_buffer_record == NULL) - { - return; - } - *pp_write_buffer_record = write_buffer_record_find_unused(); - if (*pp_write_buffer_record == NULL) - { - // This also means the buffer is full. - return; - } - (*pp_write_buffer_record)->peer_id = peer_id; - (*pp_write_buffer_record)->data_id = data_id; -} - - -/**@brief Function for dispatching outbound events to all registered event handlers. - * - * @param[in] p_event The event to dispatch. - */ -static void pdb_evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < PDB_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for resetting the internal state of the Peer Database module. - * - * @param[out] p_event The event to dispatch. - */ -static void internal_state_reset() -{ - for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) - { - write_buffer_record_invalidate(&m_write_buffer_records[i]); - } -} - - -static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs) -{ - uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE; - p_peer_data->data_id = data_id; - - p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory; - p_peer_data->length_words = BYTES_TO_WORDS(n_bytes); -} - - -static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs) -{ - peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs); -} - - -static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data) -{ - switch (p_peer_data->data_id) - { - case PM_PEER_DATA_ID_BONDING: - p_peer_data->length_words = PM_BONDING_DATA_N_WORDS(); - break; - case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: - p_peer_data->length_words = PM_SC_STATE_N_WORDS(); - break; - case PM_PEER_DATA_ID_PEER_RANK: - p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS(); - break; - case PM_PEER_DATA_ID_GATT_LOCAL: - p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len); - break; - default: - // No action needed. - break; - } -} - - -/**@brief Function for writing data into persistent storage. Writing happens asynchronously. - * - * @note This will unlock the data after it has been written. - * - * @param[in] p_write_buffer_record The write buffer record to write into persistent storage. - * - * @retval NRF_SUCCESS Data storing was successfully started. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some - * space, the operation will be reattempted after the next compress - * procedure. This error will not happen if - * @ref pdb_write_buf_store_prepare is called beforehand. - * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. - * @retval NRF_ERROR_INVALID_STATE Module is not initialized. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t write_buf_store(pdb_buffer_record_t * p_write_buffer_record) -{ - ret_code_t err_code = NRF_SUCCESS; - pm_peer_data_const_t peer_data = {.data_id = p_write_buffer_record->data_id}; - uint8_t * p_buffer_memory; - - p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_const_point_to_buffer(&peer_data, - p_write_buffer_record->data_id, - p_buffer_memory, - p_write_buffer_record->n_bufs); - write_buf_length_words_set(&peer_data); - - err_code = pds_peer_data_store(p_write_buffer_record->peer_id, - &peer_data, - p_write_buffer_record->prepare_token, - &p_write_buffer_record->store_token); - - if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full) - { - m_n_pending_writes--; - } - - switch (err_code) - { - case NRF_SUCCESS: - p_write_buffer_record->store_busy = false; - p_write_buffer_record->store_flash_full = false; - break; - - case NRF_ERROR_BUSY: - m_n_pending_writes++; - - p_write_buffer_record->store_busy = true; - p_write_buffer_record->store_flash_full = false; - - err_code = NRF_SUCCESS; - break; - - case NRF_ERROR_STORAGE_FULL: - m_n_pending_writes++; - - p_write_buffer_record->store_busy = false; - p_write_buffer_record->store_flash_full = true; - break; - - case NRF_ERROR_INVALID_PARAM: - // No action. - break; - - default: - err_code = NRF_ERROR_INTERNAL; - break; - } - - return err_code; -} - - -/**@brief This calls @ref write_buf_store and sends events based on the return value. - * - * See @ref write_buf_store for more info. - * - * @return Whether or not the store operation succeeded. - */ -static bool write_buf_store_in_event(pdb_buffer_record_t * p_write_buffer_record) -{ - ret_code_t err_code; - pm_evt_t event; - - err_code = write_buf_store(p_write_buffer_record); - if (err_code != NRF_SUCCESS) - { - event.conn_handle = BLE_CONN_HANDLE_INVALID; - event.peer_id = p_write_buffer_record->peer_id; - - if (err_code == NRF_ERROR_STORAGE_FULL) - { - event.evt_id = PM_EVT_STORAGE_FULL; - } - else - { - event.evt_id = PM_EVT_ERROR_UNEXPECTED; - event.params.error_unexpected.error = err_code; - } - - pdb_evt_send(&event); - - return false; - } - - return true; -} - - -/**@brief This reattempts store operations on write buffers, that previously failed because of @ref - * NRF_ERROR_BUSY or @ref NRF_ERROR_STORAGE_FULL errors. - * - * param[in] retry_flash_full Whether to retry operations that failed because of an - * @ref NRF_ERROR_STORAGE_FULL error. - */ -static void reattempt_previous_operations(bool retry_flash_full) -{ - // Reattempt previously rejected store operations. - - if (m_n_pending_writes == 0) - { - return; - } - - for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) - { - if ((m_write_buffer_records[i].store_busy) - || (m_write_buffer_records[i].store_flash_full && retry_flash_full)) - { - bool success = write_buf_store_in_event(&m_write_buffer_records[i]); - - if (!success) - { - break; - } - } - } -} - - -/**@brief Function for handling events from the Peer Data Storage module. - * This function is extern in Peer Data Storage. - * - * @param[in] p_event The event to handle. - */ -void pdb_pds_evt_handler(pm_evt_t * p_event) -{ - pdb_buffer_record_t * p_write_buffer_record; - bool evt_send = true; - bool retry_flash_full = false; - - p_write_buffer_record = write_buffer_record_find_stored(p_event->params.peer_data_update_succeeded.token); - - switch (p_event->evt_id) - { - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - && (p_write_buffer_record != NULL)) - { - // The write came from PDB. - write_buffer_record_release(p_write_buffer_record); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - && (p_write_buffer_record != NULL)) - { - // The write came from PDB, retry. - m_n_pending_writes++; - p_write_buffer_record->store_token = PM_STORE_TOKEN_INVALID; - p_write_buffer_record->store_busy = true; - evt_send = false; - } - break; - - case PM_EVT_FLASH_GARBAGE_COLLECTED: - retry_flash_full = true; - break; - - default: - break; - } - - if (evt_send) - { - // Forward the event to all registered Peer Database event handlers. - pdb_evt_send(p_event); - } - - reattempt_previous_operations(retry_flash_full); -} - - -ret_code_t pdb_init() -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - PM_BUFFER_INIT(&m_write_buffer, PM_FLASH_BUFFERS, PDB_WRITE_BUF_SIZE, ret); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -pm_peer_id_t pdb_peer_allocate(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_id_allocate(); -} - - -ret_code_t pdb_peer_free(pm_peer_id_t peer_id) -{ - ret_code_t err_code_in = NRF_SUCCESS; - ret_code_t err_code_out = NRF_SUCCESS; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint32_t index = 0; - pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); - - while (p_record != NULL) - { - err_code_in = pdb_write_buf_release(peer_id, p_record->data_id); - - if ( (err_code_in != NRF_SUCCESS) - && (err_code_in != NRF_ERROR_NOT_FOUND)) - { - err_code_out = NRF_ERROR_INTERNAL; - } - - index++; - p_record = write_buffer_record_find_next(peer_id, &index); - } - - if (err_code_out == NRF_SUCCESS) - { - err_code_in = pds_peer_id_free(peer_id); - - if (err_code_in == NRF_SUCCESS) - { - // No action needed. - } - else if (err_code_in == NRF_ERROR_INVALID_PARAM) - { - err_code_out = NRF_ERROR_INVALID_PARAM; - } - else - { - err_code_out = NRF_ERROR_INTERNAL; - } - } - - return err_code_out; -} - - -ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_flash_t * const p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - // Pass NULL to only retrieve a pointer. - return pds_peer_data_read(peer_id, data_id, (pm_peer_data_t*)p_peer_data, NULL); -} - - - -ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - uint32_t n_bufs, - pm_peer_data_t * p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_PARAM_NOT_NULL(p_peer_data); - VERIFY_DATA_ID_WRITE_BUF(data_id); - - if ( (n_bufs == 0) - || (n_bufs > PM_FLASH_BUFFERS) - || !pds_peer_id_is_allocated(peer_id)) - { - return NRF_ERROR_INVALID_PARAM; - } - - pdb_buffer_record_t * p_write_buffer_record; - uint8_t * p_buffer_memory; - bool new_record = false; - bool find_new_buffer = false; - - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - find_new_buffer = true; - } - else if (p_write_buffer_record->n_bufs < n_bufs) - { - // @TODO: Copy? - // Existing buffer is too small. - for (uint8_t i = 0; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - write_buffer_record_invalidate(p_write_buffer_record); - find_new_buffer = true; - } - else if (p_write_buffer_record->n_bufs > n_bufs) - { - // Release excess blocks. - for (uint8_t i = n_bufs; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - } - else - { - // Do nothing. - } - - if (find_new_buffer) - { - // No buffer exists. - write_buffer_record_acquire(&p_write_buffer_record, peer_id, data_id); - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_BUSY; - } - } - - if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) - { - p_write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_write_buffer, n_bufs); - - if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) - { - write_buffer_record_invalidate(p_write_buffer_record); - return NRF_ERROR_BUSY; - } - - new_record = true; - } - - p_write_buffer_record->n_bufs = n_bufs; - - p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); - - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs); - if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL)) - { - p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words); - } - - return NRF_SUCCESS; -} - - -ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret_code_t err_code = NRF_SUCCESS; - pdb_buffer_record_t * p_write_buffer_record; - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID) - { - err_code = pds_space_reserve_cancel(p_write_buffer_record->prepare_token); - if (err_code != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - } - - write_buffer_record_release(p_write_buffer_record); - - return err_code; -} - - -ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_DATA_ID_WRITE_BUF(data_id); - - ret_code_t err_code = NRF_SUCCESS; - pdb_buffer_record_t * p_write_buffer_record; - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID) - { - uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, - p_write_buffer_record->buffer_block_id); - pm_peer_data_const_t peer_data = {.data_id = data_id}; - - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs); - - write_buf_length_words_set(&peer_data); - - err_code = pds_space_reserve(&peer_data, &p_write_buffer_record->prepare_token); - if (err_code == NRF_ERROR_INVALID_LENGTH) - { - return NRF_ERROR_INTERNAL; - } - } - - return err_code; -} - - -ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_id_t new_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_DATA_ID_WRITE_BUF(data_id); - - pdb_buffer_record_t * p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - p_write_buffer_record->peer_id = new_peer_id; - p_write_buffer_record->data_id = data_id; - return write_buf_store(p_write_buffer_record); -} - - -ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_data_delete(peer_id, data_id); -} - - -uint32_t pdb_n_peers(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_count_get(); -} - - -pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_next_peer_id_get(prev_peer_id); -} - - -pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_next_deleted_peer_id_get(prev_peer_id); -} - - -ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - // Provide the buffer length in bytes. - uint32_t const data_len_bytes = (p_peer_data->length_words * sizeof(uint32_t)); - return pds_peer_data_read(peer_id, data_id, p_peer_data, &data_len_bytes); -} - - -ret_code_t pdb_raw_store(pm_peer_id_t peer_id, - pm_peer_data_const_t * p_peer_data, - pm_store_token_t * p_store_token) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_data_store(peer_id, p_peer_data, PDS_PREPARE_TOKEN_INVALID, p_store_token); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h deleted file mode 100644 index 5e1e0fb6b8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_DATABASE_H__ -#define PEER_DATABASE_H__ - -#include -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "sdk_errors.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @cond NO_DOXYGEN - * @defgroup peer_database Peer Database - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for simple management of reading and - * writing of peer data into persistent storage. - * - */ - -#define PDB_WRITE_BUF_SIZE (sizeof(pm_peer_data_bonding_t)) //!< The size (in bytes) of each block in the internal buffer accessible via @ref pdb_write_buf_get. - - -/**@brief Function for initializing the module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL An unexpected error happened. - */ -ret_code_t pdb_init(void); - - -/**@brief Function for allocating persistent bond storage for a peer. - * - * @return The ID of the newly allocated storage. - * @retval PM_PEER_ID_INVALID If no peer ID is available. - */ -pm_peer_id_t pdb_peer_allocate(void); - - -/**@brief Function for freeing a peer's persistent bond storage. - * - * @note This function will call @ref pdb_write_buf_release on the data for this peer. - * - * @param[in] peer_id ID to be freed. - * - * @retval NRF_SUCCESS Peer ID was released and clear operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM Peer ID was invalid. - */ -ret_code_t pdb_peer_free(pm_peer_id_t peer_id); - - -/**@brief Function for retrieving a pointer to peer data in flash (read-only). - * - * @note Dereferencing this pointer is not the safest thing to do if interrupts are enabled, - * because Flash Data Storage garbage collection might move the data around. Either disable - * interrupts while using the data, or use @ref pdb_peer_data_load. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to read. - * @param[out] p_peer_data The peer data, read-only. - * - * @retval NRF_SUCCESS If the pointer to the data was retrieved successfully. - * @retval NRF_ERROR_INVALID_PARAM If either @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. - */ -ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_flash_t * const p_peer_data); - - -/**@brief Function for retrieving pointers to a write buffer for peer data. - * - * @details This function will provide pointers to a buffer of the data. The data buffer will not be - * written to persistent storage until @ref pdb_write_buf_store is called. The buffer is - * released by calling either @ref pdb_write_buf_release, @ref pdb_write_buf_store, or - * @ref pdb_peer_free. - * - * When the data_id refers to a variable length data type, the available size is written - * to the data, both the top-level, and any internal length fields. - * - * @note Calling this function on a peer_id/data_id pair that already has a buffer created will - * give the same buffer, not create a new one. If n_bufs was increased since last time, the - * buffer might be relocated to be able to provide additional room. In this case, the data - * will be copied. If n_bufs was increased since last time, this function might return @ref - * NRF_ERROR_BUSY. In that case, the buffer is automatically released. - * - * @param[in] peer_id ID of peer to get a write buffer for. - * @param[in] data_id Which piece of data to get. - * @param[in] n_bufs The number of contiguous buffers needed. - * @param[out] p_peer_data Pointers to mutable peer data. - * - * @retval NRF_SUCCESS Data retrieved successfully. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated, or n_bufs was 0 - * or more than the total available buffers. - * @retval NRF_ERROR_NULL p_peer_data was NULL. - * @retval NRF_ERROR_BUSY Not enough buffer(s) available. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - uint32_t n_bufs, - pm_peer_data_t * p_peer_data); - - -/**@brief Function for freeing a write buffer allocated with @ref pdb_write_buf_get. - * - * @note This function will not write peer data to persistent memory. Data in released buffer will - * be lost. - * - * @note This function will undo any previous call to @ref pdb_write_buf_store_prepare for this - * piece of data. - * - * @param[in] peer_id ID of peer to release buffer for. - * @param[in] data_id Which piece of data to release buffer for. - * - * @retval NRF_SUCCESS Successfully released buffer. - * @retval NRF_ERROR_NOT_FOUND No buffer was allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for reserving space in persistent storage for data in a buffer. - * - * @note This function only works for data which has a write buffer allocated. If the write buffer - * is released, this prepare is undone. - * - * @note If space has already been reserved for this data, nothing is done. - * - * @param[in] peer_id The peer whose data to reserve space for. - * @param[in] data_id The type of data to reserve space for. - * - * @retval NRF_SUCCESS Successfully reserved space in persistent storage. - * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. - * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - */ -ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for writing data into persistent storage. Writing happens asynchronously. - * - * @note This will unlock the data after it has been written. - * - * @param[in] peer_id The ID used to address the write buffer. - * @param[in] data_id Which piece of data to store. - * @param[in] new_peer_id The ID to put in flash. This will usually be the same as peer_id. - * - * @retval NRF_SUCCESS Data storing was successfully started. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some - * space, the operation will be reattempted after the next compress - * procedure. This error will not happen if - * @ref pdb_write_buf_store_prepare is called beforehand. - * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. - * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_id_t new_peer_id); - - -/**@brief Function for clearing data from persistent storage. - * - * @param[in] peer_id ID of peer to clear data for. - * @param[in] data_id Which piece of data to clear. - * - * @retval NRF_SUCCESS The clear was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM Data ID or peer ID was invalid. - * @retval NRF_ERROR_NOT_FOUND Nothing to clear for this peer ID/data ID combination. - * @retval NRF_ERROR_BUSY Underlying modules are busy and can't take any more requests at - * this moment. - * @retval NRF_ERROR_INTERNAL Internal error. - */ -ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pdb_n_peers(void); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. - */ -pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. - * Can be used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID pending deletion. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. - */ -pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for copy peer data from flash into a provided buffer. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to read. - * @param[inout] p_peer_data The buffer where to copy data into. The field @c length_words in this - * parameter must represent the buffer length in words. - * - * @note Actually, it represents the buffer length in bytes upon entering the function, - * and upon exit it represents the length of the data in words.. not good. Fix this. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. - * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. - */ -ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_peer_data); - - -/**@brief Function for writing data directly to persistent storage from external memory. - * - * @param[in] peer_id ID of peer to write data for. - * @param[in] p_peer_data Data to store. - * @param[out] p_store_token A token identifying this particular store operation. The token can be - * used to identify events pertaining to this operation. - * - * @retval NRF_SUCCESS Data successfully written. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - * @retval NRF_ERROR_NULL p_peer_data contained a NULL pointer. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. - * @retval NRF_ERROR_INVALID_LENGTH Data length above the maximum allowed. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. - */ -ret_code_t pdb_raw_store(pm_peer_id_t peer_id, - pm_peer_data_const_t * p_peer_data, - pm_store_token_t * p_store_token); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_DATABASE_H__ */ - - diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c deleted file mode 100644 index 06b0594c71..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_id.h" - -#include -#include -#include "sdk_errors.h" -#include "peer_manager_types.h" -#include "pm_mutex.h" - - -typedef struct -{ - uint8_t used_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are in use. */ - uint8_t deleted_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are marked for deletion. */ -} pi_t; - - -static pi_t m_pi = {{0}, {0}}; - - -static void internal_state_reset(pi_t * p_pi) -{ - memset(p_pi, 0, sizeof(pi_t)); -} - - -void peer_id_init(void) -{ - internal_state_reset(&m_pi); - pm_mutex_init(m_pi.used_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); - pm_mutex_init(m_pi.deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); -} - - -static pm_peer_id_t claim(pm_peer_id_t peer_id, uint8_t * mutex_group) -{ - pm_peer_id_t allocated_peer_id = PM_PEER_ID_INVALID; - if (peer_id == PM_PEER_ID_INVALID) - { - allocated_peer_id = pm_mutex_lock_first_available(mutex_group, PM_PEER_ID_N_AVAILABLE_IDS); - if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS) - { - allocated_peer_id = PM_PEER_ID_INVALID; - } - } - else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - bool lock_success = pm_mutex_lock(mutex_group, peer_id); - allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID; - } - return allocated_peer_id; -} - - -static void release(pm_peer_id_t peer_id, uint8_t * mutex_group) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - pm_mutex_unlock(mutex_group, peer_id); - } -} - - -pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id) -{ - return claim(peer_id, m_pi.used_peer_ids); -} - - -bool peer_id_delete(pm_peer_id_t peer_id) -{ - pm_peer_id_t deleted_peer_id; - - if (peer_id == PM_PEER_ID_INVALID) - { - return false; - } - - deleted_peer_id = claim(peer_id, m_pi.deleted_peer_ids); - - return (deleted_peer_id == peer_id); -} - - -void peer_id_free(pm_peer_id_t peer_id) -{ - release(peer_id, m_pi.used_peer_ids); - release(peer_id, m_pi.deleted_peer_ids); -} - - -bool peer_id_is_allocated(pm_peer_id_t peer_id) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - return pm_mutex_lock_status_get(m_pi.used_peer_ids, peer_id); - } - return false; -} - - -bool peer_id_is_deleted(pm_peer_id_t peer_id) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - return pm_mutex_lock_status_get(m_pi.deleted_peer_ids, peer_id); - } - return false; -} - - -pm_peer_id_t next_id_get(pm_peer_id_t prev_peer_id, uint8_t * mutex_group) -{ - pm_peer_id_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1); - for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) - { - if (pm_mutex_lock_status_get(mutex_group, i)) - { - return i; - } - } - - return PM_PEER_ID_INVALID; -} - - -pm_peer_id_t peer_id_get_next_used(pm_peer_id_t peer_id) -{ - peer_id = next_id_get(peer_id, m_pi.used_peer_ids); - - while (peer_id != PM_PEER_ID_INVALID) - { - if (!peer_id_is_deleted(peer_id)) - { - return peer_id; - } - - peer_id = next_id_get(peer_id, m_pi.used_peer_ids); - } - - return peer_id; -} - - -pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id) -{ - return next_id_get(prev_peer_id, m_pi.deleted_peer_ids); -} - - -uint32_t peer_id_n_ids(void) -{ - uint32_t n_ids = 0; - - for (pm_peer_id_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) - { - n_ids += pm_mutex_lock_status_get(m_pi.used_peer_ids, i); - } - - return n_ids; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h deleted file mode 100644 index 5664ccc574..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_ID_H__ -#define PEER_ID_H__ - - -#include -#include "sdk_errors.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup peer_id Peer IDs - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module keeps track of which peer IDs are in - * use and which are free. - */ - - -/**@brief Function for initializing the module. - */ -void peer_id_init(void); - - -/**@brief Function for claiming an unused peer ID. - * - * @param peer_id The peer ID to allocate. If this is @ref PM_PEER_ID_INVALID, the first available - * will be allocated. - * - * @return The allocated peer ID. - * @retval PM_PEER_ID_INVALID If no peer ID could be allocated or module is not initialized. - */ -pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id); - - -/**@brief Function for marking a peer ID for deletion. - * - * @param peer_id The peer ID to delete. - * - * @retval true Deletion was successful. - * @retval false Peer ID already marked for deletion, peer_id was PM_PEER_ID_INVALID, or module is - * not initialized. - */ -bool peer_id_delete(pm_peer_id_t peer_id); - - -/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent - * storage. - * - * @param[in] peer_id Peer ID to free. - */ -void peer_id_free(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is marked for deletion. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true peer_id is in marked for deletion. - * @retval false peer_id is not marked for deletion, or the module is not initialized. - */ -bool peer_id_is_deleted(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is in use. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true peer_id is in use. - * @retval false peer_id is free, or the module is not initialized. - */ -bool peer_id_is_allocated(pm_peer_id_t peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is - * not initialized. - */ -pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs marked for deletion. - * Can be used to loop through all peer IDs marked for deletion. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is - * not initialized. - */ -pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs, or 0 if module is not initialized. - */ -uint32_t peer_id_n_ids(void); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_ID_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c deleted file mode 100644 index 9d31a463ca..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c +++ /dev/null @@ -1,965 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "ble_err.h" -#include "peer_manager.h" -#include -#include "security_manager.h" -#include "security_dispatcher.h" -#include "gatt_cache_manager.h" -#include "gatts_cache_manager.h" -#include "peer_database.h" -#include "peer_data_storage.h" -#include "id_manager.h" -#include "ble_conn_state.h" -#include "peer_manager_internal.h" -#include "nrf_sdh_ble.h" - - -#define MODULE_INITIALIZED (m_module_initialized) /**< Macro indicating whether the module has been initialized properly. */ - - -static bool m_module_initialized; /**< Whether or not @ref pm_init has been called successfully. */ -static bool m_peer_rank_initialized; /**< Whether or not @ref rank_init has been called successfully. */ -static bool m_deleting_all; /**< True from when @ref pm_peers_delete is called until all peers have been deleted. */ -static pm_store_token_t m_peer_rank_token; /**< The store token of an ongoing peer rank update via a call to @ref pm_peer_rank_highest. If @ref PM_STORE_TOKEN_INVALID, there is no ongoing update. */ -static uint32_t m_current_highest_peer_rank; /**< The current highest peer rank. Used by @ref pm_peer_rank_highest. */ -static pm_peer_id_t m_highest_ranked_peer; /**< The peer with the highest peer rank. Used by @ref pm_peer_rank_highest. */ -static pm_evt_handler_t m_evt_handlers[PM_MAX_REGISTRANTS];/**< The subscribers to Peer Manager events, as registered through @ref pm_register. */ -static uint8_t m_n_registrants; /**< The number of event handlers registered through @ref pm_register. */ -static ble_conn_state_user_flag_id_t m_bonded_flag_id; /**< The flag ID for which connections are with a peer with which we are bonded. */ - - -/**@brief Function for sending a Peer Manager event to all subscribers. - * - * @param[in] p_pm_evt The event to send. - */ -static void evt_send(pm_evt_t const * p_pm_evt) -{ - for (int i = 0; i < m_n_registrants; i++) - { - m_evt_handlers[i](p_pm_evt); - } -} - - -/**@brief Function for initializing peer rank static variables. - */ -static void rank_vars_update(void) -{ - ret_code_t err_code = pm_peer_ranks_get(&m_highest_ranked_peer, - &m_current_highest_peer_rank, - NULL, - NULL); - - m_peer_rank_initialized = ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); -} - - -/**@brief Event handler for events from the Peer Database module. - * This handler is extern in the Peer Database module. - * - * @param[in] p_pdb_evt The incoming Peer Database event. - */ -void pm_pdb_evt_handler(pm_evt_t * p_pdb_evt) -{ - bool send_evt = true; - - p_pdb_evt->conn_handle = im_conn_handle_get(p_pdb_evt->peer_id); - - switch (p_pdb_evt->evt_id) - { - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) - && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_succeeded.token)) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_highest_ranked_peer = p_pdb_evt->peer_id; - - p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - } - else if ( m_peer_rank_initialized - && (p_pdb_evt->peer_id == m_highest_ranked_peer) - && (p_pdb_evt->params.peer_data_update_succeeded.data_id - == PM_PEER_DATA_ID_PEER_RANK)) - { - // Update peer rank variable if highest ranked peer has changed its rank. - rank_vars_update(); - } - } - else if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_DELETE) - { - if ( m_peer_rank_initialized - && (p_pdb_evt->peer_id == m_highest_ranked_peer) - && (p_pdb_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_PEER_RANK)) - { - // Update peer rank variable if highest ranked peer has deleted its rank. - rank_vars_update(); - } - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) - && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_failed.token)) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_current_highest_peer_rank -= 1; - - p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - } - } - break; - - case PM_EVT_PEER_DELETE_SUCCEEDED: - // Check that no peers marked for deletion are left. - if (m_deleting_all - && (pdb_next_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID) - && (pdb_next_deleted_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID)) - { - // pm_peers_delete() has been called and this is the last peer to be deleted. - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - - send_evt = false; - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); // Ensure that PEER_DELETE_SUCCEEDED arrives before PEERS_DELETE_SUCCEEDED. - evt_send(&pm_delete_all_evt); - } - - if (m_peer_rank_initialized && (p_pdb_evt->peer_id == m_highest_ranked_peer)) - { - // Update peer rank variable if highest ranked peer has been deleted. - rank_vars_update(); - } - break; - - case PM_EVT_PEER_DELETE_FAILED: - if (m_deleting_all) - { - // pm_peers_delete() was called and has thus failed. - - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_FAILED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - pm_delete_all_evt.params.peers_delete_failed_evt.error - = p_pdb_evt->params.peer_delete_failed.error; - - send_evt = false; - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); // Ensure that PEER_DELETE_FAILED arrives before PEERS_DELETE_FAILED. - evt_send(&pm_delete_all_evt); - } - break; - - default: - // Do nothing. - break; - } - - if (send_evt) - { - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); - } -} - - -/**@brief Event handler for events from the Security Manager module. - * This handler is extern in the Security Manager module. - * - * @param[in] p_sm_evt The incoming Security Manager event. - */ -void pm_sm_evt_handler(pm_evt_t * p_sm_evt) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_sm_evt); - - switch (p_sm_evt->evt_id) - { - case PM_EVT_CONN_SEC_SUCCEEDED: - { - bool bonded = p_sm_evt->params.conn_sec_succeeded.procedure - == PM_LINK_SECURED_PROCEDURE_BONDING; - ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_bonded_flag_id, bonded); - break; - } - - default: - /* No action */ - break; - } - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_sm_evt); -} - - -/**@brief Event handler for events from the GATT Cache Manager module. - * This handler is extern in GATT Cache Manager. - * - * @param[in] p_gcm_evt The incoming GATT Cache Manager event. - */ -void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt) -{ - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_gcm_evt); -} - - -/**@brief Event handler for events from the ID Manager module. - * This function is registered in the ID Manager. - * - * @param[in] p_im_evt The incoming ID Manager event. - */ -void pm_im_evt_handler(pm_evt_t * p_im_evt) -{ - switch (p_im_evt->evt_id) - { - case PM_EVT_BONDED_PEER_CONNECTED: - ble_conn_state_user_flag_set(p_im_evt->conn_handle, m_bonded_flag_id, true); - break; - default: - /* No action. */ - break; - } - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_im_evt); -} - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - VERIFY_MODULE_INITIALIZED_VOID(); - - im_ble_evt_handler(p_ble_evt); - sm_ble_evt_handler(p_ble_evt); - gcm_ble_evt_handler(p_ble_evt); -} - -NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, PM_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - - -/**@brief Function for resetting the internal state of this module. - */ -static void internal_state_reset() -{ - m_highest_ranked_peer = PM_PEER_ID_INVALID; - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_bonded_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; -} - - -ret_code_t pm_init(void) -{ - ret_code_t err_code; - - err_code = pds_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = pdb_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = sm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = smd_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = gcm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = gscm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = im_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - internal_state_reset(); - - m_bonded_flag_id = ble_conn_state_user_flag_acquire(); - if (m_bonded_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - m_peer_rank_initialized = false; - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t pm_register(pm_evt_handler_t event_handler) -{ - VERIFY_MODULE_INITIALIZED(); - - if (m_n_registrants >= PM_MAX_REGISTRANTS) - { - return NRF_ERROR_NO_MEM; - } - - m_evt_handlers[m_n_registrants] = event_handler; - m_n_registrants += 1; - - return NRF_SUCCESS; -} - - -ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - - err_code = sm_sec_params_set(p_sec_params); - - // NRF_ERROR_INVALID_PARAM if parameters are invalid, - // NRF_SUCCESS otherwise. - return err_code; -} - - -ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - - err_code = sm_link_secure(conn_handle, force_repairing); - - return err_code; -} - - -void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - if (p_conn_sec_config != NULL) - { - sm_conn_sec_config_reply(conn_handle, p_conn_sec_config); - } -} - - -ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context) -{ - VERIFY_MODULE_INITIALIZED(); - - return sm_sec_params_reply(conn_handle, p_sec_params, p_context); -} - - -void pm_local_database_has_changed(void) -{ - VERIFY_MODULE_INITIALIZED_VOID(); - gcm_local_database_has_changed(); -} - - -ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr) -{ - VERIFY_MODULE_INITIALIZED(); - return im_id_addr_set(p_addr); -} - - -ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_addr); - return im_id_addr_get(p_addr); -} - - -ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_privacy_params); - return im_privacy_set(p_privacy_params); -} - - -ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_privacy_params); - VERIFY_PARAM_NOT_NULL(p_privacy_params->p_device_irk); - return im_privacy_get(p_privacy_params); -} - - -bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - VERIFY_MODULE_INITIALIZED(); - - if ((p_addr == NULL) || (p_irk == NULL)) - { - return false; - } - else - { - return im_address_resolve(p_addr, p_irk); - } -} - - -ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - return im_whitelist_set(p_peers, peer_cnt); -} - - -ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - - if (((p_addrs == NULL) && (p_irks == NULL)) || - ((p_addrs != NULL) && (p_addr_cnt == NULL)) || - ((p_irks != NULL) && (p_irk_cnt == NULL))) - { - // The buffers can't be both NULL, and if a buffer is provided its size must be specified. - return NRF_ERROR_NULL; - } - - return im_whitelist_get(p_addrs, p_addr_cnt, p_irks, p_irk_cnt); -} - - -ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - return im_device_identities_list_set(p_peers, peer_cnt); -} - - -ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_conn_sec_status); - - ble_conn_state_status_t status = ble_conn_state_status(conn_handle); - - if (status == BLE_CONN_STATUS_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - - p_conn_sec_status->connected = (status == BLE_CONN_STATUS_CONNECTED); - p_conn_sec_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_bonded_flag_id); - p_conn_sec_status->encrypted = ble_conn_state_encrypted(conn_handle); - p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); - return NRF_SUCCESS; -} - - -ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) -{ - VERIFY_MODULE_INITIALIZED(); - return sm_lesc_public_key_set(p_public_key); -} - - -ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_conn_handle); - *p_conn_handle = im_conn_handle_get(peer_id); - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_peer_id); - *p_peer_id = im_peer_id_get_by_conn_handle(conn_handle); - return NRF_SUCCESS; -} - - -uint32_t pm_peer_count(void) -{ - if (!MODULE_INITIALIZED) - { - return 0; - } - return pdb_n_peers(); -} - - -pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - if (!MODULE_INITIALIZED) - { - return PM_PEER_ID_INVALID; - } - return pdb_next_peer_id_get(prev_peer_id); -} - - -ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void * p_data, - uint16_t * p_length) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_data); - VERIFY_PARAM_NOT_NULL(p_length); - if (ALIGN_NUM(4, *p_length) != *p_length) - { - return NRF_ERROR_INVALID_PARAM; - } - - pm_peer_data_t peer_data; - memset(&peer_data, 0, sizeof(peer_data)); - peer_data.length_words = BYTES_TO_WORDS(*p_length); - peer_data.data_id = data_id; - peer_data.p_all_data = p_data; - - ret_code_t err_code = pdb_peer_data_load(peer_id, data_id, &peer_data); - - *p_length = peer_data.length_words * BYTES_PER_WORD; - - return err_code; -} - - -ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, - pm_peer_data_bonding_t * p_data) -{ - uint16_t length = sizeof(pm_peer_data_bonding_t); - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_BONDING, - p_data, - &length); -} - - -ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, - ble_gatt_db_srv_t * p_data, - uint16_t * p_length) -{ - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_GATT_REMOTE, - p_data, - p_length); -} - - -ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, - void * p_data, - uint16_t * p_length) -{ - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_APPLICATION, - p_data, - p_length); -} - - -ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_data); - if (ALIGN_NUM(4, length) != length) - { - return NRF_ERROR_INVALID_PARAM; - } - - pm_peer_data_flash_t peer_data; - memset(&peer_data, 0, sizeof(peer_data)); - peer_data.length_words = BYTES_TO_WORDS(length); - peer_data.data_id = data_id; - peer_data.p_all_data = p_data; - - return pdb_raw_store(peer_id, &peer_data, p_token); -} - - -ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, - pm_peer_data_bonding_t const * p_data, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_BONDING, - p_data, - ALIGN_NUM(4, sizeof(pm_peer_data_bonding_t)), - p_token); -} - - -ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, - ble_gatt_db_srv_t const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_GATT_REMOTE, - p_data, - length, - p_token); -} - - -ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, - void const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_APPLICATION, - p_data, - length, - p_token); -} - - -ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - VERIFY_MODULE_INITIALIZED(); - - if (data_id == PM_PEER_DATA_ID_BONDING) - { - return NRF_ERROR_INVALID_PARAM; - } - - return pdb_clear(peer_id, data_id); -} - - -ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, - pm_peer_data_bonding_t * p_bonding_data, - pm_store_token_t * p_token) -{ - ret_code_t err_code; - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_bonding_data); - VERIFY_PARAM_NOT_NULL(p_new_peer_id); - - memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); - - // Search through existing bonds to look for a duplicate. - pds_peer_data_iterate_prepare(); - - // @note emdi: should maybe use a critical section, since data is not copied while iterating. - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_is_duplicate_bonding_data(p_bonding_data, peer_data.p_bonding_data)) - { - *p_new_peer_id = peer_id; - return NRF_SUCCESS; - } - } - - // If no duplicate data is found, prepare to write a new bond to flash. - - *p_new_peer_id = pdb_peer_allocate(); - - if (*p_new_peer_id == PM_PEER_ID_INVALID) - { - return NRF_ERROR_NO_MEM; - } - - memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); - - peer_data.data_id = PM_PEER_DATA_ID_BONDING; - peer_data.p_bonding_data = p_bonding_data; - peer_data.length_words = BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)); - - err_code = pdb_raw_store(*p_new_peer_id, &peer_data, p_token); - - if (err_code != NRF_SUCCESS) - { - if (im_peer_free(*p_new_peer_id) != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - // NRF_ERROR_STORAGE_FULL, if no space in flash. - // NRF_ERROR_BUSY, if flash filesystem was busy. - // NRF_ERROR_INTENRAL, on internal error. - return err_code; - } - - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_delete(pm_peer_id_t peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - - return im_peer_free(peer_id); -} - - -ret_code_t pm_peers_delete(void) -{ - VERIFY_MODULE_INITIALIZED(); - - m_deleting_all = true; - - pm_peer_id_t current_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - - if (current_peer_id == PM_PEER_ID_INVALID) - { - // No peers bonded. - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - - evt_send(&pm_delete_all_evt); - } - - while (current_peer_id != PM_PEER_ID_INVALID) - { - ret_code_t err_code = pm_peer_delete(current_peer_id); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - current_peer_id = pdb_next_peer_id_get(current_peer_id); - } - - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, - uint32_t * p_highest_rank, - pm_peer_id_t * p_lowest_ranked_peer, - uint32_t * p_lowest_rank) -{ - VERIFY_MODULE_INITIALIZED(); - - pm_peer_id_t peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - uint32_t peer_rank = 0; - //lint -save -e65 -e64 - pm_peer_data_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(peer_rank)), - .p_peer_rank = &peer_rank}; - //lint -restore - ret_code_t err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); - uint32_t highest_rank = 0; - uint32_t lowest_rank = 0xFFFFFFFF; - pm_peer_id_t highest_ranked_peer = PM_PEER_ID_INVALID; - pm_peer_id_t lowest_ranked_peer = PM_PEER_ID_INVALID; - - if (err_code == NRF_ERROR_INVALID_PARAM) - { - // No peer IDs exist. - return NRF_ERROR_NOT_FOUND; - } - - while ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)) - { - if (err_code == NRF_ERROR_NOT_FOUND) - { - peer_rank = 0; - } - if (peer_rank >= highest_rank) - { - highest_rank = peer_rank; - highest_ranked_peer = peer_id; - } - if (peer_rank < lowest_rank) - { - lowest_rank = peer_rank; - lowest_ranked_peer = peer_id; - } - peer_id = pdb_next_peer_id_get(peer_id); - err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); - } - if (peer_id == PM_PEER_ID_INVALID) - { - err_code = NRF_SUCCESS; - if (p_highest_ranked_peer != NULL) - { - *p_highest_ranked_peer = highest_ranked_peer; - } - if (p_highest_rank != NULL) - { - *p_highest_rank = highest_rank; - } - if (p_lowest_ranked_peer != NULL) - { - *p_lowest_ranked_peer = lowest_ranked_peer; - } - if (p_lowest_rank != NULL) - { - *p_lowest_rank = lowest_rank; - } - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - return err_code; -} - - -/**@brief Function for initializing peer rank functionality. - */ -static void rank_init(void) -{ - rank_vars_update(); -} - - -ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - //lint -save -e65 -e64 - pm_peer_data_flash_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(m_current_highest_peer_rank)), - .data_id = PM_PEER_DATA_ID_PEER_RANK, - .p_peer_rank = &m_current_highest_peer_rank}; - //lint -restore - - - if (!m_peer_rank_initialized) - { - rank_init(); - } - - if (!m_peer_rank_initialized || (m_peer_rank_token != PM_STORE_TOKEN_INVALID)) - { - err_code = NRF_ERROR_BUSY; - } - else - { - if ((peer_id == m_highest_ranked_peer) && (m_current_highest_peer_rank > 0)) - { - pm_evt_t pm_evt; - - // The reported peer is already regarded as highest (provided it has an index at all) - err_code = NRF_SUCCESS; - - memset(&pm_evt, 0, sizeof(pm_evt)); - pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; - pm_evt.conn_handle = im_conn_handle_get(peer_id); - pm_evt.peer_id = peer_id; - pm_evt.params.peer_data_update_succeeded.data_id = PM_PEER_DATA_ID_PEER_RANK; - pm_evt.params.peer_data_update_succeeded.action = PM_PEER_DATA_OP_UPDATE; - pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - pm_evt.params.peer_data_update_succeeded.flash_changed = false; - - evt_send(&pm_evt); - } - else - { - m_current_highest_peer_rank += 1; - err_code = pdb_raw_store(peer_id, &peer_data, &m_peer_rank_token); - if (err_code != NRF_SUCCESS) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_current_highest_peer_rank -= 1; - { - if ((err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_STORAGE_FULL)) - err_code = NRF_ERROR_INTERNAL; - } - } - } - } - return err_code; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h deleted file mode 100644 index b8a65f098f..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h +++ /dev/null @@ -1,765 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file peer_manager.h - * - * @defgroup peer_manager Peer Manager - * @ingroup ble_sdk_lib - * @{ - * @brief Module for managing BLE bonding, which includes controlling encryption and pairing - * procedures as well as persistently storing different pieces of data that must be stored - * when bonded. - * - * @details The API consists of functions for configuring the pairing and encryption behavior of the - * device and functions for manipulating the stored data. - * - * This module uses Flash Data Storage (FDS) to interface with persistent storage. The - * Peer Manager needs exclusive use of certain FDS file IDs and record keys. See - * @ref lib_fds_functionality_keys for more information. - */ - - -#ifndef PEER_MANAGER_H__ -#define PEER_MANAGER_H__ - -#include -#include -#include "sdk_common.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_database.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/**@brief Security status of a connection. - */ -typedef struct -{ - uint8_t connected : 1; /**< @brief The connection is active (not disconnected). */ - uint8_t encrypted : 1; /**< @brief Communication on this link is encrypted. */ - uint8_t mitm_protected : 1; /**< @brief The encrypted communication is also protected against man-in-the-middle attacks. */ - uint8_t bonded : 1; /**< @brief The peer is bonded with us. */ -} pm_conn_sec_status_t; - - -/**@brief Function for initializing the Peer Manager. - * - * @details You must initialize the Peer Manager before you can call any other Peer Manager - * functions. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_init(void); - - -/**@brief Function for registering an event handler with the Peer Manager. - * - * @param[in] event_handler Callback for events from the @ref peer_manager module. @p event_handler - * is called for every event that the Peer Manager sends after this - * function is called. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_NULL If @p event_handler was NULL. - * @retval NRF_ERROR_NO_MEM If no more registrations can happen. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_register(pm_evt_handler_t event_handler); - - -/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. - * - * @details Until this function is called, all bonding procedures that are initiated by the - * peer are rejected. - * - * This function can be called multiple times with different parameters, even with NULL as - * @p p_sec_params, in which case the Peer Manager starts rejecting all procedures again. - * - * @param[in] p_sec_params Security parameters to be used for subsequent security procedures. - * - * @retval NRF_SUCCESS If the parameters were set successfully. - * @retval NRF_ERROR_INVALID_PARAM If the combination of parameters is invalid. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params); - - -/**@brief Function for establishing encryption on a connection, and optionally establishing a bond. - * - * @details This function attempts to secure the link that is specified by @p conn_handle. It uses - * the parameters that were previously provided in a call to @ref pm_sec_params_set. - * - * If the connection is a master connection, calling this function starts a security - * procedure on the link. If we have keys from a previous bonding procedure with this peer - * and the keys meet the security requirements in the currently active security parameters, - * the function attempts to establish encryption with the existing keys. If no key exists, - * the function attempts to perform pairing and bonding according to the currently active - * security parameters. - * - * If the function completes successfully, a @ref PM_EVT_CONN_SEC_START event is sent. - * The procedure might be queued, in which case the @ref PM_EVT_CONN_SEC_START event is - * delayed until the procedure is initiated in the SoftDevice. - * - * If the connection is a slave connection, the function sends a security request to - * the peer (master). It is up to the peer then to initiate pairing or encryption. - * If the peer ignores the request, a @ref BLE_GAP_EVT_TIMEOUT event occurs - * with the source @ref BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST. Otherwise, the peer initiates - * security, in which case things happen as if the peer had initiated security itself. - * See @ref PM_EVT_CONN_SEC_START for information about peer-initiated security. - * - * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. - * @param[in] force_repairing Whether to force a pairing procedure even if there is an existing - * encryption key. This argument is relevant only for - * the central role. Recommended value: false. - * - * @retval NRF_SUCCESS If the operation completed successfully. - * @retval NRF_ERROR_TIMEOUT If there was an SMP time-out, so that no more security - * operations can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. - * @retval NRF_ERROR_NOT_FOUND If the security parameters have not been set, either by - * @ref pm_sec_params_set or by @ref pm_conn_sec_params_reply. - * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. - * @retval NRF_ERROR_NO_MEM If no more authentication procedures can run in parallel - * for the given role. See @ref sd_ble_gap_authenticate. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized, or the peer is - * disconnected or in the process of disconnecting. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing security parameters for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, the parameters given in @ref pm_sec_params_set are used. See @ref - * pm_conn_sec_config_t for the value of the default. - * - * @param[in] conn_handle The connection to set the parameters for. - * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. - * @param[in] p_context The context found in the request event that this function replies to. - * - * @retval NRF_SUCCESS Successful reply. - * @retval NRF_ERROR_NULL p_sec_params or p_context was null. - * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context); - - -/**@brief Function for manually informing that the local database has changed. - * - * @details This function sends a service changed indication to all bonded and/or connected peers - * that subscribe to this indication. If a bonded peer is not connected, the indication is - * sent when it reconnects. Every time an indication is sent, a @ref - * PM_EVT_SERVICE_CHANGED_IND_SENT event occurs, followed by a @ref - * PM_EVT_SERVICE_CHANGED_IND_CONFIRMED when the peer sends its confirmation. Peers that - * are not subscribed to the service changed indication when this function is called do not - * receive an indication, and no events are sent to the user. Likewise, if the service - * changed characteristic is not present in the local database, this no indications are - * sent peers, and no events are sent to the user. - */ -void pm_local_database_has_changed(void); - - -/**@brief Function for getting the security status of a connection. - * - * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. - * @param[out] p_conn_sec_status Security status of the link. - * - * @retval NRF_SUCCESS If pairing was initiated successfully. - * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. - * @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status); - - -/**@brief Experimental function for specifying the public key to use for LESC operations. - * - * @details This function can be called multiple times. The specified public key will be used for - * all subsequent LESC (LE Secure Connections) operations until the next time this function - * is called. - * - * @note The key must continue to reside in application memory as it is not copied by Peer Manager. - * - * @param[in] p_public_key The public key to use for all subsequent LESC operations. - * - * @retval NRF_SUCCESS If pairing was initiated successfully. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); - - -/**@brief Function for setting or clearing the whitelist. - * - * When using the S13x SoftDevice v3.x, this function sets or clears the whitelist. - * When using the S13x SoftDevice v2.x, this function caches a list of - * peers that can be retrieved later by @ref pm_whitelist_get to pass to the @ref lib_ble_advertising. - * - * To clear the current whitelist, pass either NULL as @p p_peers or zero as @p peer_cnt. - * - * @param[in] p_peers The peers to add to the whitelist. Pass NULL to clear the current whitelist. - * @param[in] peer_cnt The number of peers to add to the whitelist. The number must not be greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. Pass zero to clear the current - * whitelist. - * - * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. - * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is already in use and cannot be set. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer in @p p_peers has an address that cannot - * be used for whitelisting. - * @retval NRF_ERROR_NOT_FOUND If any of the peers in @p p_peers cannot be found. - * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/**@brief Function for retrieving the previously set whitelist. - * - * The function retrieves the whitelist of GAP addresses and IRKs that was - * previously set by @ref pm_whitelist_set. - * - * To retrieve only GAP addresses or only IRKs, provide only one of the - * buffers. If a buffer is provided, its size must be specified. - * - * @param[out] p_addrs The buffer where to store GAP addresses. Pass NULL to retrieve - * only IRKs (in that case, @p p_irks must not be NULL). - * @param[in,out] p_addr_cnt In: The size of the @p p_addrs buffer. - * May be NULL if and only if @p p_addrs is NULL. - * Out: The number of GAP addresses copied into the buffer. - * If @p p_addrs is NULL, this parameter remains unchanged. - * @param[out] p_irks The buffer where to store IRKs. Pass NULL to retrieve - * only GAP addresses (in that case, @p p_addrs must not NULL). - * @param[in,out] p_irk_cnt In: The size of the @p p_irks buffer. - * May be NULL if and only if @p p_irks is NULL. - * Out: The number of IRKs copied into the buffer. - * If @p p_irks is NULL, this paramater remains unchanged. - * - * @retval NRF_SUCCESS If the whitelist was successfully retrieved. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be used for - * whitelisting (this error can occur only - * when using the S13x SoftDevice v2.x). - * @retval NRF_ERROR_NULL If a required parameter is NULL. - * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. - * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers - * cannot be found. It might have been deleted. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt); - - -/**@brief Function for setting and clearing the device identities list. - * - * @param[in] p_peers The peers to add to the device identities list. Pass NULL to clear - * the device identities list. - * @param[in] peer_cnt The number of peers. Pass zero to clear the device identities list. - * - * @retval NRF_SUCCESS If the device identities list was successfully - * set or cleared. - * @retval NRF_ERROR_NOT_FOUND If a peer is invalid or its data could not - * be found in flash. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be - * used for whitelisting. - * @retval BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE If the device identities list is in use and - * cannot be set. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_NOT_SUPPORTED If using a SoftDevice that does not support - * device identities, e.g. S130 v2.0. - */ -ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/**@brief Function for setting the local Bluetooth identity address. - * - * @details The local Bluetooth identity address is the address that identifies the device - * to other peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are running. - * - * The SoftDevice sets a default address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC when it is - * enabled. This default address is a random number that is populated during the IC manufacturing - * process. It remains unchanged for the lifetime of each IC, but the application can use this - * function to assign a different identity address. - * - * The identity address is distributed to the peer during bonding. Changing the identity address - * means bonded devices might not recognize us. - * - * - * @param[in] p_addr The GAP address to be set. - * - * @retval NRF_SUCCESS If the identity address was set successfully. - * @retval NRF_ERROR_NULL If @p p_addr is NULL. - * @retval NRF_ERROR_INVALID_ADDR If the @p p_addr pointer is invalid. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address is invalid. - * @retval NRF_ERROR_BUSY If the SoftDevice was busy. Process SoftDevice events - * and retry. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized or if this function - * was called while advertising, scanning, or while connected. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr); - - -/**@brief Function for retrieving the local Bluetooth identity address. - * - * This function always returns the identity address, irrespective of the privacy settings. - * This means that the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. - * - * @param[out] p_addr Pointer to the address structure to be filled in. - * - * @retval NRF_SUCCESS If the address was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_addr is NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr); - - -/**@brief Function for configuring privacy settings. - * - * The privacy settings cannot be configured while advertising, scanning, or while in a connection. - * - * @note The SoftDevice functions @ref sd_ble_gap_addr_set - * and @ref sd_ble_gap_privacy_set must not be called when using the Peer Manager. - * Use this function instead. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If the privacy settings were configured successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. - * @retval NRF_ERROR_BUSY If the operation could not be performed at this time. - * Process SoftDevice events and retry. - * @retval NRF_ERROR_INVALID_PARAM If the address type is invalid. - * @retval NRF_ERROR_INVALID_STATE If this function is called while BLE roles using - * privacy are enabled. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params); - - -/**@brief Function for retrieving privacy settings. - * - * The privacy settings that are returned include the current IRK as well. - * - * @param[out] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If the privacy settings were retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params or @p p_privacy_params->p_device_irk is - * NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params); - - -/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). - * - * @param[in] p_addr A private random resolvable address. - * @param[in] p_irk An identity resolution key (IRK). - * - * @retval true The IRK used matched the one used to create the address. - * @retval false The IRK used did not match the one used to create the address, or an argument was - * NULL or invalid. - */ -bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - - -/**@brief Function for getting the connection handle of the connection with a bonded peer. - * - * @param[in] peer_id The peer ID of the bonded peer. - * @param[out] p_conn_handle Connection handle, or @ref BLE_ERROR_INVALID_CONN_HANDLE if the peer - * is not connected. - * - * @retval NRF_SUCCESS If the connection handle was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_conn_handle was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle); - - -/**@brief Function for retrieving the ID of a peer, given its connection handle. - * - * @param[in] conn_handle The connection handle of the peer. - * @param[out] p_peer_id The peer ID, or @ref PM_PEER_ID_INVALID if the peer is not bonded or - * @p conn_handle does not refer to a valid connection. - * - * @retval NRF_SUCCESS If the peer ID was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_peer_id was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. - * - * @details This function can be used to loop through all used peer IDs. The order in which - * peer IDs are returned should be considered unpredictable. @ref PM_PEER_ID_INVALID - * is considered to be before the first and after the last used peer ID. - * - * @details To loop through all peer IDs exactly once, use the following constuct: - * @code{c} - * pm_peer_id_t current_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - * while (current_peer_id != PM_PEER_ID_INVALID) - * { - * // Do something with current_peer_id. - * current_peer_id = pm_next_peer_id_get(current_peer_id) - * } - * @endcode - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. If @p prev_peer_id was @ref PM_PEER_ID_INVALID, the - * next peer ID is the first used peer ID. If @p prev_peer_id was the last - * used peer ID, the function returns @ref PM_PEER_ID_INVALID. - */ -pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs that are available. - * - * @details This function returns the number of peers for which there is data in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pm_peer_count(void); - - - - -/**@anchor PM_PEER_DATA_FUNCTIONS - * @name Functions (Peer Data) - * Functions for manipulating peer data. - * @{ - */ - -/** - * @{ - */ - -/**@brief Function for retrieving stored data of a peer. - * - * @note The length of the provided buffer must be a multiple of 4. - * - * @param[in] peer_id Peer ID to get data for. - * @param[in] data_id Which type of data to read. - * @param[out] p_data Where to put the retrieved data. The documentation for - * @ref pm_peer_data_id_t specifies what data type each data ID is stored as. - * @param[inout] p_len In: The length in bytes of @p p_data. - * Out: The length in bytes of the read data, if the read was successful. - * - * @retval NRF_SUCCESS If the data was read successfully. - * @retval NRF_ERROR_INVALID_PARAM If the the data type or the peer ID was invalid or unallocated, - * or if the length in @p p_length was not a multiple of 4. - * @retval NRF_ERROR_NULL If a pointer parameter was NULL. - * @retval NRF_ERROR_NOT_FOUND If no stored data was found for this peer ID/data ID combination. - * @retval NRF_ERROR_DATA_SIZE If the provided buffer was not large enough. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void * p_data, - uint16_t * p_len); - -/**@brief Function for reading a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, - pm_peer_data_bonding_t * p_data); - -/**@brief Function for reading a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, - ble_gatt_db_srv_t * p_data, - uint16_t * p_len); - -/**@brief Function for reading a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, - void * p_data, - uint16_t * p_len); -/** @}*/ - - -/** - * @{ - */ - -/**@brief Function for setting or updating stored data of a peer. - * - * @note Writing the data to persistent storage happens asynchronously. Therefore, the buffer - * that contains the data must be kept alive until the operation has completed. - * - * @note The data written using this function might later be overwritten as a result of internal - * operations in the Peer Manager. A Peer Manager event is sent each time data is updated, - * regardless of whether the operation originated internally or from action by the user. - * - * @param[in] peer_id Peer ID to set data for. - * @param[in] data_id Which type of data to set. - * @param[in] p_data New value to set. The documentation for @ref pm_peer_data_id_t specifies - * what data type each data ID should be stored as. - * @param[in] len The length in bytes of @p p_data. - * @param[out] p_token A token that identifies this particular store operation. The token can be - * used to identify events that pertain to this operation. This parameter can - * be NULL. - * - * @retval NRF_SUCCESS If the data is scheduled to be written to persistent storage. - * @retval NRF_ERROR_NULL If @p p_data is NULL. - * @retval NRF_ERROR_NOT_FOUND If no peer was found for the peer ID. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void const * p_data, - uint16_t len, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, - pm_peer_data_bonding_t const * p_data, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, - ble_gatt_db_srv_t const * p_data, - uint16_t len, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, - void const * p_data, - uint16_t len, - pm_store_token_t * p_token); -/** @}*/ - - -/** - * @{ - */ - -/**@brief Function for deleting a peer's stored pieces of data. - * - * @details This function deletes specific data that is stored for a peer. Note that bonding data - * cannot be cleared separately. - * - * To delete all data for a peer (including bonding data), use @ref pm_peer_delete. - * - * @note Clearing data in persistent storage happens asynchronously. - * - * @param[in] peer_id Peer ID to clear data for. - * @param[in] data_id Which data to clear. - * - * @retval NRF_SUCCESS If the clear procedure was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p data_id was PM_PEER_DATA_ID_BONDING or invalid, or - * @p peer_id was invalid. - * @retval NRF_ERROR_NOT_FOUND If there was no data to clear for this peer ID/data ID combination. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for manually adding a peer to the persistent storage. - * - * @details This function allocates a new peer ID and stores bonding data for the new peer. The - * bonding data is necessary to prevent ambiguity/inconsistency in peer data. - * - * @param[in] p_bonding_data The bonding data of the new peer (must contain a public/static - * address or a non-zero IRK). - * @param[out] p_new_peer_id Peer ID for the new peer, or an existing peer if a match was found. - * @param[out] p_token A token that identifies this particular store operation (storing the - * bonding data). The token can be used to identify events that pertain - * to this operation. This parameter can be NULL. - * - * @retval NRF_SUCCESS If the store operation for bonding data was initiated successfully. - * @retval NRF_ERROR_NULL If @p p_bonding_data or @p p_new_peer_id is NULL. - * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. - * @retval NRF_ERROR_NO_MEM If there are no more available peer IDs. - * @retval NRF_ERROR_BUSY If the underlying flash filesystem is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, - pm_peer_data_bonding_t * p_bonding_data, - pm_store_token_t * p_token); - - -/**@brief Function for freeing persistent storage for a peer. - * - * @details This function deletes every piece of data that is associated with the specified peer and - * frees the peer ID to be used for another peer. The deletion happens asynchronously, and - * the peer ID is not freed until the data is deleted. When the operation finishes, a @ref - * PM_EVT_PEER_DELETE_SUCCEEDED or @ref PM_EVT_PEER_DELETE_FAILED event is sent. - * - * @warning Use this function only when not connected to or connectable for the peer that is being - * deleted. If the peer is or becomes connected or data is manually written in flash during - * this procedure (until the success or failure event happens), the behavior is undefined. - * - * @param[in] peer_id Peer ID to be freed and have all associated data deleted. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If the peer ID was not valid. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_delete(pm_peer_id_t peer_id); - - -/**@brief Function for deleting all data stored for all peers. - * - * @details This function sends either a @ref PM_EVT_PEERS_DELETE_SUCCEEDED or a @ref - * PM_EVT_PEERS_DELETE_FAILED event. In addition, a @ref PM_EVT_PEER_DELETE_SUCCEEDED or - * @ref PM_EVT_PEER_DELETE_FAILED event is sent for each deleted peer. - * - * @note When there is no peer data in flash the @ref PM_EVT_PEER_DELETE_SUCCEEDED event is sent synchronously. - * - * @warning Use this function only when not connected or connectable. If a peer is or becomes - * connected or a @ref PM_PEER_DATA_FUNCTIONS function is used during this procedure (until - * the success or failure event happens), the behavior is undefined. - * - * @retval NRF_SUCCESS If the deletion process was initiated successfully. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peers_delete(void); -/** @}*/ - - -/** - * @{ - */ - - -/**@brief Function for finding the highest and lowest ranked peers. - * - * @details The rank is saved in persistent storage under the data ID @ref PM_PEER_DATA_ID_PEER_RANK. - * - * @details The interpretation of rank is up to the user, because the rank is only updated by - * calling @ref pm_peer_rank_highest or by manipulating the value using a @ref - * PM_PEER_DATA_FUNCTIONS function. - * - * @note Any argument that is NULL is ignored. - * - * @param[out] p_highest_ranked_peer The peer ID with the highest rank of all peers, for example, - * the most recently used peer. - * @param[out] p_highest_rank The highest rank. - * @param[out] p_lowest_ranked_peer The peer ID with the lowest rank of all peers, for example, - * the least recently used peer. - * @param[out] p_lowest_rank The lowest rank. - * - * @retval NRF_SUCCESS If the operation completed successfully. - * @retval NRF_ERROR_NOT_FOUND If no peers were found. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, - uint32_t * p_highest_rank, - pm_peer_id_t * p_lowest_ranked_peer, - uint32_t * p_lowest_rank); - - -/**@brief Function for updating the rank of a peer to be highest among all stored peers. - * - * @details If this function returns @ref NRF_SUCCESS, either a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or a - * @ref PM_EVT_PEER_DATA_UPDATE_FAILED event is sent with a @ref - * PM_STORE_TOKEN_INVALID store token when the operation is complete. Until the operation - * is complete, this function returns @ref NRF_ERROR_BUSY. - * - * When the operation is complete, the peer is the highest ranked peer as reported by - * @ref pm_peer_ranks_get. - * - * @note The @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event can arrive before the function returns if the peer - * is already ranked highest. In this case, the @ref pm_peer_data_update_succeeded_evt_t::flash_changed flag - * in the event will be false. - * - * @param[in] peer_id The peer to rank highest. - * - * @retval NRF_SUCCESS If the peer's rank is, or will be updated to be highest. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations, or if a previous call to this function has not - * completed. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id); - -/** @}*/ - -/** @} */ - -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif // PEER_MANAGER_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h deleted file mode 100644 index f3299d0a1e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_MANAGER_INTERNAL_H__ -#define PEER_MANAGER_INTERNAL_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @file peer_manager_types.h - * - * @addtogroup peer_manager - * @brief File containing definitions used solely inside the Peer Manager's modules. - * @{ - */ - -ANON_UNIONS_ENABLE - -/**@brief One piece of data associated with a peer, together with its type. - * - * @note This type is deprecated. - */ -typedef struct -{ - uint16_t length_words; /**< @brief The length of the data in words. */ - pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ - union - { - pm_peer_data_bonding_t * p_bonding_data; /**< @brief The exchanged bond information in addition to metadata of the bonding. */ - uint32_t * p_peer_rank; /**< @brief A value locally assigned to this peer. Its interpretation is up to the user. The rank is not set automatically by the Peer Manager, but it is assigned by the user using either @ref pm_peer_rank_highest or a @ref PM_PEER_DATA_FUNCTIONS function. */ - bool * p_service_changed_pending; /**< @brief Whether a service changed indication should be sent to the peer. */ - pm_peer_data_local_gatt_db_t * p_local_gatt_db; /**< @brief Persistent information pertaining to a peer GATT client. */ - ble_gatt_db_srv_t * p_remote_gatt_db; /**< @brief Persistent information pertaining to a peer GATT server. */ - uint8_t * p_application_data; /**< @brief Arbitrary data to associate with the peer. This data can be freely used by the application. */ - void * p_all_data; /**< @brief Generic access pointer to the data. It is used only to handle the data without regard to type. */ - }; /**< @brief The data. */ -} pm_peer_data_t; - - -/**@brief Immutable version of @ref pm_peer_data_t. - * - * @note This type is deprecated. - */ -typedef struct -{ - uint16_t length_words; /**< @brief The length of the data in words. */ - pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ - union - { - pm_peer_data_bonding_t const * p_bonding_data; /**< @brief Immutable @ref pm_peer_data_t::p_bonding_data. */ - uint32_t const * p_peer_rank; /**< @brief Immutable @ref pm_peer_data_t::p_peer_rank. */ - bool const * p_service_changed_pending; /**< @brief Immutable @ref pm_peer_data_t::p_service_changed_pending. */ - pm_peer_data_local_gatt_db_t const * p_local_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_local_gatt_db. */ - ble_gatt_db_srv_t const * p_remote_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_remote_gatt_db. */ - uint8_t const * p_application_data; /**< @brief Immutable @ref pm_peer_data_t::p_application_data. */ - void const * p_all_data; /**< @brief Immutable @ref pm_peer_data_t::p_all_data. */ - }; /**< @brief The data. */ -} pm_peer_data_const_t; - -ANON_UNIONS_DISABLE - - -/**@brief Version of @ref pm_peer_data_t that reflects the structure of peer data in flash. - * - * @note This type is deprecated. - */ -typedef pm_peer_data_const_t pm_peer_data_flash_t; - - -/**@brief Event handler for events from the @ref peer_manager module. - * - * @sa pm_register - * - * @param[in] p_event The event that has occurred. - */ -typedef void (*pm_evt_handler_internal_t)(pm_evt_t * p_event); - - -/**@brief Macro for calculating the flash size of bonding data. - * - * @return The number of words that the data takes in flash. - */ -#define PM_BONDING_DATA_N_WORDS() BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)) - - -/**@brief Macro for calculating the flash size of service changed pending state. - * - * @return The number of words that the data takes in flash. - */ -#define PM_SC_STATE_N_WORDS() BYTES_TO_WORDS(sizeof(bool)) - - -/**@brief Macro for calculating the flash size of local GATT database data. - * - * @param[in] local_db_len The length, in bytes, of the database as reported by the SoftDevice. - * - * @return The number of words that the data takes in flash. - */ -#define PM_LOCAL_DB_N_WORDS(local_db_len) \ - BYTES_TO_WORDS((local_db_len) + PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - - -/**@brief Macro for calculating the length of a local GATT database attribute array. - * - * @param[in] n_words The number of words that the data takes in flash. - * - * @return The length of the database attribute array. - */ -#define PM_LOCAL_DB_LEN(n_words) (((n_words) * BYTES_PER_WORD) - PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - - -/**@brief Macro for calculating the flash size of remote GATT database data. - * - * @param[in] service_count The number of services in the service array. - * - * @return The number of words that the data takes in flash. - */ -#define PM_REMOTE_DB_N_WORDS(service_count) BYTES_TO_WORDS(sizeof(ble_gatt_db_srv_t) * (service_count)) - - -/**@brief Macro for calculating the flash size of remote GATT database data. - * - * @param[in] n_words The length in number of words. - * - * @return The number of words that the data takes in flash. - */ -#define PM_REMOTE_DB_N_SERVICES(n_words) (((n_words) * BYTES_PER_WORD) / sizeof(ble_gatt_db_srv_t)) - - -/**@brief Function for calculating the flash size of the usage index. - * - * @return The number of words that the data takes in flash. - */ -#define PM_USAGE_INDEX_N_WORDS() BYTES_TO_WORDS(sizeof(uint32_t)) - -/** @} - * @endcond - */ - - -#ifdef NRF_PM_DEBUG - - #define NRF_PM_DEBUG_CHECK(condition) \ - if (!(condition)) \ - { \ - __asm("bkpt #0"); \ - } - -#else - - // Prevent "variable set but never used" compiler warnings. - #define NRF_PM_DEBUG_CHECK(condition) (void)(condition) - -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_MANAGER_INTERNAL_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h deleted file mode 100644 index 8c699839fb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h +++ /dev/null @@ -1,377 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file peer_manager_types.h - * - * @addtogroup peer_manager - * @{ - */ - -#ifndef PEER_MANAGER_TYPES_H__ -#define PEER_MANAGER_TYPES_H__ - -#include -#include -#include -#include "nrf.h" -#include "ble_gap.h" -#include "ble_hci.h" -#include "ble_gatt_db.h" -#include "app_util.h" -#include "app_util_platform.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Handle to uniquely identify a peer for which we have persistently stored data. - */ -typedef uint16_t pm_peer_id_t; - -/**@brief Type that is used for write prepares (used to reserve space in flash). - */ -typedef uint32_t pm_prepare_token_t; - -/**@brief Type that is used to hold a reference to a stored item in flash. - */ -typedef uint32_t pm_store_token_t; - -/**@brief Errors from security procedures in Peer Manager. - * - * @details Possible values are defined in @ref PM_SEC_ERRORS and @ref BLE_GAP_SEC_STATUS. - */ -typedef uint16_t pm_sec_error_code_t; - - -//lint -emacro(516,PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - -#define PM_PEER_ID_INVALID 0xFFFF /**< @brief Invalid value for @ref pm_peer_id_t. */ -#define PM_STORE_TOKEN_INVALID 0 /**< @brief Invalid value for store token. */ -#define PM_PEER_ID_N_AVAILABLE_IDS 256 /**< @brief The number of available peer IDs. */ -#define PM_LOCAL_DB_LEN_OVERHEAD_BYTES offsetof(pm_peer_data_local_gatt_db_t, data) /**< @brief The static-length part of the local GATT data struct. */ - - -#define PM_CONN_SEC_ERROR_BASE 0x1000 /**< @brief The base for Peer Manager defined errors. See @ref PM_SEC_ERRORS and @ref pm_sec_error_code_t. */ - - -/**@defgroup PM_SEC_ERRORS Peer Manager defined security errors - * - * @details The first 256 numbers in this range correspond to the status codes in - * @ref BLE_HCI_STATUS_CODES. - * @{ */ -#define PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING (PM_CONN_SEC_ERROR_BASE + 0x06) /**< @brief Encryption failed because the peripheral has lost the LTK for this bond. See also @ref BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING and Table 3.7 ("Pairing Failed Reason Codes") in the Bluetooth Core Specification 4.2, section 3.H.3.5.5 (@linkBLEcore). */ -#define PM_CONN_SEC_ERROR_MIC_FAILURE (PM_CONN_SEC_ERROR_BASE + 0x3D) /**< @brief Encryption ended with disconnection because of mismatching keys or a stray packet during a procedure. See the SoftDevice GAP Message Sequence Charts on encryption (@linkBLEMSCgap), the Bluetooth Core Specification 4.2, sections 6.B.5.1.3.1 and 3.H.3.5.5 (@linkBLEcore), and @ref BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE. */ -#define PM_CONN_SEC_ERROR_DISCONNECT (PM_CONN_SEC_ERROR_BASE + 0x100) /**< @brief Pairing or encryption did not finish before the link disconnected for an unrelated reason. */ -#define PM_CONN_SEC_ERROR_SMP_TIMEOUT (PM_CONN_SEC_ERROR_BASE + 0x101) /**< @brief Pairing/bonding could not start because an SMP time-out has already happened on this link. This means that no more pairing or bonding can happen on this link. To be able to pair or bond, the link must be disconnected and then reconnected. See Bluetooth Core Specification 4.2 section 3.H.3.4 (@linkBLEcore). */ - /** @} */ - - - -/**@defgroup PM_PEER_ID_VERSIONS All versions of Peer IDs. - * @brief The data ID for each iteration of the data formats in flash. - * @details Each time the format (in flash) of a piece of peer data changes, the data ID will also - * be updated. This list of defines is a record of each data ID that has ever existed, and - * code that caters to legacy formats can find the relevant IDs here. - * @{ */ -#define PM_PEER_DATA_ID_FIRST_VX 0 /**< @brief The smallest data ID. */ -#define PM_PEER_DATA_ID_BONDING_V1 0 /**< @brief The data ID of the first version of bonding data. */ -#define PM_PEER_DATA_ID_BONDING_V2 7 /**< @brief The data ID of the second version of bonding data. */ -#define PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1 1 /**< @brief The data ID of the first version of the service changed pending flag. */ -#define PM_PEER_DATA_ID_GATT_LOCAL_V1 2 /**< @brief The data ID of the first version of local GATT data. */ -#define PM_PEER_DATA_ID_GATT_LOCAL_V2 8 /**< @brief The data ID of the second version of local GATT data. */ -#define PM_PEER_DATA_ID_GATT_REMOTE_V1 3 /**< @brief The data ID of the first version of remote GATT data. */ -#define PM_PEER_DATA_ID_APPLICATION_V1 4 /**< @brief The data ID of the first version of application data. */ -#define PM_PEER_DATA_ID_GATT_REMOTE_V2 5 /**< @brief The data ID of the second version of remote GATT data. */ -#define PM_PEER_DATA_ID_PEER_RANK_V1 6 /**< @brief The data ID of the first version of the rank. */ -#define PM_PEER_DATA_ID_LAST_VX 9 /**< @brief The data ID after the last valid one. */ -#define PM_PEER_DATA_ID_INVALID_VX 0xFF /**< @brief A data ID guaranteed to be invalid. */ -/**@}*/ - - -/**@brief The different types of data associated with a peer. - */ -typedef enum -{ - PM_PEER_DATA_ID_FIRST = PM_PEER_DATA_ID_FIRST_VX, /**< @brief The smallest data ID. */ - PM_PEER_DATA_ID_BONDING = PM_PEER_DATA_ID_BONDING_V2, /**< @brief The data ID for bonding data. Type: @ref pm_peer_data_bonding_t. */ - PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1, /**< @brief The data ID for service changed state. Type: bool. */ - PM_PEER_DATA_ID_GATT_LOCAL = PM_PEER_DATA_ID_GATT_LOCAL_V2, /**< @brief The data ID for local GATT data (sys attributes). Type: @ref pm_peer_data_local_gatt_db_t. */ - PM_PEER_DATA_ID_GATT_REMOTE = PM_PEER_DATA_ID_GATT_REMOTE_V2, /**< @brief The data ID for remote GATT data. Type: uint8_t array. */ - PM_PEER_DATA_ID_PEER_RANK = PM_PEER_DATA_ID_PEER_RANK_V1, /**< @brief The data ID for peer rank. See @ref pm_peer_rank_highest. Type: uint32_t. */ - PM_PEER_DATA_ID_APPLICATION = PM_PEER_DATA_ID_APPLICATION_V1, /**< @brief The data ID for application data. Type: uint8_t array. */ - PM_PEER_DATA_ID_LAST = PM_PEER_DATA_ID_LAST_VX, /**< @brief One more than the highest data ID. */ - PM_PEER_DATA_ID_INVALID = PM_PEER_DATA_ID_INVALID_VX, /**< @brief A data ID guaranteed to be invalid. */ -} pm_peer_data_id_t; - - -/**@brief Different procedures that can lead to an encrypted link. - */ -typedef enum -{ - PM_LINK_SECURED_PROCEDURE_ENCRYPTION, /**< @brief Using an LTK that was shared during a previous bonding procedure to encrypt the link. */ - PM_LINK_SECURED_PROCEDURE_BONDING, /**< @brief A pairing procedure, followed by a bonding procedure. */ - PM_LINK_SECURED_PROCEDURE_PAIRING, /**< @brief A pairing procedure with no bonding. */ -} pm_conn_sec_procedure_t; - - -/**@brief Configuration of a security procedure. - */ -typedef struct -{ - bool allow_repairing; /** @brief Whether to allow the peer to pair if it wants to, but is already bonded. If this is false, the procedure is rejected, and no more events are sent. Default: false. */ -} pm_conn_sec_config_t; - - -/**@brief Data associated with a bond to a peer. - */ -typedef struct -{ - uint8_t own_role; /**< @brief The BLE role of the local device during bonding. See @ref BLE_GAP_ROLES. */ - ble_gap_id_key_t peer_ble_id; /**< @brief The peer's Bluetooth address and identity resolution key (IRK). */ - ble_gap_enc_key_t peer_ltk; /**< @brief The peer's long-term encryption key (LTK) and master ID. */ - ble_gap_enc_key_t own_ltk; /**< @brief Locally generated long-term encryption key (LTK) and master ID, distributed to the peer. */ -} pm_peer_data_bonding_t; - - -/**@brief Data on a local GATT database. - */ -typedef struct -{ - uint32_t flags; /**< @brief Flags that describe the database attributes. */ - uint16_t len; /**< @brief Size of the attribute array. */ - uint8_t data[1]; /**< @brief Array to hold the database attributes. */ -} pm_peer_data_local_gatt_db_t; - - -/**@brief Device Privacy. - * - * The privacy feature provides a way for the device to avoid being tracked over a period of - * time. The privacy feature, when enabled, hides the local device identity and replaces it - * with a private address that is automatically refreshed at a specified interval. - * - * If a device still wants to be recognized by other peers, it needs to share it's Identity - * Resolving Key (IRK). With this key, a device can generate a random private address that - * can only be recognized by peers in possession of that key, and devices can establish - * connections without revealing their real identities. - * - * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all - * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. - * The IRK distributed during bonding procedure is the device IRK that is active when @ref - * sd_ble_gap_sec_params_reply is called. - */ -#if (NRF_SD_BLE_API_VERSION < 3) - -typedef struct -{ - uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ - uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ - uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ - ble_gap_irk_t * p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. - When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. - By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ -} pm_privacy_params_t; - - -/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes - * @{ */ -#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ -#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ -/**@} */ - -#else - -typedef ble_gap_privacy_params_t pm_privacy_params_t; - -#endif - - -/**@brief Types of events that can come from the @ref peer_manager module. - */ -typedef enum -{ - PM_EVT_BONDED_PEER_CONNECTED, /**< @brief A connected peer has been identified as one with which we have a bond. When performing bonding with a peer for the first time, this event will not be sent until a new connection is established with the peer. When we are central, this event is always sent when the Peer Manager receives the @ref BLE_GAP_EVT_CONNECTED event. When we are peripheral, this event might in rare cases arrive later. */ - PM_EVT_CONN_SEC_START, /**< @brief A security procedure has started on a link, initiated either locally or remotely. The security procedure is using the last parameters provided via @ref pm_sec_params_set. This event is always followed by either a @ref PM_EVT_CONN_SEC_SUCCEEDED or a @ref PM_EVT_CONN_SEC_FAILED event. This is an informational event; no action is needed for the procedure to proceed. */ - PM_EVT_CONN_SEC_SUCCEEDED, /**< @brief A link has been encrypted, either as a result of a call to @ref pm_conn_secure or a result of an action by the peer. The event structure contains more information about the circumstances. This event might contain a peer ID with the value @ref PM_PEER_ID_INVALID, which means that the peer (central) used an address that could not be identified, but it used an encryption key (LTK) that is present in the database. */ - PM_EVT_CONN_SEC_FAILED, /**< @brief A pairing or encryption procedure has failed. In some cases, this means that security is not possible on this link (temporarily or permanently). How to handle this error depends on the application. */ - PM_EVT_CONN_SEC_CONFIG_REQ, /**< @brief The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref pm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */ - PM_EVT_CONN_SEC_PARAMS_REQ, /**< @brief Security parameters (@ref ble_gap_sec_params_t) are needed for an ongoing security procedure. Reply with @ref pm_conn_sec_params_reply before the event handler returns. If no reply is sent, the parameters given in @ref pm_sec_params_set are used. If a peripheral connection, the central's sec_params will be available in the event. */ - PM_EVT_STORAGE_FULL, /**< @brief There is no more room for peer data in flash storage. To solve this problem, delete data that is not needed anymore and run a garbage collection procedure in FDS. */ - PM_EVT_ERROR_UNEXPECTED, /**< @brief An unrecoverable error happened inside Peer Manager. An operation failed with the provided error. */ - PM_EVT_PEER_DATA_UPDATE_SUCCEEDED, /**< @brief A piece of peer data was stored, updated, or cleared in flash storage. This event is sent for all successful changes to peer data, also those initiated internally in Peer Manager. To identify an operation, compare the store token in the event with the store token received during the initiating function call. Events from internally initiated changes might have invalid store tokens. */ - PM_EVT_PEER_DATA_UPDATE_FAILED, /**< @brief A piece of peer data could not be stored, updated, or cleared in flash storage. This event is sent instead of @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED for the failed operation. */ - PM_EVT_PEER_DELETE_SUCCEEDED, /**< @brief A peer was cleared from flash storage, for example because a call to @ref pm_peer_delete succeeded. This event can also be sent as part of a call to @ref pm_peers_delete or internal cleanup. */ - PM_EVT_PEER_DELETE_FAILED, /**< @brief A peer could not be cleared from flash storage. This event is sent instead of @ref PM_EVT_PEER_DELETE_SUCCEEDED for the failed operation. */ - PM_EVT_PEERS_DELETE_SUCCEEDED, /**< @brief A call to @ref pm_peers_delete has completed successfully. Flash storage now contains no peer data. */ - PM_EVT_PEERS_DELETE_FAILED, /**< @brief A call to @ref pm_peers_delete has failed, which means that at least one of the peers could not be deleted. Other peers might have been deleted, or might still be queued to be deleted. No more @ref PM_EVT_PEERS_DELETE_SUCCEEDED or @ref PM_EVT_PEERS_DELETE_FAILED events are sent until the next time @ref pm_peers_delete is called. */ - PM_EVT_LOCAL_DB_CACHE_APPLIED, /**< @brief Local database values for a peer (taken from flash storage) have been provided to the SoftDevice. */ - PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED, /**< @brief Local database values for a peer (taken from flash storage) were rejected by the SoftDevice, which means that either the database has changed or the user has manually set the local database to an invalid value (using @ref pm_peer_data_store). */ - PM_EVT_SERVICE_CHANGED_IND_SENT, /**< @brief A service changed indication has been sent to a peer, as a result of a call to @ref pm_local_database_has_changed. This event will be followed by a @ref PM_EVT_SERVICE_CHANGED_IND_CONFIRMED event if the peer acknowledges the indication. */ - PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< @brief A service changed indication that was sent has been confirmed by a peer. The peer can now be considered aware that the local database has changed. */ - PM_EVT_SLAVE_SECURITY_REQ, /**< @brief The peer (peripheral) has requested link encryption, which has been enabled. */ - PM_EVT_FLASH_GARBAGE_COLLECTED, /**< @brief The flash has been garbage collected (By FDS), possibly freeing up space. */ -} pm_evt_id_t; - - -/**@brief Events parameters specific to the @ref PM_EVT_CONN_SEC_START event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that has started. */ -} pm_conn_sec_start_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that led to securing the link. */ - bool data_stored; /**< @brief Whether bonding data was successfully requested to be stored. This is false if: No bonding happened, or an internal error occurred when trying to store the data, or if the data was rejected via @ref pm_conn_sec_config_reply. */ -} pm_conn_secured_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that failed. */ - pm_sec_error_code_t error; /**< @brief An error code that describes the failure. */ - uint8_t error_src; /**< @brief The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ -} pm_conn_secure_failed_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. - */ -typedef struct -{ - ble_gap_sec_params_t const * p_peer_params; /**< @brief Peer security parameters, if role is peripheral. Otherwise, this is NULL. */ - void const * p_context; /**< @brief This pointer must be provided in the reply if the reply function takes a p_context argument. */ -} pm_conn_sec_params_req_evt_t; - - -/**@brief Actions that can be performed to peer data in persistent storage. - */ -typedef enum -{ - PM_PEER_DATA_OP_UPDATE, /**< @brief Writing or overwriting the data. */ - PM_PEER_DATA_OP_DELETE, /**< @brief Removing the data. */ -} pm_peer_data_op_t; - - -/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. - */ -typedef struct -{ - pm_peer_data_id_t data_id; /**< @brief The type of the data that was changed. */ - pm_peer_data_op_t action; /**< @brief What happened to the data. */ - pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ - uint8_t flash_changed : 1; /**< @brief If this is false, no operation was done in flash, because the value was already what it should be. Please note that in certain scenarios, this flag will be true even if the new value is the same as the old. */ -} pm_peer_data_update_succeeded_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. - */ -typedef struct -{ - pm_peer_data_id_t data_id; /**< @brief The type of the data that was supposed to be changed. */ - pm_peer_data_op_t action; /**< @brief The action that failed. */ - pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ - ret_code_t error; /**< @brief An error code that describes the failure. */ -} pm_peer_data_update_failed_t; - - -/**@brief Standard parameters for failure events. - */ -typedef struct -{ - ret_code_t error; /**< @brief The error that occurred. */ -} pm_failure_evt_t; - - -/**@brief Events parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. - */ -typedef struct -{ - bool bond; /**< @brief Whether the peripheral requested bonding. */ - bool mitm; /**< @brief Whether the peripheral requested man-in-the-middle protection. */ -} pm_evt_slave_security_req_t; - - -/**@brief An event from the @ref peer_manager module. - * - * @details The structure contains both standard parameters and parameters that are specific to some events. - */ -typedef struct -{ - pm_evt_id_t evt_id; /**< @brief The type of the event. */ - uint16_t conn_handle; /**< @brief The connection that this event pertains to, or @ref BLE_CONN_HANDLE_INVALID. */ - pm_peer_id_t peer_id; /**< @brief The bonded peer that this event pertains to, or @ref PM_PEER_ID_INVALID. */ - union - { - pm_conn_sec_start_evt_t conn_sec_start; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_START event. */ - pm_conn_secured_evt_t conn_sec_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. */ - pm_conn_secure_failed_evt_t conn_sec_failed; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. */ - pm_conn_sec_params_req_evt_t conn_sec_params_req; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. */ - pm_peer_data_update_succeeded_evt_t peer_data_update_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. */ - pm_peer_data_update_failed_t peer_data_update_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. */ - pm_failure_evt_t peer_delete_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */ - pm_failure_evt_t peers_delete_failed_evt; /**< @brief Parameters specific to the @ref PM_EVT_PEERS_DELETE_FAILED event. */ - pm_failure_evt_t error_unexpected; /**< @brief Parameters specific to the @ref PM_EVT_ERROR_UNEXPECTED event. */ - pm_evt_slave_security_req_t slave_security_req; /**< @brief Parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. */ - } params; -} pm_evt_t; - - -/**@brief Event handler for events from the @ref peer_manager module. - * - * @sa pm_register - * - * @param[in] p_event The event that has occurred. - */ -typedef void (*pm_evt_handler_t)(pm_evt_t const * p_event); - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_MANAGER_TYPES_H__ */ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c deleted file mode 100644 index 83fdf77f11..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "pm_buffer.h" - -#include -#include -#include "nrf_error.h" -#include "pm_mutex.h" - - -#define BUFFER_IS_VALID(p_buffer) ((p_buffer != NULL) \ - && (p_buffer->p_memory != NULL) \ - && (p_buffer->p_mutex != NULL)) - - - -ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, - uint8_t * p_buffer_memory, - uint32_t buffer_memory_size, - uint8_t * p_mutex_memory, - uint32_t mutex_memory_size, - uint32_t n_blocks, - uint32_t block_size) -{ - if ( (p_buffer != NULL) - && (p_buffer_memory != NULL) - && (p_mutex_memory != NULL) - && (buffer_memory_size >= (n_blocks * block_size)) - && (mutex_memory_size >= MUTEX_STORAGE_SIZE(n_blocks)) - && (n_blocks != 0) - && (block_size != 0)) - { - p_buffer->p_memory = p_buffer_memory; - p_buffer->p_mutex = p_mutex_memory; - p_buffer->n_blocks = n_blocks; - p_buffer->block_size = block_size; - pm_mutex_init(p_buffer->p_mutex, n_blocks); - - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } -} - - -uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks) -{ - if (!BUFFER_IS_VALID(p_buffer)) - { - return ( PM_BUFFER_INVALID_ID ); - } - - uint8_t first_locked_mutex = PM_BUFFER_INVALID_ID; - - for (uint8_t i = 0; i < p_buffer->n_blocks; i++) - { - if (pm_mutex_lock(p_buffer->p_mutex, i)) - { - if (first_locked_mutex == PM_BUFFER_INVALID_ID) - { - first_locked_mutex = i; - } - if ((i - first_locked_mutex + 1) == n_blocks) - { - return first_locked_mutex; - } - } - else if (first_locked_mutex != PM_BUFFER_INVALID_ID) - { - for (uint8_t j = first_locked_mutex; j < i; j++) - { - pm_buffer_release(p_buffer, j); - } - first_locked_mutex = PM_BUFFER_INVALID_ID; - } - } - - return ( PM_BUFFER_INVALID_ID ); -} - - -uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id) -{ - if (!BUFFER_IS_VALID(p_buffer)) - { - return ( NULL ); - } - - if ( (id != PM_BUFFER_INVALID_ID) - && pm_mutex_lock_status_get(p_buffer->p_mutex, id) ) - { - return ( &p_buffer->p_memory[id * p_buffer->block_size] ); - } - else - { - return ( NULL ); - } -} - - -void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id) -{ - if ( BUFFER_IS_VALID(p_buffer) - && (id != PM_BUFFER_INVALID_ID) - && pm_mutex_lock_status_get(p_buffer->p_mutex, id)) - { - pm_mutex_unlock(p_buffer->p_mutex, id); - } -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h deleted file mode 100644 index 3697441fbf..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef BUFFER_H__ -#define BUFFER_H__ - -#include -#include "compiler_abstraction.h" -#include "sdk_errors.h" -#include "pm_mutex.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup pm_buffer Buffer - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides a simple buffer. - */ - - -#define PM_BUFFER_INVALID_ID 0xFF //!< Invalid buffer block ID. - - -/**@brief Convenience macro for declaring memory and initializing a buffer instance. - * - * @param[out] p_buffer The buffer instance to initialize. - * @param[in] n_blocks The desired number of blocks in the buffer. - * @param[in] block_size The desired block size of the buffer. - * @param[out] err_code The return code from @ref pm_buffer_init. - */ -#define PM_BUFFER_INIT(p_buffer, n_blocks, block_size, err_code) \ -do \ -{ \ - __ALIGN(4) static uint8_t buffer_memory[(n_blocks) * (block_size)]; \ - static uint8_t mutex_memory[MUTEX_STORAGE_SIZE(n_blocks)]; \ - err_code = pm_buffer_init((p_buffer), \ - buffer_memory, \ - (n_blocks) * (block_size), \ - mutex_memory, \ - MUTEX_STORAGE_SIZE(n_blocks), \ - (n_blocks), \ - (block_size)); \ -} while (0) - - -typedef struct -{ - uint8_t * p_memory; /**< The storage for all buffer entries. The size of the buffer must be n_blocks*block_size. */ - uint8_t * p_mutex; /**< A mutex group with one mutex for each buffer entry. */ - uint32_t n_blocks; /**< The number of allocatable blocks in the buffer. */ - uint32_t block_size; /**< The size of each block in the buffer. */ -} pm_buffer_t; - -/**@brief Function for initializing a buffer instance. - * - * @param[out] p_buffer The buffer instance to initialize. - * @param[in] p_buffer_memory The memory this buffer will use. - * @param[in] buffer_memory_size The size of p_buffer_memory. This must be at least - * n_blocks*block_size. - * @param[in] p_mutex_memory The memory for the mutexes. This must be at least - * @ref MUTEX_STORAGE_SIZE(n_blocks). - * @param[in] mutex_memory_size The size of p_mutex_memory. - * @param[in] n_blocks The number of blocks in the buffer. - * @param[in] block_size The size of each block. - * - * @retval NRF_SUCCESS Successfully initialized buffer instance. - * @retval NRF_ERROR_INVALID_PARAM A parameter was 0 or NULL or a size was too small. - */ -ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, - uint8_t * p_buffer_memory, - uint32_t buffer_memory_size, - uint8_t * p_mutex_memory, - uint32_t mutex_memory_size, - uint32_t n_blocks, - uint32_t block_size); - - -/**@brief Function for acquiring a buffer block in a buffer. - * - * @param[in] p_buffer The buffer instance acquire from. - * @param[in] n_blocks The number of contiguous blocks to acquire. - * - * @return The id of the acquired block, if successful. - * @retval PM_BUFFER_INVALID_ID If unsuccessful. - */ -uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks); - - -/**@brief Function for getting a pointer to a specific buffer block. - * - * @param[in] p_buffer The buffer instance get from. - * @param[in] id The id of the buffer to get the pointer for. - * - * @return A pointer to the buffer for the specified id, if the id is valid. - * @retval NULL If the id is invalid. - */ -uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id); - - -/**@brief Function for releasing a buffer block. - * - * @param[in] p_buffer The buffer instance containing the block to release. - * @param[in] id The id of the block to release. - */ -void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id); - - - -#ifdef __cplusplus -} -#endif - -#endif // BUFFER_H__ - -/** - * @} - * @endcond - */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c deleted file mode 100644 index 10c26078b0..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "pm_mutex.h" - -#include -#include -#include "nrf_error.h" -#include "app_util_platform.h" - - - -/**@brief Locks the mutex defined by the mask. - * - * @param p_mutex pointer to the mutex storage. - * @param mutex_mask the mask identifying the mutex position. - * - * @retval true if the mutex could be locked. - * @retval false if the mutex was already locked. - */ -static bool lock_by_mask(uint8_t * p_mutex, uint8_t mutex_mask) -{ - bool success = false; - - if ( (*p_mutex & mutex_mask) == 0 ) - { - CRITICAL_REGION_ENTER(); - if ( (*p_mutex & mutex_mask) == 0 ) - { - *p_mutex |= mutex_mask; - - success = true; - } - CRITICAL_REGION_EXIT(); - } - - return ( success ); -} - - -void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size) -{ - if (p_mutex != NULL) - { - memset(&p_mutex[0], 0, MUTEX_STORAGE_SIZE(mutex_size)); - } -} - - -bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_id) -{ - if (p_mutex != NULL) - { - return ( lock_by_mask(&(p_mutex[mutex_id >> 3]), (1 << (mutex_id & 0x07))) ); - } - else - { - return false; - } -} - - -void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_id) -{ - uint8_t mutex_base = mutex_id >> 3; - uint8_t mutex_mask = (1 << (mutex_id & 0x07)); - - if ((p_mutex != NULL) - && (p_mutex[mutex_base] & mutex_mask)) - { - CRITICAL_REGION_ENTER(); - p_mutex[mutex_base] &= ~mutex_mask; - CRITICAL_REGION_EXIT(); - } -} - - -uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size) -{ - if (p_mutex != NULL) - { - for ( uint16_t i = 0; i < mutex_size; i++ ) - { - if ( lock_by_mask(&(p_mutex[i >> 3]), 1 << (i & 0x07)) ) - { - return ( i ); - } - } - } - - return ( mutex_size ); -} - - -bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_id) -{ - if (p_mutex != NULL) - { - return ( (p_mutex[mutex_id >> 3] & (1 << (mutex_id & 0x07))) ); - } - else - { - return true; - } -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h deleted file mode 100644 index 7031d73fcb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef MUTEX_H__ -#define MUTEX_H__ - - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @cond NO_DOXYGEN - * @defgroup pm_mutex Mutex - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides thread-safe mutexes. - */ - - -/**@brief Defines the storage size of a specified mutex group. - * - * @param number_of_mutexes the number of mutexes in the group. - */ -#define MUTEX_STORAGE_SIZE(number_of_mutexes) ((7 + (number_of_mutexes)) >> 3) - - -/**@brief Initializes a mutex group. - * - * @param[in] p_mutex Pointer to the mutex group. See @ref MUTEX_STORAGE_SIZE(). - * @param[in] mutex_size The size of the mutex group in number of mutexes. - */ -void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size); - - -/**@brief Locks the mutex specified by the bit id. - * - * @param[inout] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - * - * @retval true if it was possible to lock the mutex. - * @retval false otherwise. - */ -bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_bit_id); - - -/**@brief Locks the first unlocked mutex within the mutex group. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_size The size of the mutex group. - * - * @return The first unlocked mutex id in the group. - * @retval group-size if there was no unlocked mutex available. - */ -uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size); - - -/**@brief Unlocks the mutex specified by the bit id. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - */ -void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_bit_id); - - -/**@brief Gets the locking status of the specified mutex. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - * - * @retval true if the mutex was locked. - * @retval false otherwise. - */ -bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_bit_id); - - - -#ifdef __cplusplus -} -#endif - -#endif // MUTEX_H__ - -/** @} - * @endcond - */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c deleted file mode 100644 index b36fea2aae..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c +++ /dev/null @@ -1,1119 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "security_dispatcher.h" - -#include -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_database.h" -#include "id_manager.h" - -#ifndef PM_CENTRAL_ENABLED - #define PM_CENTRAL_ENABLED 1 -#endif - -// The number of registered event handlers. -#define SMD_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - -STATIC_ASSERT((NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0) || PM_CENTRAL_ENABLED, - "Peer Manager Central operation must be enabled when using central links."); - -// Security Dispacher event handlers in Security Manager and GATT Cache Manager. -extern void sm_smd_evt_handler(pm_evt_t * p_event); - -// Security Dispatcher events' handlers. -// The number of elements in this array is SMD_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - sm_smd_evt_handler -}; - -static bool m_module_initialized; - -static ble_conn_state_user_flag_id_t m_flag_sec_proc = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_pairing = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_bonding = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_new_peer = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_allow_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; - -static ble_gap_lesc_p256_pk_t m_peer_pk; - - -static __INLINE bool sec_procedure(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc); -} - -static __INLINE bool pairing(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_pairing); -} - -static __INLINE bool bonding(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_bonding); -} - -static __INLINE bool peer_created(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_new_peer); -} - -static __INLINE bool allow_repairing(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_allow_repairing); -} - - -/**@brief Function for sending an SMD event to all event handlers. - * - * @param[in] p_event The event to pass to all event handlers. - */ -static void evt_send(pm_evt_t * p_event) -{ - p_event->peer_id = im_peer_id_get_by_conn_handle(p_event->conn_handle); - - for (uint32_t i = 0; i < SMD_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for sending a PM_EVT_CONN_SEC_START event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] procedure The procedure that has started on the connection. - */ -static void sec_start_send(uint16_t conn_handle, - pm_conn_sec_procedure_t procedure) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_START, - .conn_handle = conn_handle, - .params = {.conn_sec_start = {.procedure = procedure}} - }; - evt_send(&evt); -} - - -/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .conn_handle = conn_handle, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - evt_send(&error_evt); -} - - -/**@brief Function for cleaning up after a failed security procedure. - * - * @param[in] conn_handle The handle of the connection the security procedure happens on. - * @param[in] procedure The procedure that failed. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static void conn_sec_failure(uint16_t conn_handle, - pm_conn_sec_procedure_t procedure, - pm_sec_error_code_t error, - uint8_t error_src) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_FAILED, - .conn_handle = conn_handle, - .params = - { - .conn_sec_failed = - { - .procedure = procedure, - .error = error, - .error_src = error_src, - } - } - }; - - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); - - evt_send(&evt); - return; -} - - -/**@brief Function for cleaning up after a failed pairing procedure. - * - * @param[in] conn_handle The handle of the connection the pairing procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The source of the error (local or remote). See @ref - * BLE_GAP_SEC_STATUS_SOURCES. - */ -static void pairing_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - ret_code_t err_code = NRF_SUCCESS; - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - pm_conn_sec_procedure_t procedure = bonding(conn_handle) ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - - if (peer_created(conn_handle)) - { - // The peer_id was created during the procedure, and should be freed, because no data is - // stored under it. - err_code = im_peer_free(peer_id); // Attempt to free allocated peer. - UNUSED_VARIABLE(err_code); - } - else if(peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND /* No buffer was allocated */)) - { - send_unexpected_error(conn_handle, err_code); - } - } - - conn_sec_failure(conn_handle, procedure, error, error_src); - - return; -} - - -/**@brief Function for cleaning up after a failed encryption procedure. - * - * @param[in] conn_handle The handle of the connection the encryption procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static __INLINE void encryption_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - conn_sec_failure(conn_handle, PM_LINK_SECURED_PROCEDURE_ENCRYPTION, error, error_src); - - return; -} - - -/**@brief Function for possibly cleaning up after a failed pairing or encryption procedure. - * - * @param[in] conn_handle The handle of the connection the pairing procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static void link_secure_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - if (sec_procedure(conn_handle)) - { - if (pairing(conn_handle)) - { - pairing_failure(conn_handle, error, error_src); - } - else - { - encryption_failure(conn_handle, error, error_src); - } - } -} - - -/**@brief Function for administrative actions to be taken when a security process has started. - * - * @param[in] conn_handle The connection the security process was attempted on. - * @param[in] success Whether the procedure was started successfully. - * @param[in] procedure The procedure that was started. - */ -static void sec_proc_start(uint16_t conn_handle, - bool success, - pm_conn_sec_procedure_t procedure) -{ - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, success); - if (success) - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_sec_proc_pairing, - (procedure != PM_LINK_SECURED_PROCEDURE_ENCRYPTION)); - ble_conn_state_user_flag_set(conn_handle, - m_flag_sec_proc_bonding, - (procedure == PM_LINK_SECURED_PROCEDURE_BONDING)); - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, false); - sec_start_send(conn_handle, procedure); - } -} - - - -/**@brief Function for administrative actions to be taken during the course of a security process. - * - * @param[in] conn_handle The connection the security process was attempted on. - * @param[in] peer_id The peer ID given to the connected peer. - * @param[in] success Whether the process was started successfully. - * @param[in] new_peer_created Whether a new peer was created during the process attempt. - */ -static void sec_proc_housekeeping(uint16_t conn_handle, - pm_peer_id_t peer_id, - bool success, - bool new_peer_created) -{ - if (success) - { - if (new_peer_created) - { - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, true); - im_new_peer_id(conn_handle, peer_id); - } - } - else - { - if (new_peer_created) - { - ret_code_t err_code = im_peer_free(peer_id); // Attempt to free allocated peer. - UNUSED_VARIABLE(err_code); - } - } -} - - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_INFO_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_info_request_process(ble_gap_evt_t const * p_gap_evt) -{ - ret_code_t err_code; - ble_gap_enc_info_t const * p_enc_info = NULL; - pm_peer_data_flash_t peer_data; - pm_peer_id_t peer_id = im_peer_id_get_by_master_id( - &p_gap_evt->params.sec_info_request.master_id); - - if (peer_id == PM_PEER_ID_INVALID) - { - peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle); - } - else - { - // The peer might have been unrecognized until now (since connecting). E.g. if using a - // random non-resolvable advertising address. Report the discovered peer ID just in case. - im_new_peer_id(p_gap_evt->conn_handle, peer_id); - } - - sec_proc_start(p_gap_evt->conn_handle, true, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); - - if (peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); - - if (err_code == NRF_SUCCESS) - { - // There is stored bonding data for this peer. - ble_gap_enc_key_t const * p_existing_key = &peer_data.p_bonding_data->own_ltk; - - if ( p_existing_key->enc_info.lesc - || (im_master_ids_compare(&p_existing_key->master_id, - &p_gap_evt->params.sec_info_request.master_id))) - { - p_enc_info = &p_existing_key->enc_info; - } - } - } - - err_code = sd_ble_gap_sec_info_reply(p_gap_evt->conn_handle, p_enc_info, NULL, NULL); - - if (err_code != NRF_SUCCESS) - { - sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); - send_unexpected_error(p_gap_evt->conn_handle, err_code); - } - else if (p_enc_info == NULL) - { - sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); - encryption_failure(p_gap_evt->conn_handle, - PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, - BLE_GAP_SEC_STATUS_SOURCE_LOCAL); - } - - return; -} - - - -/**@brief Function for sending a CONFIG_REQ event. - * - * @param[in] conn_handle The connection the sec parameters are needed for. - */ -static void send_config_req(uint16_t conn_handle) -{ - pm_evt_t evt; - memset(&evt, 0, sizeof(evt)); - - evt.evt_id = PM_EVT_CONN_SEC_CONFIG_REQ; - evt.conn_handle = conn_handle; - - evt_send(&evt); -} - - -void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); - - ble_conn_state_user_flag_set(conn_handle, - m_flag_allow_repairing, - p_conn_sec_config->allow_repairing); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_DISCONNECT event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void disconnect_process(ble_gap_evt_t const * p_gap_evt) -{ - pm_sec_error_code_t error = (p_gap_evt->params.disconnected.reason - == BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE) - ? PM_CONN_SEC_ERROR_MIC_FAILURE : PM_CONN_SEC_ERROR_DISCONNECT; - - link_secure_failure(p_gap_evt->conn_handle, error, BLE_GAP_SEC_STATUS_SOURCE_LOCAL); -} - - -/**@brief Function for sending a PARAMS_REQ event. - * - * @param[in] conn_handle The connection the security parameters are needed for. - * @param[in] p_peer_params The security parameters from the peer. Can be NULL if the peer's parameters - * are not yet available. - */ -static void send_params_req(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_PARAMS_REQ, - .conn_handle = conn_handle, - .params = - { - .conn_sec_params_req = - { - .p_peer_params = p_peer_params - }, - }, - }; - - evt_send(&evt); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_params_request_process(ble_gap_evt_t const * p_gap_evt) -{ - if (ble_conn_state_role(p_gap_evt->conn_handle) == BLE_GAP_ROLE_PERIPH) - { - sec_proc_start(p_gap_evt->conn_handle, - true, - p_gap_evt->params.sec_params_request.peer_params.bond - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING); - } - - send_params_req(p_gap_evt->conn_handle, &p_gap_evt->params.sec_params_request.peer_params); - return; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when - * the auth_status is success. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_success_process(ble_gap_evt_t const * p_gap_evt) -{ - ret_code_t err_code = NRF_SUCCESS; - uint16_t conn_handle = p_gap_evt->conn_handle; - uint8_t role = ble_conn_state_role(conn_handle); - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - pm_peer_id_t new_peer_id = peer_id; - pm_peer_data_t peer_data; - bool data_stored = false; - - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); - - if (role == BLE_GAP_ROLE_INVALID) - { - /* Unlikely, but maybe possible? */ - return; - } - - if (p_gap_evt->params.auth_status.bonded) - { - pm_peer_id_t duplicate_peer_id = PM_PEER_ID_INVALID; - data_stored = true; - - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); - if (err_code != NRF_SUCCESS) - { - send_unexpected_error(conn_handle, err_code); - data_stored = false; - } - else - { - duplicate_peer_id = im_find_duplicate_bonding_data(peer_data.p_bonding_data, - PM_PEER_ID_INVALID); - } - - if (duplicate_peer_id != PM_PEER_ID_INVALID) - { - // The peer has been identified as someone we have already bonded with. - new_peer_id = duplicate_peer_id; - im_new_peer_id(conn_handle, new_peer_id); - - // If the flag is true, the configuration has been requested before. - if (!allow_repairing(conn_handle)) - { - send_config_req(conn_handle); - if (!allow_repairing(conn_handle)) - { - data_stored = false; - } - } - } - - if (data_stored) - { - err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_BONDING, new_peer_id); - if (err_code != NRF_SUCCESS) - { - /* Unexpected */ - send_unexpected_error(conn_handle, err_code); - data_stored = false; - } - } - - if ((duplicate_peer_id != PM_PEER_ID_INVALID) && peer_created(conn_handle)) - { - // We already have a bond with the peer. Now that the data has been stored for the - // existing peer, the peer created for this bonding procedure can be freed. - ret_code_t err_code_free = im_peer_free(peer_id); - UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. - } - } - else if (peer_created(conn_handle)) - { - ret_code_t err_code_free = im_peer_free(peer_id); - UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. - } - else - { - // No action. - } - - pm_evt_t pairing_success_evt; - - pairing_success_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; - pairing_success_evt.conn_handle = conn_handle; - pairing_success_evt.params.conn_sec_succeeded.procedure = p_gap_evt->params.auth_status.bonded - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - pairing_success_evt.params.conn_sec_succeeded.data_stored = data_stored; - - evt_send(&pairing_success_evt); - - return; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when - * the auth_status is failure. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_failure_process(ble_gap_evt_t const * p_gap_evt) -{ - link_secure_failure(p_gap_evt->conn_handle, - p_gap_evt->params.auth_status.auth_status, - p_gap_evt->params.auth_status.error_src); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_process(ble_gap_evt_t const * p_gap_evt) -{ - switch (p_gap_evt->params.auth_status.auth_status) - { - case BLE_GAP_SEC_STATUS_SUCCESS: - auth_status_success_process(p_gap_evt); - break; - - default: - auth_status_failure_process(p_gap_evt); - break; - } -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_CONN_SEC_UPDATE event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void conn_sec_update_process(ble_gap_evt_t const * p_gap_evt) -{ - if (!pairing(p_gap_evt->conn_handle)) - { - // This is an encryption procedure (not pairing), so this event marks the end of the procedure. - - if (!ble_conn_state_encrypted(p_gap_evt->conn_handle)) - { - encryption_failure(p_gap_evt->conn_handle, - PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, - BLE_GAP_SEC_STATUS_SOURCE_REMOTE); - } - else - { - ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_flag_sec_proc, false); - - pm_evt_t evt; - - evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; - evt.conn_handle = p_gap_evt->conn_handle; - evt.params.conn_sec_succeeded.procedure = PM_LINK_SECURED_PROCEDURE_ENCRYPTION; - evt.params.conn_sec_succeeded.data_stored = false; - - evt_send(&evt); - } - } -} - - -/**@brief Funtion for initializing a BLE Connection State user flag. - * - * @param[out] flag_id The flag to initialize. - */ -static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) -{ - if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - *p_flag_id = ble_conn_state_user_flag_acquire(); - } -} - - -ret_code_t smd_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - flag_id_init(&m_flag_sec_proc); - flag_id_init(&m_flag_sec_proc_pairing); - flag_id_init(&m_flag_sec_proc_bonding); - flag_id_init(&m_flag_sec_proc_new_peer); - flag_id_init(&m_flag_allow_repairing); - - if ((m_flag_sec_proc == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_pairing == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_bonding == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_new_peer == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_allow_repairing == BLE_CONN_STATE_USER_FLAG_INVALID)) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -/**@brief Function for putting retrieving a buffer and putting pointers into a @ref ble_gap_sec_keyset_t. - * - * @param[in] conn_handle The connection the security procedure is happening on. - * @param[in] peer_id The peer the security procedure is happening with. - * @param[in] role Our role in the connection. - * @param[in] p_public_key Pointer to a buffer holding the public key, or NULL. - * @param[out] p_sec_keyset Pointer to the keyset to be filled. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. - * @retval NRF_ERROR_BUSY Could not process request at this time. Reattempt later. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - * @retval NRF_ERROR_INTERNAL Fatal error. - */ -static ret_code_t sec_keyset_fill(uint16_t conn_handle, - pm_peer_id_t peer_id, - uint8_t role, - ble_gap_lesc_p256_pk_t * p_public_key, - ble_gap_sec_keyset_t * p_sec_keyset) -{ - ret_code_t err_code; - pm_peer_data_t peer_data; - - if (p_sec_keyset == NULL) - { - return NRF_ERROR_INTERNAL; - } - - // Acquire a memory buffer to receive bonding data into. - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); - - if (err_code == NRF_ERROR_BUSY) - { - // No action. - } - else if (err_code != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - else /* if (err_code == NRF_SUCCESS) */ - { - memset(peer_data.p_bonding_data, 0, sizeof(pm_peer_data_bonding_t)); - - peer_data.p_bonding_data->own_role = role; - - p_sec_keyset->keys_own.p_enc_key = &peer_data.p_bonding_data->own_ltk; - p_sec_keyset->keys_own.p_pk = p_public_key; - p_sec_keyset->keys_peer.p_enc_key = &peer_data.p_bonding_data->peer_ltk; - p_sec_keyset->keys_peer.p_id_key = &peer_data.p_bonding_data->peer_ble_id; - p_sec_keyset->keys_peer.p_pk = &m_peer_pk; - - // Retrieve the address the peer used during connection establishment. - // This address will be overwritten if ID is shared. Should not fail. - err_code = im_ble_addr_get(conn_handle, &peer_data.p_bonding_data->peer_ble_id.id_addr_info); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - // Buffer is OK, reserve room in flash for the data. - err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); - if (err_code == NRF_ERROR_NOT_FOUND) - { - return NRF_ERROR_INTERNAL; - } - } - - return err_code; -} - - -ret_code_t smd_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - ble_gap_lesc_p256_pk_t * p_public_key) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t role = ble_conn_state_role(conn_handle); - pm_peer_id_t peer_id = PM_PEER_ID_INVALID; - ret_code_t err_code = NRF_SUCCESS; - uint8_t sec_status = BLE_GAP_SEC_STATUS_SUCCESS; - bool new_peer_created = peer_created(conn_handle); - ble_gap_sec_keyset_t sec_keyset; - - memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t)); - if (role == BLE_GAP_ROLE_PERIPH) - { - // Set the default value for allowing repairing at the start of the sec proc. (for peripheral) - ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, false); - } - - if (role == BLE_GAP_ROLE_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - - if (p_sec_params == NULL) - { - // NULL params means reject pairing. - sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; - } - else if (!p_sec_params->bond) - { - // Pairing, no bonding. - - sec_keyset.keys_own.p_pk = p_public_key; - sec_keyset.keys_peer.p_pk = &m_peer_pk; - } - else - { - // Bonding is to be performed, prepare to receive bonding data. - - peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - if (peer_id == PM_PEER_ID_INVALID) - { - // Peer is unknown to us, allocate a new peer ID for it. - peer_id = pdb_peer_allocate(); - if (peer_id != PM_PEER_ID_INVALID) - { - new_peer_created = true; - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - } - else if (role == BLE_GAP_ROLE_PERIPH && !allow_repairing(conn_handle)) - { - // Bond already exists. Reject the pairing request if the user doesn't intervene. - // send_config_req(conn_handle, peer_id); - send_config_req(conn_handle); - if (!allow_repairing(conn_handle)) - { - // Reject pairing. - sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; - } - } - - if ((sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP) && (err_code == NRF_SUCCESS)) - { - err_code = sec_keyset_fill(conn_handle, peer_id, role, p_public_key, &sec_keyset); - } - } - - if (err_code == NRF_SUCCESS) - { - // Everything OK, reply to SoftDevice. If an error happened, the user is given an - // opportunity to change the parameters and retry the call. - if (role == BLE_GAP_ROLE_PERIPH) - { - err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_sec_params, &sec_keyset); - } - else - { - err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, NULL, &sec_keyset); - } - } - - sec_proc_housekeeping(conn_handle, - peer_id, - (err_code == NRF_SUCCESS) && (sec_status == BLE_GAP_SEC_STATUS_SUCCESS), - new_peer_created); - - return err_code; -} - - -#if PM_CENTRAL_ENABLED -/**@brief Function for initiating encryption as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central_encryption(uint16_t conn_handle, - pm_peer_id_t peer_id) -{ - pm_peer_data_flash_t peer_data; - ret_code_t err_code; - ble_gap_enc_key_t const * p_existing_key = NULL; - bool lesc = false; - - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); - - if (err_code == NRF_SUCCESS) - { - // Use peer's key since they are peripheral. - p_existing_key = &(peer_data.p_bonding_data->peer_ltk); - - lesc = peer_data.p_bonding_data->own_ltk.enc_info.lesc; - if (lesc) // LESC was used during bonding. - { - // For LESC, always use own key. - p_existing_key = &(peer_data.p_bonding_data->own_ltk); - } - } - - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) - { - if (err_code != NRF_ERROR_BUSY) - { - // Unexpected error code. - err_code = NRF_ERROR_INTERNAL; - } - } - else if (p_existing_key == NULL) /* There is no bonding data stored. This means that a bonding - procedure is in ongoing, or that the records in flash are - in a bad state. */ - { - err_code = NRF_ERROR_BUSY; - } - else if (!lesc && !im_master_id_is_valid(&(p_existing_key->master_id))) /* There is no valid LTK stored. */ - { - // No LTK to encrypt with. - err_code = NRF_ERROR_INVALID_DATA; - } - else - { - // Encrypt with existing LTK. - err_code = sd_ble_gap_encrypt(conn_handle, - &(p_existing_key->master_id), - &(p_existing_key->enc_info)); - } - - sec_proc_start(conn_handle, err_code == NRF_SUCCESS, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); - sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), false); - - return err_code; -} - - -/**@brief Function for intiating pairing as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central_pairing(uint16_t conn_handle, - pm_peer_id_t peer_id, - ble_gap_sec_params_t * p_sec_params) -{ - pm_conn_sec_procedure_t procedure = PM_LINK_SECURED_PROCEDURE_PAIRING; - bool new_peer_created = false; - ret_code_t err_code = NRF_SUCCESS; - pm_peer_data_t dummy_peer_data; - - if (p_sec_params == NULL) - { - err_code = sd_ble_gap_authenticate(conn_handle, NULL); - } - else - { - if (p_sec_params->bond) - { - procedure = PM_LINK_SECURED_PROCEDURE_BONDING; - - if (peer_id == PM_PEER_ID_INVALID) - { - // New peer is required. - peer_id = pdb_peer_allocate(); - new_peer_created = true; - } - - if (peer_id == PM_PEER_ID_INVALID) - { - err_code = NRF_ERROR_INTERNAL; - } - else - { - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &dummy_peer_data); - if (err_code == NRF_SUCCESS) - { - err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); - } - } - } - - if (err_code == NRF_SUCCESS) - { - err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); - } - - if (err_code != NRF_SUCCESS) - { - ret_code_t err_code_free = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); - if ((err_code_free != NRF_SUCCESS) && (err_code_free != NRF_ERROR_NOT_FOUND)) - { - err_code = NRF_ERROR_INTERNAL; - } - } - } - - if (err_code == NRF_ERROR_NO_MEM) - { - // sd_ble_gap_authenticate() returned NRF_ERROR_NO_MEM. Too many other sec procedures running. - err_code = NRF_ERROR_BUSY; - } - - sec_proc_start(conn_handle, err_code == NRF_SUCCESS, procedure); - sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), new_peer_created); - - return err_code; -} - - - -/**@brief Function for intiating security as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing) -{ - ret_code_t err_code; - pm_peer_id_t peer_id; - - if (p_sec_params == NULL) - { - return sd_ble_gap_authenticate(conn_handle, NULL); - } - - // Set the default value for allowing repairing at the start of the sec proc. (for central) - ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, force_repairing); - - peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - if ((peer_id != PM_PEER_ID_INVALID) && !force_repairing) - { - // There is already data in flash for this peer, and repairing has not been requested, so - // link will be encrypted with the existing keys. - err_code = link_secure_central_encryption(conn_handle, peer_id); - } - else - { - // There are no existing keys, or repairing has been explicitly requested, so pairing - // (possibly including bonding) will be performed to encrypt the link. - err_code = link_secure_central_pairing(conn_handle, peer_id, p_sec_params); - } - - return err_code; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_request_process(ble_gap_evt_t const * p_gap_evt) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_SLAVE_SECURITY_REQ, - .conn_handle = p_gap_evt->conn_handle, - .params = - { - .slave_security_req = - { - .bond = p_gap_evt->params.sec_request.bond, - .mitm = p_gap_evt->params.sec_request.mitm, - } - } - }; - evt_send(&evt); - return; -} -#endif // PM_CENTRAL_ENABLED - - -/**@brief Function for asking the central to secure the link. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_peripheral(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params) -{ - ret_code_t err_code = NRF_SUCCESS; - - if (p_sec_params != NULL) - { - err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); - } - - return err_code; -} - - -ret_code_t smd_link_secure(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t role = ble_conn_state_role(conn_handle); - - switch (role) - { -#if PM_CENTRAL_ENABLED - case BLE_GAP_ROLE_CENTRAL: - return link_secure_central(conn_handle, p_sec_params, force_repairing); -#endif - - case BLE_GAP_ROLE_PERIPH: - return link_secure_peripheral(conn_handle, p_sec_params); - - default: - return BLE_ERROR_INVALID_CONN_HANDLE; - } -} - - -void smd_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_DISCONNECTED: - disconnect_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - sec_params_request_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_SEC_INFO_REQUEST: - sec_info_request_process(&(p_ble_evt->evt.gap_evt)); - break; - -#if PM_CENTRAL_ENABLED - case BLE_GAP_EVT_SEC_REQUEST: - sec_request_process(&(p_ble_evt->evt.gap_evt)); - break; -#endif - - case BLE_GAP_EVT_AUTH_STATUS: - auth_status_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_CONN_SEC_UPDATE: - conn_sec_update_process(&(p_ble_evt->evt.gap_evt)); - break; - }; -} -#endif //NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h deleted file mode 100644 index b985fe25d3..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef SECURITY_DISPATCHER_H__ -#define SECURITY_DISPATCHER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup security_dispatcher Security Dispatcher - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and - * encryption, including flash storage of shared data. - * - */ - - -/**@brief Function for initializing the Security Dispatcher module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL An unexpected fatal error occurred. - */ -ret_code_t smd_init(void); - - -/**@brief Function for dispatching SoftDevice events to the Security Dispatcher module. - * - * @param[in] ble_evt The SoftDevice event. - */ -void smd_ble_evt_handler(ble_evt_t const * ble_evt); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing pairing and bonding parameters to use for the current pairing - * procedure on a connection. - * - * @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref - * BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_STORAGE_FULL, this function can be called - * again after corrective action. - * - * @note To reject a request, call this function with NULL p_sec_params. - * - * @param[in] conn_handle The connection handle of the connection the pairing is happening on. - * @param[in] p_sec_params The security parameters to use for this link. - * @param[in] p_public_key A pointer to the public key to use if using LESC, or NULL. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_INVALID_STATE No parameters have been requested on that conn_handle, or - * the link is disconnecting. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next - * FDS garbage collection procedure. - * @retval NRF_ERROR_BUSY No write buffer. Reattempt later. - * @retval NRF_ERROR_INTERNAL A fatal error occurred. - */ -ret_code_t smd_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - ble_gap_lesc_p256_pk_t * p_public_key); - - -/**@brief Function for initiating security on the link, with the specified parameters. - * - * @note If the connection is a peripheral connection, this will send a security request to the - * master, but the master is not obligated to initiate pairing or encryption in response. - * @note If the connection is a central connection and a key is available, the parameters will be - * used to determine whether to re-pair or to encrypt using the existing key. If no key is - * available, pairing will be started. - * - * @param[in] conn_handle Handle of the connection to initiate pairing on. - * @param[in] p_sec_params The security parameters to use for this link. As a central, this can - * be NULL to reject a slave security request. - * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether - * an encryption key already exists. This argument is only relevant for - * the central role. Recommended value: false - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_NULL p_sec_params was NULL (peripheral only). - * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, - * or the link is disconnecting. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). - * @retval NRF_ERROR_BUSY Unable to initiate procedure at this time. - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next - * FDS garbage collection procedure. - * @retval NRF_ERROR_INTERNAL No more available peer IDs. - */ -ret_code_t smd_link_secure(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* SECURITY_DISPATCHER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c deleted file mode 100644 index c2c8ad7d1d..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c +++ /dev/null @@ -1,695 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "security_manager.h" - -#include -#include "ble_err.h" -#include "security_dispatcher.h" -#include "peer_database.h" -#include "ble_conn_state.h" -#include "id_manager.h" - - -// The number of registered event handlers. -#define SM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Security Manager event handler in Peer Manager. -extern void pm_sm_evt_handler(pm_evt_t * p_sm_evt); - -// Security Manager events' handlers. -// The number of elements in this array is SM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_sm_evt_handler -}; - - -// The context type that is used in PM_EVT_CONN_SEC_PARAMS_REQ events and in calls to sm_sec_params_reply(). -typedef struct -{ - ble_gap_sec_params_t * p_sec_params; //!< The security parameters to use in the call to the security_dispatcher - ble_gap_sec_params_t sec_params_mem; //!< The buffer for holding the security parameters. - bool params_reply_called; //!< Whether @ref sm_sec_params_reply has been called for this context instance. -} sec_params_reply_context_t; - -static bool m_module_initialized; //!< Whether the Security Manager module has been initialized. - -static ble_gap_sec_params_t m_sec_params; //!< The buffer for the default security parameters set by @ref sm_sec_params_set. -static ble_gap_sec_params_t * mp_sec_params = NULL; //!< The default security parameters set by @ref sm_sec_params_set. -static bool m_sec_params_set = false; //!< Whether @ref sm_sec_params_set has been called. - -static ble_gap_lesc_p256_pk_t * m_p_public_key; //!< Pointer, provided by the user, to the public key to use for LESC procedures. - -static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_BUSY. -static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_STORAGE_FULL. -static ble_conn_state_user_flag_id_t m_flag_link_secure_force_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with true for the force_repairing parameter. -static ble_conn_state_user_flag_id_t m_flag_link_secure_null_params = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with NULL security parameters. -static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_BUSY. -static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_STORAGE_FULL. - - -/**@brief Function for sending an SM event to all registered event handlers. - * - * @param[in] p_event The event to send. - */ -static void evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < SM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for setting or clearing user flags based on error codes returned from @ref - * smd_link_secure or @ref smd_params_reply. - * - * @param[in] conn_handle The connection the call pertained to. - * @param[in] err_code The error code returned from @ref smd_link_secure or - * @ref smd_params_reply. - * @param[in] params_reply Whether the call was to @ref smd_params_reply. - */ -static void flags_set_from_err_code(uint16_t conn_handle, ret_code_t err_code, bool params_reply) -{ - bool flag_value_flash_full = false; - bool flag_value_busy = false; - - if ((err_code == NRF_ERROR_STORAGE_FULL)) - { - flag_value_busy = false; - flag_value_flash_full = true; - } - else if (err_code == NRF_ERROR_BUSY) - { - flag_value_busy = true; - flag_value_flash_full = false; - } - else - { - flag_value_busy = false; - flag_value_flash_full = false; - } - - if (params_reply) - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_params_reply_pending_flash_full, - flag_value_flash_full); - ble_conn_state_user_flag_set(conn_handle, - m_flag_params_reply_pending_busy, - flag_value_busy); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_flash_full, - false); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_busy, - false); - } - else - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_flash_full, - flag_value_flash_full); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_busy, - flag_value_busy); - } -} - - -/**@brief Function for sending an event based on error codes returned from @ref smd_link_secure or - * @ref smd_params_reply. - * - * @param[in] conn_handle The connection the event pertains to. - * @param[in] err_code The error code returned from @ref smd_link_secure or - * @ref smd_params_reply. - * @param[in] p_sec_params The security parameters attempted to pass in the call to - * @ref smd_link_secure or @ref smd_params_reply. - */ -static void events_send_from_err_code(uint16_t conn_handle, - ret_code_t err_code, - ble_gap_sec_params_t * p_sec_params) -{ - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_INVALID_STATE)) - { - pm_evt_t evt = - { - .conn_handle = conn_handle, - .peer_id = im_peer_id_get_by_conn_handle(conn_handle), - }; - if (err_code == NRF_ERROR_TIMEOUT) - { - evt.evt_id = PM_EVT_CONN_SEC_FAILED; - evt.params.conn_sec_failed.procedure = ((p_sec_params != NULL) && p_sec_params->bond) - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - evt.params.conn_sec_failed.error_src = BLE_GAP_SEC_STATUS_SOURCE_LOCAL; - evt.params.conn_sec_failed.error = PM_CONN_SEC_ERROR_SMP_TIMEOUT; - } - else if (err_code == NRF_ERROR_STORAGE_FULL) - { - evt.evt_id = PM_EVT_STORAGE_FULL; - } - else - { - evt.evt_id = PM_EVT_ERROR_UNEXPECTED; - evt.params.error_unexpected.error = err_code; - } - evt_send(&evt); - } -} - - -/**@brief Function for sending an PM_EVT_CONN_SEC_PARAMS_REQ event. - * - * @param[in] conn_handle The connection the event pertains to. - * @param[in] p_peer_params The peer's security parameters to include in the event. Can be NULL. - * @param[in] p_context Pointer to a context that the user must include in the call to @ref - * sm_sec_params_reply(). - */ -static void params_req_send(uint16_t conn_handle, - ble_gap_sec_params_t const * p_peer_params, - sec_params_reply_context_t * p_context) -{ - pm_evt_t evt; - evt.evt_id = PM_EVT_CONN_SEC_PARAMS_REQ; - evt.conn_handle = conn_handle; - evt.peer_id = im_peer_id_get_by_conn_handle(conn_handle); - evt.params.conn_sec_params_req.p_peer_params = p_peer_params; - evt.params.conn_sec_params_req.p_context = p_context; - - evt_send(&evt); -} - - -/**@brief Function for creating a new @ref sec_params_reply_context_t with the correct initial values. - * - * @return The new context. - */ -static sec_params_reply_context_t new_context_get(void) -{ - sec_params_reply_context_t new_context = - { - .p_sec_params = mp_sec_params, - .params_reply_called = false - }; - return new_context; -} - - -/**@brief Internal function corresponding to @ref sm_link_secure. - * - * @param[in] conn_handle The connection to secure. - * @param[in] null_params Whether to pass NULL security parameters to the security_dispatcher. - * @param[in] force_repairing Whether to force rebonding if peer exists. - * @param[in] send_events Whether to send events based on the result of @ref smd_link_secure. - * - * @return Same return codes as @ref sm_link_secure. - */ -static ret_code_t link_secure(uint16_t conn_handle, - bool null_params, - bool force_repairing, - bool send_events) -{ - ret_code_t err_code; - ret_code_t return_err_code; - ble_gap_sec_params_t * p_sec_params; - - if (null_params) - { - p_sec_params = NULL; - } - else - { - sec_params_reply_context_t context = new_context_get(); - params_req_send(conn_handle, NULL, &context); - p_sec_params = context.p_sec_params; - - if (!m_sec_params_set && !context.params_reply_called) - { - // Security parameters have not been set. - return NRF_ERROR_NOT_FOUND; - } - } - - - err_code = smd_link_secure(conn_handle, p_sec_params, force_repairing); - - flags_set_from_err_code(conn_handle, err_code, false); - - switch (err_code) - { - case NRF_ERROR_BUSY: - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); - return_err_code = NRF_SUCCESS; - break; - case NRF_ERROR_STORAGE_FULL: - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); - /* fallthrough */ - case NRF_SUCCESS: - case NRF_ERROR_TIMEOUT: - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_STATE: - return_err_code = err_code; - break; - default: - return_err_code = NRF_ERROR_INTERNAL; - break; - } - - if (send_events) - { - events_send_from_err_code(conn_handle, err_code, p_sec_params); - } - - return return_err_code; -} - - -/**@brief Function for requesting security parameters from the user and passing them to the security_dispatcher. - * - * @param[in] conn_handle The connection that needs security parameters. - * @param[in] p_peer_params The peer's security parameters if present. Otherwise NULL. - */ -static void smd_params_reply_perform(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) -{ - ret_code_t err_code; - sec_params_reply_context_t context = new_context_get(); - - params_req_send(conn_handle, p_peer_params, &context); - - err_code = smd_params_reply(conn_handle, context.p_sec_params, m_p_public_key); - - flags_set_from_err_code(conn_handle, err_code, true); - events_send_from_err_code(conn_handle, err_code, context.p_sec_params); -} - - -/**@brief Function for handling @ref PM_EVT_CONN_SEC_PARAMS_REQ events. - * - * @param[in] p_event The @ref PM_EVT_CONN_SEC_PARAMS_REQ event. - */ -static __INLINE void params_req_process(pm_evt_t const * p_event) -{ - smd_params_reply_perform(p_event->conn_handle, p_event->params.conn_sec_params_req.p_peer_params); -} - - -/**@brief Function for handling @ref PM_EVT_SLAVE_SECURITY_REQ events. - * - * @param[in] p_event The @ref PM_EVT_SLAVE_SECURITY_REQ event. - */ -static void sec_req_process(pm_evt_t const * p_event) -{ - bool null_params = false; - if (mp_sec_params == NULL) - { - null_params = true; - } - else if ((bool)m_sec_params.bond < (bool)p_event->params.slave_security_req.bond) - { - null_params = true; - } - else if ((bool)m_sec_params.mitm < (bool)p_event->params.slave_security_req.mitm) - { - null_params = true; - } - else - { - // No action. - } - ret_code_t err_code = link_secure(p_event->conn_handle, null_params, false, true); - UNUSED_VARIABLE(err_code); // It is acceptable to ignore the return code because it is - // acceptable to ignore a security request. -} - - -/**@brief Function for translating an SMD event to an SM event and passing it on to SM event handlers. - * - * @param[in] p_event The event to forward. - */ -static void evt_forward(pm_evt_t * p_event) -{ - evt_send(p_event); -} - - -/**@brief Event handler for events from the Security Dispatcher module. - * This handler is extern in Security Dispatcher. - * - * @param[in] p_event The event that has happened. - */ -void sm_smd_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_CONN_SEC_PARAMS_REQ: - params_req_process(p_event); - break; - case PM_EVT_SLAVE_SECURITY_REQ: - sec_req_process(p_event); - /* fallthrough */ - default: - // Forward the event to all registered Security Manager event handlers. - evt_forward(p_event); - break; - } -} - - -/**@brief Function for checking our user flags for pending calls to @ref smd_link_secure. - * - * @details This function will attempt to perform any pending calls. - * - * @param[in] flag_id The user flag to check. Must be either @ref m_flag_link_secure_pending_busy - * or @ref m_flag_link_secure_pending_flash_full. - */ -static void link_secure_pending_process(ble_conn_state_user_flag_id_t flag_id) -{ - sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); - if (sdk_mapped_flags_any_set(flag_collection)) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); - if (pending) - { - bool force_repairing = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_force_repairing); - bool null_params = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_null_params); - - ret_code_t err_code = link_secure(conn_handle_list.flag_keys[i], null_params, force_repairing, true); // If this fails, it will be automatically retried. - UNUSED_VARIABLE(err_code); - } - } - } -} - - -/**@brief Function for checking our user flags for pending calls to @ref smd_params_reply. - * - * @details This function will attempt to perform any pending calls. - * - * @param[in] flag_id The user flag to check. Must be either @ref m_flag_params_reply_pending_busy - * or @ref m_flag_params_reply_pending_flash_full. - */ -static void params_reply_pending_process(ble_conn_state_user_flag_id_t flag_id) -{ - sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); - if (sdk_mapped_flags_any_set(flag_collection)) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); - if (pending) - { - smd_params_reply_perform(conn_handle_list.flag_keys[i], NULL); - } - } - } -} - - -/**@brief Event handler for events from the Peer Database module. - * This handler is extern in Peer Database. - * - * @param[in] p_event The event that has happened. - */ -void sm_pdb_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_FLASH_GARBAGE_COLLECTED: - params_reply_pending_process(m_flag_params_reply_pending_flash_full); - link_secure_pending_process(m_flag_link_secure_pending_flash_full); - /* fallthrough */ - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - case PM_EVT_PEER_DATA_UPDATE_FAILED: - case PM_EVT_PEER_DELETE_SUCCEEDED: - case PM_EVT_PEER_DELETE_FAILED: - params_reply_pending_process(m_flag_params_reply_pending_busy); - link_secure_pending_process(m_flag_link_secure_pending_busy); - break; - default: - // Do nothing. - break; - } -} - - -/**@brief Funtion for initializing a BLE Connection State user flag. - * - * @param[out] flag_id The flag to initialize. - */ -static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) -{ - if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - *p_flag_id = ble_conn_state_user_flag_acquire(); - } -} - - -ret_code_t sm_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - flag_id_init(&m_flag_link_secure_pending_busy); - flag_id_init(&m_flag_link_secure_pending_flash_full); - flag_id_init(&m_flag_link_secure_force_repairing); - flag_id_init(&m_flag_link_secure_null_params); - flag_id_init(&m_flag_params_reply_pending_busy); - flag_id_init(&m_flag_params_reply_pending_flash_full); - - if (m_flag_params_reply_pending_flash_full == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -void sm_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - NRF_PM_DEBUG_CHECK(p_ble_evt != NULL); - - smd_ble_evt_handler(p_ble_evt); - link_secure_pending_process(m_flag_link_secure_pending_busy); -} - - -/**@brief Funtion for checking whether security parameters are valid. - * - * @param[out] p_sec_params The security parameters to verify. - * - * @return Whether the security parameters are valid. - */ -static bool sec_params_verify(ble_gap_sec_params_t * p_sec_params) -{ - // NULL check. - if (p_sec_params == NULL) - { - return false; - } - - // OOB not allowed unless MITM. - if (!p_sec_params->mitm && p_sec_params->oob) - { - return false; - } - - // IO Capabilities must be one of the valid values from @ref BLE_GAP_IO_CAPS. - if (p_sec_params->io_caps > BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY) - { - return false; - } - - // Must have either IO capabilities or OOB if MITM. - if (p_sec_params->mitm && (p_sec_params->io_caps == BLE_GAP_IO_CAPS_NONE) && !p_sec_params->oob) - { - return false; - } - - // Minimum key size cannot be larger than maximum key size. - if (p_sec_params->min_key_size > p_sec_params->max_key_size) - { - return false; - } - - // Key size cannot be below 7 bytes. - if (p_sec_params->min_key_size < 7) - { - return false; - } - - // Key size cannot be above 16 bytes. - if (p_sec_params->max_key_size > 16) - { - return false; - } - - // Signing is not supported. - if (p_sec_params->kdist_own.sign || p_sec_params->kdist_peer.sign) - { - return false; - } - - // link bit must be 0. - if (p_sec_params->kdist_own.link || p_sec_params->kdist_peer.link) - { - return false; - } - - // If bonding is not enabled, no keys can be distributed. - if (!p_sec_params->bond && ( p_sec_params->kdist_own.enc - || p_sec_params->kdist_own.id - || p_sec_params->kdist_peer.enc - || p_sec_params->kdist_peer.id)) - { - return false; - } - - // If bonding is enabled, one or more keys must be distributed. - if ( p_sec_params->bond - && !p_sec_params->kdist_own.enc - && !p_sec_params->kdist_own.id - && !p_sec_params->kdist_peer.enc - && !p_sec_params->kdist_peer.id) - { - return false; - } - - return true; -} - - -ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (p_sec_params == NULL) - { - mp_sec_params = NULL; - m_sec_params_set = true; - return NRF_SUCCESS; - } - else if (sec_params_verify(p_sec_params)) - { - m_sec_params = *p_sec_params; - mp_sec_params = &m_sec_params; - m_sec_params_set = true; - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } -} - - -void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); - - smd_conn_sec_config_reply(conn_handle, p_conn_sec_config); -} - - -ret_code_t sm_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - VERIFY_PARAM_NOT_NULL(p_context); - - sec_params_reply_context_t * p_sec_params_reply_context = (sec_params_reply_context_t *)p_context; - if (p_sec_params == NULL) - { - // Set the store pointer to NULL, so that NULL is passed to the SoftDevice. - p_sec_params_reply_context->p_sec_params = NULL; - } - else if (sec_params_verify(p_sec_params)) - { - // Copy the provided sec_params into the store. - p_sec_params_reply_context->sec_params_mem = *p_sec_params; - p_sec_params_reply_context->p_sec_params = &p_sec_params_reply_context->sec_params_mem; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } - p_sec_params_reply_context->params_reply_called = true; - - return NRF_SUCCESS; -} - - -ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - m_p_public_key = p_public_key; - - return NRF_SUCCESS; -} - - -ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret = link_secure(conn_handle, false, force_repairing, false); - return ret; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h deleted file mode 100644 index dda231cb72..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef SECURITY_MANAGER_H__ -#define SECURITY_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "security_dispatcher.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup security_manager Security Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and - * encryption, including flash storage of shared data. - */ - - -/**@brief Function for initializing the Security Manager module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t sm_init(void); - - -/**@brief Function for dispatching SoftDevice events to the Security Manager module. - * - * @param[in] ble_evt The SoftDevice event. - */ -void sm_ble_evt_handler(ble_evt_t const * ble_evt); - - -/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. - * - * @details Until this is called, all bonding procedures initiated by the peer will be rejected. - * This function can be called multiple times, even with NULL p_sec_params, in which case - * it will go back to rejecting all procedures. - * - * @param[in] p_sec_params The security parameters to use for this link. Can be NULL to reject - * all pairing procedures. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters. - */ -ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing security parameters for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Security Manager event handler returns. If - * it is not called in time, the parameters given in @ref sm_sec_params_set are used. See - * @ref pm_conn_sec_config_t for the value of the default. - * - * @param[in] conn_handle The connection to set the parameters for. - * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. - * @param[in] p_context The context found in the request event that this function replies to. - * - * @retval NRF_SUCCESS Successful reply. - * @retval NRF_ERROR_NULL p_context was null. - * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t sm_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context); - - -/**@brief Experimental function for specifying the public key to use for LESC operations. - * - * @details This function can be called multiple times. The specified public key will be used for - * all subsequent LESC (LE Secure Connections) operations until the next time this function - * is called. - * - * @note The key must continue to reside in application memory as it is not copied by Peer Manager. - * - * @param[in] p_public_key The public key to use for all subsequent LESC operations. - * - * @retval NRF_SUCCESS Pairing initiated successfully. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); - - - -/**@brief Function for initiating security on the link, with the specified parameters. - * - * @note If the connection is a peripheral connection, this will send a security request to the - * master, but the master is not obligated to initiate pairing or encryption in response. - * @note If the connection is a central connection and a key is available, the parameters will be - * used to determine whether to re-pair or to encrypt using the existing key. If no key is - * available, pairing will be started. - * - * @param[in] conn_handle Handle of the connection to initiate pairing on. - * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether - * an encryption key already exists. This argument is only relevant for - * the central role. Recommended value: false - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_NOT_FOUND Security parameters have not been set. - * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, - * or the link is disconnecting. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* SECURITY_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132_FULL/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132_FULL/mbed_lib.json index 158c66c33f..8d58f47ca1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132_FULL/mbed_lib.json +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132_FULL/mbed_lib.json @@ -12,8 +12,8 @@ "NRF_SDH_ENABLED=1", "NRF_SDH_BLE_ENABLED=1", "PEER_MANAGER_ENABLED=1", - "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", - "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=1", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=3", "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", "NRF_SDH_BLE_SERVICE_CHANGED=1", "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23", diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140_FULL/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140_FULL/mbed_lib.json index 838a47704b..434fb9659a 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140_FULL/mbed_lib.json +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140_FULL/mbed_lib.json @@ -12,8 +12,8 @@ "NRF_SDH_ENABLED=1", "NRF_SDH_BLE_ENABLED=1", "PEER_MANAGER_ENABLED=1", - "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", - "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=1", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=3", "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", "NRF_SDH_BLE_SERVICE_CHANGED=1", "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23",