diff --git a/features/FEATURE_BLE/ble/ArrayView.h b/features/FEATURE_BLE/ble/ArrayView.h new file mode 100644 index 00000000000..5cf7336c1dd --- /dev/null +++ b/features/FEATURE_BLE/ble/ArrayView.h @@ -0,0 +1,165 @@ +/* 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 BLE_ARRAY_VIEW_H_ +#define BLE_ARRAY_VIEW_H_ + +#include +#include + +namespace ble { + +/** + * Immutable view to an array. + */ +template +struct ArrayView { + + /** + * construct an array view to an empty array + */ + ArrayView() : _array(0), _size(0) { } + + /** + * construct an array view from a pointer. + * and its size. + */ + ArrayView(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct an array view from the reference to an array. + */ + template + ArrayView(T (&elements)[Size]): + _array(elements), _size(Size) { } + + /** + * Return the size of the array viewed. + */ + size_t size() const { + return _size; + } + + /** + * Access to a mutable element of the array. + */ + T& operator[](size_t index) { + return _array[index]; + } + + /** + * Access to an immutable element of the array. + */ + const T& operator[](size_t index) const { + return _array[index]; + } + + /** + * Get the pointer to the array + */ + T* data() { + return _array; + } + + /** + * Get the pointer to the const array + */ + const T* data() const { + return _array; + } + + /** + * Equality operator + */ + friend bool operator==(const ArrayView& lhs, const ArrayView& rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + } + + /** + * Not equal operator + */ + friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs) { + return !(lhs == rhs); + } + +private: + T* const _array; + const size_t _size; +}; + + +/** + * Generate an array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The array_view to elements. + */ +template +ArrayView make_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate an array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The array_view to array_ptr with a size of array_size. + */ +template +ArrayView make_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +/** + * Generate a const array view from a C/C++ array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param elements The array viewed. + * @return The ArrayView to elements. + */ +template +ArrayView make_const_ArrayView(T (&elements)[Size]) { + return ArrayView(elements); +} + +/** + * Generate a const array view from a C/C++ pointer and the size of the array. + * This helper avoid the typing of template parameter when ArrayView are + * created 'inline'. + * @param array_ptr The pointer to the array to view. + * @param array_size The size of the array. + * @return The ArrayView to array_ptr with a size of array_size. + */ +template +ArrayView make_const_ArrayView(T* array_ptr, size_t array_size) { + return ArrayView(array_ptr, array_size); +} + +} // namespace ble + +#endif /* BLE_ARRAY_VIEW_H_ */ diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h new file mode 100644 index 00000000000..f20f03c432a --- /dev/null +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -0,0 +1,77 @@ +/* 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 BLE_TYPES_H_ +#define BLE_TYPES_H_ + +#include +#include + +namespace ble { + +/** + * A connection handle is an unsigned integer capable of holding a pointer. + * The real type (either a pointer to an object or an integer) is opaque and + * platform dependent. + */ +typedef uintptr_t connection_handle_t; + +/** + * Model an attribute handle in a GATT database. + */ +typedef uint16_t attribute_handle_t; + + + /** + * Model an inclusive range of GATT attributes handles. + */ +struct attribute_handle_range_t { + attribute_handle_t begin; + attribute_handle_t end; + + friend bool operator==( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return (lhs.begin == rhs.begin) && (lhs.end == rhs.end); + } + + friend bool operator!=( + const attribute_handle_range_t& lhs, const attribute_handle_range_t& rhs + ) { + return !(lhs == rhs); + } +}; + + +/** + * Construct an attribute_handle_range_t from its start and end handle. + * @note This function is defined instead of a constructor to keep "POD-ness" + * of attribute_handle_range_t. + */ +static inline attribute_handle_range_t attribute_handle_range( + attribute_handle_t begin, + attribute_handle_t end +) { + attribute_handle_range_t result = { + begin, + end + }; + return result; +} + +} // namespace ble + +#endif /* BLE_TYPES_H_ */ diff --git a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h index 0349318b79e..e50180809a3 100644 --- a/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h +++ b/features/FEATURE_BLE/ble/CharacteristicDescriptorDiscovery.h @@ -70,6 +70,11 @@ class CharacteristicDescriptorDiscovery { * status of the discovery operation */ ble_error_t status; + + /** + * error code associated with the status if any. + */ + uint8_t error_code; }; /** diff --git a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h index 3529c360ad8..4fcd719dc95 100644 --- a/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h +++ b/features/FEATURE_BLE/ble/DiscoveredCharacteristic.h @@ -22,7 +22,7 @@ #include "GattAttribute.h" #include "GattClient.h" #include "CharacteristicDescriptorDiscovery.h" -#include "ble/DiscoveredCharacteristicDescriptor.h" +#include "DiscoveredCharacteristicDescriptor.h" /** * @brief Representation of a characteristic discovered during a GattClient diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 5a01e4e9a4b..1f8c62cb69f 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -17,6 +17,7 @@ #ifndef __GAP_H__ #define __GAP_H__ +#include "BLETypes.h" #include "ble/BLEProtocol.h" #include "GapAdvertisingData.h" #include "GapAdvertisingParams.h" @@ -171,7 +172,7 @@ class Gap { /** * Type for connection handle. */ - typedef uint16_t Handle_t; + typedef ble::connection_handle_t Handle_t; /** * Structure containing GAP connection parameters. When in peripheral role diff --git a/features/FEATURE_BLE/ble/GattAttribute.h b/features/FEATURE_BLE/ble/GattAttribute.h index 119c68c173d..1011bc0d53c 100644 --- a/features/FEATURE_BLE/ble/GattAttribute.h +++ b/features/FEATURE_BLE/ble/GattAttribute.h @@ -18,6 +18,7 @@ #define __GATT_ATTRIBUTE_H__ #include "UUID.h" +#include "BLETypes.h" /** * Instances of this class encapsulate the data that belongs to a Bluetooth Low @@ -29,7 +30,7 @@ class GattAttribute { * Type for the handle or ID of the attribute in the ATT table. These are * unique and are usually generated by the underlying BLE stack. */ - typedef uint16_t Handle_t; + typedef ble::attribute_handle_t Handle_t; /** * Define the value of an invalid attribute handle. */ diff --git a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h index 40c1e61dd67..d8eb362235d 100644 --- a/features/FEATURE_BLE/ble/GattCallbackParamTypes.h +++ b/features/FEATURE_BLE/ble/GattCallbackParamTypes.h @@ -17,6 +17,16 @@ #ifndef __GATT_CALLBACK_PARAM_TYPES_H__ #define __GATT_CALLBACK_PARAM_TYPES_H__ +/** + * Parameter of the callback invoked on a write operation. + * This parameter is used whether a GattServer as received a write operation or + * if the GattClient has completed a write operation. + * + * @important The fields connHandle, handle and writeOp are used in both + * callbacks while: + * - offset, len and data are reserved for GattServer write callbacks. + * - status and error_code are reserved for GattClient write callbacks. + */ struct GattWriteCallbackParams { /** * Enumeration for write operations. @@ -34,22 +44,48 @@ struct GattWriteCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the write operation applies. */ WriteOp_t writeOp; /**< Type of write operation. */ - uint16_t offset; /**< Offset for the write operation. */ - uint16_t len; /**< Length (in bytes) of the data to write. */ + + // Note: offset is used in GattServer while status is used in GattClient + union { + uint16_t offset; /**< Offset for the GattServer write operation. */ + ble_error_t status; /**< Status of the GattClient Write operation */ + }; + + // Note: len is used in GattServer while error_code is used in GattClient + union { + uint16_t len; /**< Length (in bytes) of the data to write (GattServer). */ + uint8_t error_code; /**< Error code of the GattClient Write operation */ + }; + /** * Pointer to the data to write. * * @note Data might not persist beyond the callback; make a local copy if * needed. + * @note This field is not used by callbacks invoked by the GattClient module. */ const uint8_t *data; }; +/** + * Parameter of the callback invoked on a read operation. + * This parameter is used whether a GattServer as received a read operation or + * if the GattClient has completed a read operation. + * + * @important The fields connHandle, handle and offset are used in both + * callbacks while: + * - len and data are reserved for GattServer read callbacks. + * - status and error_code are reserved for GattClient read callbacks. + */ struct GattReadCallbackParams { Gap::Handle_t connHandle; /**< The handle of the connection that triggered the event. */ GattAttribute::Handle_t handle; /**< Attribute Handle to which the read operation applies. */ uint16_t offset; /**< Offset for the read operation. */ - uint16_t len; /**< Length (in bytes) of the data to read. */ + union { + uint16_t len; /**< Length (in bytes) of the data to read. */ + uint8_t error_code; /**< Error code if any (GattClient) */ + }; + /** * Pointer to the data read. * @@ -57,6 +93,7 @@ struct GattReadCallbackParams { * needed. */ const uint8_t *data; + ble_error_t status; /**< Status of the operation BLE_ERROR_NONE in case of success or the error in case of error */ }; enum GattAuthCallbackReply_t { diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index dc194f50b36..5f043ebb22a 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -80,6 +80,9 @@ class GattClient { * The following functions are meant to be overridden in the platform-specific sub-class. */ public: + + virtual ~GattClient() { } + /** * Launch service discovery. Once launched, application callbacks will be * invoked for matching services or characteristics. isServiceDiscoveryActive() diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h new file mode 100644 index 00000000000..8b525e8d06e --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -0,0 +1,154 @@ +/* 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_GENERIC_GATT_CLIENT +#define MBED_BLE_GENERIC_GATT_CLIENT + +#include +#include "ble/GattClient.h" +#include "ble/pal/PalGattClient.h" + +// IMPORTANT: private header. Not part of the public interface. + +namespace ble { +namespace generic { + +// forward declarations +struct procedure_control_block_t; +struct discovery_control_block_t; +struct read_control_block_t; +struct write_control_block_t; +struct descriptor_discovery_control_block_t; + +/** + * Generic implementation of the GattClient. + * It requires a pal::GattClient injected at construction site. + * @important: Not part of the public interface of BLE API. + */ +class GenericGattClient : public GattClient { + + // give access to control block classes + friend struct procedure_control_block_t; + friend struct discovery_control_block_t; + friend struct read_control_block_t; + friend struct write_control_block_t; + friend struct descriptor_discovery_control_block_t; + +public: + /** + * Create a GenericGattClient from a pal::GattClient + */ + GenericGattClient(pal::GattClient* pal_client); + + /** + * @see GattClient::launchServiceDiscovery + */ + virtual ble_error_t launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid + ); + + /** + * @see GattClient::isServiceDiscoveryActive + */ + virtual bool isServiceDiscoveryActive() const; + + /** + * @see GattClient::terminateServiceDiscovery + */ + virtual void terminateServiceDiscovery(); + + /** + * @see GattClient::read + */ + virtual ble_error_t read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset + ) const; + + /** + * @see GattClient::write + */ + virtual ble_error_t write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value + ) const; + + /** + * @see GattClient::onServiceDiscoveryTermination + */ + virtual void onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback + ); + + /** + * @see GattClient::discoverCharacteristicDescriptors + */ + virtual ble_error_t discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ); + + /** + * @see GattClient::isCharacteristicDescriptorDiscoveryActive + */ + virtual bool isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic + ) const; + + /** + * @see GattClient::terminateCharacteristicDescriptorDiscovery + */ + virtual void terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic + ); + + /** + * @see GattClient::reset + */ + virtual ble_error_t reset(void); + +private: + procedure_control_block_t* get_control_block(Gap::Handle_t connection); + const procedure_control_block_t* get_control_block(Gap::Handle_t connection) const; + void insert_control_block(procedure_control_block_t* cb) const; + void remove_control_block(procedure_control_block_t* cb) const; + + void on_termination(Gap::Handle_t connection_handle); + void on_server_message_received(connection_handle_t, const pal::AttServerMessage&); + void on_server_response(connection_handle_t, const pal::AttServerMessage&); + void on_server_event(connection_handle_t, const pal::AttServerMessage&); + void on_transaction_timeout(connection_handle_t); + + uint16_t get_mtu(Gap::Handle_t connection) const; + + pal::GattClient* const _pal_client; + ServiceDiscovery::TerminationCallback_t _termination_callback; + mutable procedure_control_block_t* control_blocks; +}; + +} +} + +#endif /* MBED_BLE_GENERIC_GATT_CLIENT */ diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h new file mode 100644 index 00000000000..56bd1a2f062 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -0,0 +1,687 @@ +/* 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 BLE_PAL_ATTCLIENT_H_ +#define BLE_PAL_ATTCLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" +#include "platform/Callback.h" +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Send attribute protocol requests to an ATT server. It also handle reception + * of ATT response and server indication/notification. + * + * Every request send and response or response event received is for a specified + * connection. + * + * @warning This class should not be used outside mbed BLE, availability is not + * guaranteed for all ports. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F + */ +struct AttClient { + /** + * Initialization of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the ATT operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the ATT operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Send an exchange MTU request which negotiate the size of the MTU used by + * the connection. + * + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * + * The mtu choosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occured then the mtu used remains the default value. + * + * @param connection The handle of the connection to send this request to. + * + * @return BLE_ERROR_NONE if the request has been succesfully sent or the + * appropriate error otherwise. + * + * @see ble::pal::AttExchangeMTUResponse The type of response received from + * the server + * @see ble::pal::AttErrorResponse::REQUEST_NOT_SUPPORTED The error code + * returned by the server in case of error. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.1 + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Send a find information request to a server in order to obtain the + * mapping of attribute handles with their associated types. + * + * The server will reply with a ble::pal::AttFindInformationResponse + * containing at least one [attribute handle, attribute type] pair. If the + * last handle in the response is not equal to the end handle of the finding + * range then this request can be issued again with an updated range (begin + * equal to last handle received + 1) to discover the remaining attributes. + * + * To discover the whole ATT server, the first find information request + * should have a discovery range of [0x0001 - 0xFFFF]. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The attribute range where handle-type informations + * should be discovered. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.1 + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Send a Find By Type Value Request which retrieve the handles of attributes + * that have known 16-bit UUID attribute type and known attribute value. + * + * The server should reply with a ble::pal::AttFindByTypeValueResponse + * containing the handle (or handle range in case of grouping attributes) of + * the attribute found. + * + * If not all attributes can be contained in the response it is necessary to + * send again this request with an updated range to continue the discovery. + * + * The server can send a ble::pal::AttErrorResponse with the code + * ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND if no attributes have + * been found in the range specified. The attribute handle in the response + * is then equal to the first handle of the discovery range. + * + * If the range is malformed the server will reply a + * ble::pal::AttErrorResponse with the error code ble::pal::INVALID_HANDLE. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param discovery_range The handle range where attributes with type and + * value are searched. + * @param type The type of attribute to find (it is a 16 bit UUID). + * @param value The value of the attributes to found. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.3 + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) = 0; + + /** + * Send a Read By Type Request used to obtain the values of attributes where + * the attribute type is known but the handle is not known. + * + * If attributes with the type requested are present in the range, the server + * should reply with a ble::pal::AttReadByTypeResponse. If the response does + * not cover the full range, the request should be sent again with an updated + * range. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If there is no + * attributes matching type in the range. + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range The handle range where attributes with the given type + * should be read. + * @param type The type of attributes to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.1 + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) = 0; + + /** + * Send a Read Request to read the value of an attribute in the server. + * + * In case of success, the server will reply with a ble::pal::AttReadResponse. + * containing the value of the attribute. If the length of the value in the + * response is equal to (mtu - 1) then the remaining part of the value can + * be obtained by a read_blob_request. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.3 + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Send a read blob request to a server to read a part of the value of an + * attribute at a given offset. + * + * In case of success, the server will reply with a ble::pal::AttReadBlobResponse + * containing the value read. If the value of the attribute starting at the + * offset requested is longer than (mtu - 1) octets then only the first + * (mtu - 1) octets will be present in the response. + * The remaining octets can be acquired by another Read Blob Request with an + * updated index. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the attribute handle + * is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If the attribute + * value cannot be read. + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the offset is greater + * than the attribute length. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_LONG: If the attribute + * value has a length that is less than or equal to (mtu - 1). + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to read. + * @param offset The offset of the first octet to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.5 + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Send a read multiple request to the server. It is used to read two or more + * attributes values at once. + * + * In case of success, the server will reply with a + * ble::pal::AttReadMultipleResponse containing the concatenation of the + * values read. Given that values are concatained, all attributes values + * should be of fixed size except for the last one. The concatained value + * is also truncated to (mtu - 1) if it doesn't fit in the response. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If any of the attribute + * handle is invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read any of the attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read any of the + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read any of the attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * The first attribute causing the error is reporter in the handle_in_error + * field in the error response. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handles Set of attribute handles to read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.7 + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) = 0; + + /** + * Send a read by group type request to the server. It is used to get + * informations about grouping attribute of a given type on a server. + * + * The server will reply with a ble::pal::ReadByGroupTypeResponse containing + * informations about the grouping attribute found. Informations are: + * - handle of the grouping attribute. + * - last handle of the group . + * - attribute value. + * + * If the last handle received is not the last handle of the discovery range + * then it is necessary to send another request with a discovery range + * updated to: [last handle + 1 : end]. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the range of handle + * provided is invalid. + * - ble::pal::AttErrorResponse::UNSUPPORTED_GROUP_TYPE: if the group type + * is not a supported grouping attribute. + * - ble::pal::AttErrorResponse::ATTRIBUTE_NOT_FOUND: If no attribute with + * the given type exists within the range provided. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to read the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to read the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to read the requested attributes. + * - ble::pal::AttErrorResponse::READ_NOT_PERMITTED: If any of the + * attributes value cannot be read. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param read_range Range where this request apply. + * @param group_type Type of the grouping attribute to find and read. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.9 + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) = 0; + + /** + * Send a write request to the server to write the value of an attribute. + * + * In case of success, the server will reply with a + * ble::pal::AttWriteResponse to acknowledge that the write operation went + * well. + * + * If the attribute value has a variable length, then the attribute value + * shall be truncated or lengthened to match the length of the value in the + * request. + * + * If the attribute value has a fixed length and the Attribute Value parameter length + * is less than or equal to the length of the attribute value, the octets of the + * attribute value parameter length shall be written; all other octets in this attribute + * value shall be unchanged. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * value to write exceeds the maximum valid length or of the attribute + * value; whether the attribute has a variable length value or a fixed + * length value. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.1 + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write command to the server. A write command is similar to a write + * request except that it won't receive any response from the server + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 3). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.3 + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a signed write command to the server. Behaviour is similar to a write + * command except that 12 bytes of the mtu are reserved for the authentication + * signature. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle Handle of the attribute to write. + * @param value Value to write. It can't be longer than (mtu - 15). + * + * @note the authentication signature to send with this request is + * computed by the implementation following the rules defined in BLUETOOTH + * SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.4 + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * The Prepare Write Request is used to request the server to prepare to + * write the value of an attribute. The client can send multiple prepare + * write request which will be put in a queue until the client send an + * Execute Write Request which will execute sequentially the write request + * in the queue. + * + * In case of success the server will respond with a + * ble::pal::AttPrepareWriteResponse containing the values (attribute handle, + * offset and value) present in the write request. + * + * If a prepare write request is rejected by the server, the state queue of + * the prepare write request queue remains unaltered. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_HANDLE: If the handle to write is + * invalid. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHENTICATION: If the client + * security is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_AUTHORIZATION: If the client + * authorization is not sufficient to write the requested attribute. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: If the + * client has an insufficient encryption key size to write the requested + * attributes. + * - ble::pal::AttErrorResponse::INSUFFICIENT_ENCRYPTION: If the client + * has not enabled encryption required to write the requested attributes. + * - ble::pal::AttErrorResponse::WRITE_NOT_PERMITTED: If the attribute + * value cannot be written due to permission. + * - ble::pal::PREPARE_QUEUE_FULL: If the queue of prepare write request + * is full. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param attribute_handle The handle of the attribute to be written. + * @param offset The offset of the first octet to be written. + * @param value The value of the attribute to be written. It can't be longer + * than (mtu - 5). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.1 + * + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) = 0; + + /** + * Send an Execute Write Request to the server. This request will instruct + * the server to execute or cancel the prepare write requests currently held + * in the prepare queue from this client. + * + * If the execute parameter is set to true, the server should execute the + * request held in the queue. If the parameter is equal to false then the + * server should cancel the requests in the queue. + * + * In case of success, the server will respond with a + * ble::pal::AttExecuteWriteResponse indicating that the request was correctly + * handled. + * + * In case of error, the server will send a ble::pal::AttErrorResponse. The + * error code depends on the situation: + * - ble::pal::AttErrorResponse::INVALID_OFFSET: If the value offset is + * greater than the current length of the attribute to write. + * - ble::pal::AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: If the + * length of the value write exceeds the length of the attribute value + * about to be written. + * Higher layer can also set an application error code (0x80 - 0x9F). + * + * The error response will contains the attribute handle which as caused the + * error and the remaining of the prepare queue is discarded. The state of + * the attributes that were to be written from the prepare queue is not + * defined in this case. + * + * @param connection_handle The handle of the connection to send this + * request to. + * @param execute Boolean indicating if the prepare queue should be executed + * or cleared. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or an + * appropriate error otherwise. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.3 + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + AttClient() { } + + virtual ~AttClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + AttClient(const AttClient&); + AttClient& operator=(const AttClient&); +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATTCLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h new file mode 100644 index 00000000000..d99a55e4978 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -0,0 +1,297 @@ +/* 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 BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ +#define BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ + +#include "AttClient.h" +#include "PalGattClient.h" + +namespace ble { +namespace pal { + +/** + * Adapt a pal::AttClient into a pal::GattClient. + * + * This class let vendors define their abstraction layer in term of an AttClient + * and adapt any AttClient into a GattClient. + */ +class AttClientToGattClientAdapter : public GattClient { + +public: + static const uint16_t END_ATTRIBUTE_HANDLE = 0xFFFF; + static const uint16_t SERVICE_TYPE_UUID = 0x2800; + static const uint16_t INCLUDE_TYPE_UUID = 0x2802; + static const uint16_t CHARACTERISTIC_TYPE_UUID = 0x2803; + + /** + * Construct an instance of GattClient from an instance of AttClient. + * @param client The client to adapt. + */ + AttClientToGattClientAdapter(AttClient& client) : + GattClient(), _client(client) { + _client.when_server_message_received( + mbed::callback(this, &AttClientToGattClientAdapter::on_server_event) + ); + _client.when_transaction_timeout( + mbed::callback( + this, &AttClientToGattClientAdapter::on_transaction_timeout + ) + ); + } + + /** + * @see ble::pal::GattClient::exchange_mtu + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) { + return _client.exchange_mtu_request(connection); + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + return _client.get_mtu_size(connection_handle, mtu_size); + } + + /** + * @see ble::pal::GattClient::discover_primary_service + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) { + return _client.read_by_group_type_request( + connection, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_primary_service_by_service_uuid + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_begining, + const UUID& uuid + ) { + return _client.find_by_type_value_request( + connection_handle, + attribute_handle_range(discovery_range_begining, END_ATTRIBUTE_HANDLE), + SERVICE_TYPE_UUID, + ArrayView( + uuid.getBaseUUID(), + (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) ? 2 : UUID::LENGTH_OF_LONG_UUID + ) + ); + } + + /** + * @see ble::pal::GattClient::find_included_service + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) { + return _client.read_by_type_request( + connection_handle, + service_range, + INCLUDE_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_of_a_service + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + return _client.read_by_type_request( + connection_handle, + discovery_range, + CHARACTERISTIC_TYPE_UUID + ); + } + + /** + * @see ble::pal::GattClient::discover_characteristics_descriptors + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) { + return _client.find_information_request( + connection_handle, + descriptors_discovery_range + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_value + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + return _client.read_request( + connection_handle, + attribute_handle + ); + } + + /** + * @see ble::pal::GattClient::read_using_characteristic_uuid + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) { + return _client.read_by_type_request( + connection_handle, + read_range, + uuid + ); + } + + /** + * @see ble::pal::GattClient::read_attribute_blob + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + return _client.read_blob_request( + connection_handle, + attribute_handle, + offset + ); + } + + /** + * @see ble::pal::GattClient::read_multiple_characteristic_values + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) { + return _client.read_multiple_request( + connection_handle, + characteristic_value_handles + ); + } + + /** + * @see ble::pal::GattClient::write_without_response + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::signed_write_without_response + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) { + return _client.signed_write_command( + connection_handle, + characteristic_value_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::write_attribute + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + return _client.write_request( + connection_handle, + attribute_handle, + value + ); + } + + /** + * @see ble::pal::GattClient::queue_prepare_write + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) { + return _client.prepare_write_request( + connection_handle, + characteristic_value_handle, + offset, + value + ); + } + + /** + * @see ble::pal::GattClient::execute_write_queue + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) { + return _client.execute_write_request(connection_handle, execute); + } + + /** + * @see ble::pal::GattClient::initialize + */ + virtual ble_error_t initialize() { + return _client.initialize(); + } + + /** + * @see ble::pal::GattClient::terminate + */ + virtual ble_error_t terminate() { + return _client.initialize(); + } + +private: + AttClient& _client; +}; + +} // namespace pal +} // namespace ble + + +#endif /* BLE_PAL_ATTCLIENTTOGATTCLIENTADAPTER_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/AttServerMessage.h b/features/FEATURE_BLE/ble/pal/AttServerMessage.h new file mode 100644 index 00000000000..1862549673d --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/AttServerMessage.h @@ -0,0 +1,771 @@ +/* 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 BLE_PAL_ATT_SERVER_MESSAGE_H_ +#define BLE_PAL_ATT_SERVER_MESSAGE_H_ + +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" + +namespace ble { +namespace pal { + +/** + * Operation code defined for attribute operations + * @note see: BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.8 + */ +struct AttributeOpcode { + enum Code { + ERROR_RESPONSE = 0x01, /// Opcode of an AttErrorResponse + EXCHANGE_MTU_REQUEST = 0x02, + EXCHANGE_MTU_RESPONSE = 0x03, /// OpCode of an AttExchangeMTUResponse + FIND_INFORMATION_REQUEST = 0x04, + FIND_INFORMATION_RESPONSE = 0x05, /// OpCode of an AttFindInformationResponse + FIND_BY_TYPE_VALUE_REQUEST = 0x06, + FIND_BY_VALUE_TYPE_RESPONSE = 0x07, /// OpCode of an AttFindByTypeValueResponse + READ_BY_TYPE_REQUEST = 0x08, + READ_BY_TYPE_RESPONSE = 0x09, /// Opcode of an AttReadByTypeResponse + READ_REQUEST = 0x0A, + READ_RESPONSE = 0x0B, /// Opcode of an AttReadResponse + READ_BLOB_REQUEST = 0x0C, + READ_BLOB_RESPONSE = 0x0D, /// Opcode of an AttReadBlobResponse + READ_MULTIPLE_REQUEST = 0x0E, + READ_MULTIPLE_RESPONSE = 0x0F, /// Opcode of an AttReadMultipleResponse + READ_BY_GROUP_TYPE_REQUEST = 0x10, + READ_BY_GROUP_TYPE_RESPONSE = 0x11, /// Opcode of an AttReadByGroupTypeResponse + WRITE_REQUEST = 0x12, + WRITE_RESPONSE = 0x13, /// Opcode of an AttWriteResponse + WRITE_COMMAND = 0x52, + SIGNED_WRITE_COMMAND = 0xD2, + PREPARE_WRITE_REQUEST = 0x16, + PREPARE_WRITE_RESPONSE = 0x17, /// Opcode of an AttPrepareWriteResponse + EXECUTE_WRITE_REQUEST = 0x18, + EXECUTE_WRITE_RESPONSE = 0x19, /// Opcode of an AttExecuteWriteResponse + HANDLE_VALUE_NOTIFICATION = 0x1B, + HANDLE_VALUE_INDICATION = 0x1D + }; + + /** + * Construct an AttributeOpcode from a Code. + */ + AttributeOpcode(Code value) : _value(value) { } + + /** + * Equality comparison operator between two AttributeOpcode + */ + friend bool operator==(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value == rhs._value; + } + + /** + * Non equality comparison operator between two AttributeOpcode + */ + friend bool operator!=(AttributeOpcode lhs, AttributeOpcode rhs) { + return lhs._value != rhs._value; + } + + /** + * implicit cast to uint8_t. + * Allows AttributeOpcode to be used in switch statements. + */ + operator uint8_t() const { + return _value; + } + +private: + uint8_t _value; +}; + + +/** + * Base class for Attribute Server Message. + * The correct type of the instance can be determined with the attribute opcode. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.1 + */ +struct AttServerMessage { + /** + * Op code used to identify the type of the attribute response. + */ + const AttributeOpcode opcode; + +protected: + /** + * Construction of an AttResponse is reserved for descendent of the class + */ + AttServerMessage(AttributeOpcode opcode_) : opcode(opcode_) { } +}; + + +/** + * Response to a request which can't be performed + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.1.1 + * for details about error response. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.9 + * which details possible error response by requests. + */ +struct AttErrorResponse : public AttServerMessage { + /** + * Construct an attribute error response. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param handle_in_error_ The attribute handle that generated this error + * response. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + attribute_handle_t handle_in_error_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(handle_in_error_), error_code(error_code_) { + } + + /** + * Construct an attribute error response in the case where there was no + * attribute handle in the original response or if the request is not + * supported. + * + * @param request_opcode_ The Attribute opcode of the request that generated + * the error. + * @param error_code The reason why the request has generated an error. + */ + AttErrorResponse( + AttributeOpcode request_opcode_, + uint8_t error_code_ + ) : AttServerMessage(AttributeOpcode::ERROR_RESPONSE), + request_opcode(request_opcode_), + handle_in_error(0x0000), error_code(error_code_) { + } + + /** + * The opcode of the request that generated this error response. + */ + const AttributeOpcode request_opcode; + + /** + * The attribute handle that generated this error response. + * If there was no attribute handle in the original request or if the + * request is not supported, then this field is equal to 0x0000. + */ + const attribute_handle_t handle_in_error; + + /** + * The reason why the request has generated an error response + */ + const uint8_t error_code; + + /** + * List of Error codes for the ATT protocol + */ + enum AttributeErrorCode { + /** The attribute handle given was not valid on this server. */ + INVALID_HANDLE = 0x01, + + /** The attribute cannot be read. */ + READ_NOT_PERMITTED = 0x02, + + /** The attribute cannot be written. */ + WRITE_NOT_PERMITTED = 0x03, + + /** The attribute PDU was invalid. */ + INVALID_PDU = 0x04, + + /** The attribute requires authentication before it can be read or + * written. + */ + INSUFFICIENT_AUTHENTICATION = 0x05, + + /** Attribute server does not support the request received from the + * client. + */ + REQUEST_NOT_SUPPORTED = 0x06, + + /** Offset specified was past the end of the attribute. */ + INVALID_OFFSET = 0x07, + + /** The attribute requires authorization before it can be read or written. */ + INSUFFICIENT_AUTHORIZATION = 0x08, + + /** Too many prepare writes have been queued. */ + PREPARE_QUEUE_FULL = 0x09, + + /** No attribute found within the given attribute handle range. */ + ATTRIBUTE_NOT_FOUND = 0x0A, + + /** The attribute cannot be read using the Read Blob Request. */ + ATTRIBUTE_NOT_LONG = 0x0B, + + /** The Encryption Key Size used for encrypting this link is + * insufficient. + */ + INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0C, + + /** The attribute value length is invalid for the operation. */ + INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0D, + + /** The attribute request that was requested has encountered an error + * that was unlikely, and therefore could not be completed as requested. + */ + UNLIKELY_ERROR = 0x0E, + + /** The attribute requires encryption before it can be read or written. */ + INSUFFICIENT_ENCRYPTION = 0x0F, + + /** The attribute type is not a supported grouping attribute as defined + * by a higher layer specification. + */ + UNSUPPORTED_GROUP_TYPE = 0x10, + + /** Insufficient Resources to complete the request. */ + INSUFFICIENT_RESOURCES = 0x11, + + /* 0x12 - 0x7F => reserved for future use */ + + /* 0x80 - 0x9F => Application Error */ + + /* 0xA0 0xDF => Reserved for future use */ + + /* 0xE0 - 0xFF Common Profile and service Error Codes */ + + /** The Write Request Rejected error code is used when a requested write + * operation cannot be fulfilled for reasons other than permissions. + */ + WRITE_REQUEST_REJECTED = 0xFC, + + /** The Client Characteristic Configuration Descriptor Improperly + * Configured error code is used when a Client Characteristic + * Configuration descriptor is not configured according to the + * requirements of the profile or service. + */ + CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED = 0xFD, + + /** The Procedure Already in Progress error code is used when a profile + * or service request cannot be serviced because an operation that has + * been previously triggered is still in progress + */ + PROCEDURE_ALREADY_IN_PROGRESS = 0xFE, + + /** The Out of Range error code is used when an attribute value is out + * of range as defined by a profile or service specification. + */ + OUT_OF_RANGE = 0xFF + }; +}; + + +/** + * The Exchange MTU Request is used by the client to inform the server of the + * client’s maximum receive MTU size and request the server to respond with its + * maximum rx MTU size. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.2.2 + */ +struct AttExchangeMTUResponse : public AttServerMessage { + /** + * Construct an exchange mtu response containing the max rx mtu of the + * server. + * + * @param server_rx_mtu_ The max rx mtu the server can handle. + */ + AttExchangeMTUResponse(uint16_t server_rx_mtu_) : + AttServerMessage(AttributeOpcode::EXCHANGE_MTU_RESPONSE), + server_rx_mtu(server_rx_mtu_) { + } + + /** + * The max rx mtu the server can handle. + */ + const uint16_t server_rx_mtu; +}; + + +/** + * The Find Information Response is sent in reply to a received Find Information + * Request and contains information about this server. + * + * The Find Information Response contains a sequence of handle-uuid pairs in + * ascending order if attribute handles. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.2 + */ +struct AttFindInformationResponse : public AttServerMessage { + + /** handle-uuid pair */ + struct information_data_t { + attribute_handle_t handle; + UUID uuid; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindInformationResponse() : + AttServerMessage(AttributeOpcode::FIND_INFORMATION_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindInformationResponse() { } + + /** + * Returns the number of information_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Access to information_data_t elements present in the response. + * @note Out of range access is undefined. + */ + virtual information_data_t operator[](size_t index) const = 0; +}; + + +/** + * Find by type value responses are sent in response to find by type value + * request. + * + * The response contains a sequence of Found Attribute Handle, Group End Handle + * pair where: + * - Found Attribute Handle is the handle of an attribute matching the type + * and the value requested. + * - Group End Handle is the end of the attribute group if the attribute found + * is a grouping attribute or the same value as Found Attribute Handle if + * the attribute is not a grouping attribute. + * + * This class should be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.3.4 + */ +struct AttFindByTypeValueResponse : public AttServerMessage { + /** + * Base constructor, setup the OpCode of the response. + */ + AttFindByTypeValueResponse() : + AttServerMessage(AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttFindByTypeValueResponse() { } + + /** + * Returns the number of attribute_handle_range_t present in the response. + */ + virtual std::size_t size() const = 0; + + /** + * Access to the attribute range present in the response. + * @note Out of range access is undefined. + */ + virtual attribute_handle_range_t operator[](size_t index) const = 0; +}; + + +/** + * Response to a Read By Type request. + * + * It contains a list of handle-value pairs where: + * - handle is the handle of the attribute matching the rype requested. + * - value is the value of the attribute found. If the value is longer than + * (mtu - 4) then it can be truncated and read blob request should be used + * to read the remaining octet of the attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.2 + */ +struct AttReadByTypeResponse : public AttServerMessage { + /** + * handle-value pair + */ + struct attribute_data_t { + attribute_handle_t handle; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByTypeResponse() { } + + /** + * Return the number of attribute_data_t presents in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data at index. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The read response is sent in reply to a received Read Request and contains + * the value of the attribute that has been read. + * + * The attribute value shall be set to the value of the attribute identified by + * the attribute handle in the request. If the attribute value is longer than + * (ATT_MTU-1) then the first (ATT_MTU-1) octets shall be included in this + * response. + * + * @note The Read Blob Request would be used to read the remaining octets of a + * long attribute value. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.4 + */ +struct AttReadResponse : public AttServerMessage { + /** + * Construct a Read Response from an array of bytes. + */ + AttReadResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * The Read Blob Response is sent in reply to a received Read Blob Request and + * contains part of the value of the attribute that has been read. + * + * If the offset requested is equal to the length of the attribute then the + * response contains no data and the size of the data returned is equal to 0. + * + * If the value of the attribute starting at the offset requested is longer than + * (mtu - 1) octets then the first (mtu - 1) will be present in the response. + * The remaining octets will be acquired by another Read Blob Request with an + * updated index. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.6 + */ +struct AttReadBlobResponse : public AttServerMessage { + /** + * Construct a read blob response from the value responded. + */ + AttReadBlobResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_BLOB_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + + /** + * Return the pointer to the actual data + */ + const uint8_t* data() const { + return _data.data(); + } + +private: + const ArrayView _data; +}; + + +/** + * Response to a Read Multiple Request. It contains the values of the attributes + * that have been read. + * + * If the set of values that has been read is longer than (mtu - 1) then only + * the first (mtu - 1) octets are included in the response. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.8 + */ +struct AttReadMultipleResponse : public AttServerMessage { + /** + * Construct a Resd Multiple Response from the set of value received. + */ + AttReadMultipleResponse(ArrayView data_) : + AttServerMessage(AttributeOpcode::READ_MULTIPLE_RESPONSE), _data(data_) { + } + + /** + * Return the number of octets presents in the response set of value. + */ + size_t size() const { + return _data.size(); + } + + /** + * Return the octet of the set of value read at the specified index. + * @note Out of range access is undefined. + */ + uint8_t operator[](size_t index) const { + return _data[index]; + } + +private: + const ArrayView _data; +}; + + +/** + * The Read By Group Type Response is sent in reply to a received Read By + * Group Type Request and contains the handles and values of the attributes that + * have been read. + * + * The response is a list of group range-value pair where: + * - group range: The range of the group found where begin is the grouping + * attribute handle and end is the handle of the end of the group. + * - value: The value of the grouping attribute. + * + * This class has to be subclassed by an implementation specific class defining + * the member function size and the subscript operator. + * + * @note The value responded can be trucated if it doesn't fit in the response, + * in that case a Read Blob Request could be used to read the remaining octets. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.4.10 + */ +struct AttReadByGroupTypeResponse : public AttServerMessage { + /** + * Data read from the grouping attribute. + * It includes the range of the group and the value of the attribute. + */ + struct attribute_data_t { + attribute_handle_range_t group_range; + ArrayView value; + }; + + /** + * Base constructor, setup the OpCode of the response. + */ + AttReadByGroupTypeResponse() : + AttServerMessage(AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE) { + } + + /** + * virtual destructor to overide if the sub class needs it. + */ + virtual ~AttReadByGroupTypeResponse() { } + + /** + * Return the number of attribute_data_t present in the response. + */ + virtual size_t size() const = 0; + + /** + * Return the attribute data read at the index specified. + * @note Out of range access is undefined. + */ + virtual attribute_data_t operator[](size_t index) const = 0; +}; + + +/** + * The Write Response is sent in reply to a valid Write Request and + * acknowledges that the attribute has been successfully written. + * It is just a placeholder which indicates the client that the write request + * was successful. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.5.2 + */ +struct AttWriteResponse : public AttServerMessage { + /** + * Construct a write response. + */ + AttWriteResponse() : AttServerMessage(AttributeOpcode::WRITE_RESPONSE) { } +}; + + +/** + * Response to a Prepare Write Request. It acknowledges the client that the + * value has been successfully received and placed in the write queue. + * + * The response contains the same values as the one present in the request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.2 + */ +struct AttPrepareWriteResponse : public AttServerMessage { + /** + * Construct a prepare write response. + * @param handle_ The handle of the attribute to be written. + * @param offset_: The offset of the first octet to be writen. + * @param value_: The value of the attribute to be written at the offset + * indicated. + */ + AttPrepareWriteResponse( + attribute_handle_t handle_, + uint16_t offset_, + ArrayView value_ + ) : AttServerMessage(AttributeOpcode::PREPARE_WRITE_RESPONSE), + attribute_handle(handle_), + offset(offset_), + partial_value(value_) { + } + + /** + * The handle of the attribute to be written. + */ + const attribute_handle_t attribute_handle; + + /** + * The offset of the first octet to be writen. + */ + const uint16_t offset; + + /** + * The value of the attribute to be written at the offset indicated. + */ + const ArrayView partial_value; +}; + + +/** + * The Execute Write Response is sent in response to a received Execute Write + * Request. + * + * It is just a placeholder which indicates the client that the execution of the + * write request has been successfull. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.6.4 + */ +struct AttExecuteWriteResponse : public AttServerMessage { + /** + * Construct an execute write response object. + */ + AttExecuteWriteResponse() : + AttServerMessage(AttributeOpcode::EXECUTE_WRITE_RESPONSE) { + } +}; + + +/** + * Notification of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.1 + */ +struct AttHandleValueNotification : public AttServerMessage { + /** + * Construct an Handle Value Notification from the attribute handle and its + * value notified. + */ + AttHandleValueNotification( + attribute_handle_t attribute_handle, + ArrayView attribute_value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_NOTIFICATION), + attribute_handle(attribute_handle), + attribute_value(attribute_value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +/** + * Indication of an attribute's value sent by the server. + * + * It contains the handle of the attribute and its value. The client should + * respond with and handle value confirmation. + * + * If the attribute value is longer than (mtu - 3) then the value is truncated + * to (mtu - 3) octets to fit in the response and the client will have to use + * a read blob request to read the remaining octets of the attribute. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.4.7.2 + */ +struct AttHandleValueIndication : public AttServerMessage { + /** + * Construct an Handle Value Indication from the attribute handle and its + * value indicated. + */ + AttHandleValueIndication( + attribute_handle_t handle, ArrayView value + ) : AttServerMessage(AttributeOpcode::HANDLE_VALUE_INDICATION), + attribute_handle(handle), attribute_value(value) { + } + + /** + * Handle of the attribute + */ + const attribute_handle_t attribute_handle; + + /** + * The current value of the attribute. + */ + const ArrayView attribute_value; +}; + + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_ATT_SERVER_MESSAGE_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h new file mode 100644 index 00000000000..2152c428f43 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -0,0 +1,642 @@ +/* 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 BLE_PAL_GATT_CLIENT_H_ +#define BLE_PAL_GATT_CLIENT_H_ + +#include "ble/UUID.h" +#include "ble/BLETypes.h" +#include "ble/ArrayView.h" +#include "ble/blecommon.h" + +#include "platform/Callback.h" + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Adaptation layer for a GATT client. + * + * Define the primitive necessary to implement a proper GATT client. These + * primitives are sometime GATT procedure, ATT procedure or a bit of both. + * + * In general, discovery procedures follow strictly GATT formulation while + * attribute manipulation procedures (read/write) follow the ATT formulation + * to avoid multiple identical implementation for characteristic values and + * characteristic descriptors value, it also fill a hole leave by the + * specification which doesn't define any GATT procedure to get the UUID of an + * included service with a 128 bit UUID. + * + * Complementary informations around ATT procedures can be found in the Section + * 3.4 of the Vol3, Part F of the Bluetooth specification while more informations + * around the GATT procedures can be found in the Section 4 of the Vol 3, Part + * G of the Bluetooth specification. + * + * Complete and compliant Gatt Client used by developer is realized at an higher + * level using the primitives defined in this adaptation layer. + * + * If a stack expose the complete ATT layer then it is possible to provide an + * implementation for GattClient by subclassing the AttClient class and use + * the class AttClientToGattClientAdapter + */ +class GattClient { + +public: + /** + * Initialisation of the instance. An implementation can use this function + * to initialise the subsystems needed to realize the operations of this + * interface. + * + * This function has to be called before any other operations. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t initialize() = 0; + + /** + * Termination of the instance. An implementation can use this function + * to release the subsystems initialised to realise the operations of + * this interface. + * + * After a call to this function, initialise should be called again to + * allow usage of the interface. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t terminate() = 0; + + /** + * Negotiate the mtu to use by this connection. + * First the client send to the server the maximum rx mtu that it can receive + * then the client reply with the maximum rx mtu it can receive. + * The mtu chosen for the connection is the minimum of the client Rx mtu + * and server Rx mtu values. + * + * If an error occurred then the mtu used remains the default value. + * + * The server will reply to this request with an AttExchangeMTUResponse in + * case of success or AttErrorResponse in case of failure. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.3.1 + * + * @param connection The handle of the connection to send this request to. + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t exchange_mtu(connection_handle_t connection) = 0; + + /** + * Acquire the size of the mtu for a given connection. + * + * @param connection The handle of the connection for which the the MTU size + * should be acquired. + * + * @param mtu_size Output parameter which will contain the MTU size. + * + * @return BLE_ERROR_NONE if the MTU size has been acquired or the + * appropriate error otherwise. + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) = 0; + + /** + * Discover primary services in the range [begin - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * ReadByGoupType response where for each attribute_data exposed: + * - attribute_handle is the service attribute handle + * - end_group_handle is the last handle of the service + * - attribute_value is the UUID of the service. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover All + * Primary Services procedure. The complete implementation of the procedure + * is realized at an higher level. + * @note This function issue a Read By Group Type ATT request where the + * type parameter is equal to Primary Service and the Ending Handle parameter + * is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.1 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service( + connection_handle_t connection, + attribute_handle_t discovery_range_begining + ) = 0; + + /** + * Discover primary services by UUID in the range [discovery_range_begining - 0xFFFF]. + * + * If services exists in the range provided, the server will reply with a + * FindByTypeValueResponse containing the attribute range of each service + * discovered. + * + * If the end of the range is not reached, this procedure can be relaunched + * with the last handle of the last service discovered plus one as the + * beginning of the discovery range. + * + * If there is not services left to discover in the range, the server can + * either: + * * Reply with an ErrorResponse with the Error code set to ATTRIBUTE_NOT_FOUND + * * Set the end handle of the last service to 0xFFFF. + * + * @note This function realize a partial implementation of the Discover + * Primary Service by Service UUID procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find By Type Value ATT request where the + * type parameter is equal to Primary Service and the Ending Handle + * parameter is equal to 0xFFFF. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.2 + * + * @param connection The handle of the connection to send this request to. + * @param begin The beginning of the discovery range. + * @param uuid The UUID of the service to discover. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_primary_service_by_service_uuid( + connection_handle_t connection_handle, + attribute_handle_t discovery_range_beginning, + const UUID& uuid + ) = 0; + + /** + * Find included services within a service. + * + * If services are included in the service range then the server will reply + * with a ReadByTypeResponse where for each attribute record: + * - attribute_handle The handle where the service is included within the + * service definition. + * - attribute_data Contains two handles defining the range of the included. + * If the service found have a 16 bit uuid then its UUID is also included + * in the attribute data. + * + * If the end of the service range is not reached, this procedure can be + * relaunched with the handle of the last included service discovered plus + * one as the beginning of the new discovery range. + * + * The procedure is complete when either: + * - The server reply with an ErrorResponse with the Error code set to + * ATTRIBUTE_NOT_FOUND + * - An included service handle returned is equal to the end of the range. + * + * If the service UUID is a 128 bits one then it is necessary to issue a read + * attribute request on the first handle of the service discovered to get it. + * + * @note This function realize a partial implementation of the Find Included + * Services procedure. The complete implementation of the procedure is + * realized at an higher level. + * @note This function issue a Read By Type ATT request where the + * type parameter is equal to Include. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.5.1 + * + * @param connection The handle of the connection to send this request to. + * @param service_range The range of the service where service inclusion has + * to be discovered. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t find_included_service( + connection_handle_t connection_handle, + attribute_handle_range_t service_range + ) = 0; + + /** + * Find characteristic declarations within a service definition. + * + * If characteristic declarations are found within the range then the server + * should reply with a ReadByTypeResponse where for each attribute record: + * - attribute_handle is the handle of the characteristic definition + * - attribute_data contains the the following values attached to the + * characteristic : + * + properties: the properties of the characteristic. + * + value handle: the handle of the value of the characteristic. + * + uuid: the UUID of the characteristic. + * + * The procedure is considered complete when the server send an ErrorResponse + * with the ErrorCode set to ATTRIBUTE_NOT_FOUND or a ReadByType response + * has an attribute_handle set to the end of the discovery range. + * + * If the procedure is not complete after a server response, it should be + * relaunched with an updated range starting at the last attribute_handle + * discovered plus one. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics of a Service procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request where the type + * parameter is equal to Characteristic. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.6.1 + * + * @note The GATT procedure Discover Characteristics by UUID is implemented + * at a higher level using this function as a base. + * + * @param connection The handle of the connection to send this request to. + * @param discovery_range The range of attributes where the characteristics + * are discovered. It should be contained within a service. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_of_a_service( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) = 0; + + /** + * Discover characteristic descriptors of a characteristic. + * + * If descriptors are found within the range provided then the server should + * reply with a FindInformationResponse containing a list of + * attribute_handle_t, UUID pairs where the attribute handle is the + * descriptor handle and UUID is the UUID of the descriptor. + * + * The procedure is complete when the server send an ErrorResponse with the + * error code ATTRIBUTE_NOT_FOUND or the FindInformationResponse has an + * attribute handle that is equal to the end handle of the discovery range. + * + * @note This function realize a partial implementation of the Discover All + * Characteristics Descriptors procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Find Information ATT request.. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.7.1 + * + * @note It should be possible to use this function to issue a regular + * ATT Find Information Request. + * + * @param connection The handle of the connection to send this request to. + * @param descriptors_discovery_range The range of attributes where the + * descriptors are discovered. The first handle shall be no less than the + * characteristic value handle plus one and the last handle shall be no more + * than the last handle of the characteristic. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t discover_characteristics_descriptors( + connection_handle_t connection_handle, + attribute_handle_range_t descriptors_discovery_range + ) = 0; + + /** + * Read the value of an attribute. + * + * The server will reply with an AttReadResponse. In case of error, the + * server will reply with an AttErrorResponse. + * + * @note This function issue an ATT Read Request. + * + * @note: This function is the base function for the read Characteristic + * Value and Read Characteristic Descriptor GATT procedures. It can also + * be used to read the 128 bit UUID of a service discovered with + * find_included_service. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.1 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.1 + * + * @param connection The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_value( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) = 0; + + /** + * Read a characteristic value using its UUID (type). + * + * The server will respond a ReadByTypeResponse containing a sequence of + * attribute handle and attribute value pairs. + * To read remaining attributes, the client should launch a new request + * with an updated range. + * + * The procedure is considered complete when the server respond with an + * ErrorResponse containing the ErrorCode ATTRIBUTE_NOT_FOUND or when an + * handle in the ReadByTypeResponse is equal to the end of the discovered + * range. + * + * @note This function realize a partial implementation of the Read Using + * Characteristics Characteristic procedure. The complete implementation of + * the procedure is realized at an higher level. + * @note This function issue a Read By Type ATT request. + * @note BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.2 + * + * @note It should be possible to use this function to issue a regular + * ATT Read By Type Request. + * + * @param connection The handle of the connection to send this request to. + * @param attribute_range Range of the handle where an attribute with + * uuid as type is present. + * @param uuid UUID of the characteristic(s) to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_using_characteristic_uuid( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& uuid + ) = 0; + + /** + * Read a partial value of an attribute. + * + * The server will respond with a ReadBlobResponse containing the data read + * or an ErrorResponse in case of error. + * + * The procedure is not complete as long as the value in response have the + * same size as the mtu minus one. If the procedure is not complete, it can + * be launch again with an updated offset to read the remaining part of the + * attribute value. + * + * @note This function issue an ATT Read Blob Request. + * + * @note: This function is the base function for the Read Long + * Characteristic Value and Read Long Characteristic Descriptor GATT + * procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to read. + * @param offset Beginning offset for the read operation. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_attribute_blob( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) = 0; + + /** + * Read atomically multiple characteristics values. + * + * The server will respond with a ReadMultiple response containing the + * concatenation of the values of the characteristics. + * + * @note values might be truncated + * + * In case of error, the server should respond a with an ErrorResponse. + * + * @note This function issue an ATT Read Multiple Request. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.8.4 + * + * @param connection_handle The handle of the connection to send this request to. + * @param characteristic_value_handles Handle of the characteristic values + * to read. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t read_multiple_characteristic_values( + connection_handle_t connection_handle, + const ArrayView& characteristic_value_handles + ) = 0; + + /** + * Send a write command to the server. + * + * @note This function issue an ATT Write Command. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.1 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a Signed Write without Response command to the server. + * + * @note This function issue an ATT Write Command with the signed flag and + * the signature. + * + * @note signature is calculated by the stack. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.2 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t signed_write_without_response( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value + ) = 0; + + /** + * Send a write request to the server. + * + * The server should respond with a WriteResponse in case of success or an + * ErrorResponse in case of error. + * + * @note This function issue an ATT Write Request. + * + * @note: This function is the base function for the Write Characteristic + * Value and Write Characteristic Descriptors GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.12.3 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t write_attribute( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) = 0; + + /** + * Send a prepare write request to the server. + * + * The write request will go into a queue until the client execute or cancel + * the request with an execute write request which will write all the values + * in the queue atomically. + * + * The server should respond with a PrepareWriteResponse containing the + * content of the request in case of success and an ErrorResponse in case of + * error. + * + * If an ErrorResponse is received it doesn't invalidate what is already in + * the queue. + * + * @note This function issue an ATT Prepare Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param attribute_handle Handle of the attribute to write. + * @param value The value to write. + * @param offset offset where the value should be written. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t queue_prepare_write( + connection_handle_t connection_handle, + attribute_handle_t characteristic_value_handle, + const ArrayView& value, + uint16_t offset + ) = 0; + + /** + * Send a request to the server to execute the queue of prepared write + * requests. + * + * The server should respond with an ExecuteWriteResponse in case of success + * and an Error response in case of failure. + * + * @note This function issue an ATT Execute Write Request. + * + * @note: This function is one of the base function for the Write Long + * Characteristic Value and Reliable Writes GATT procedures. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.4 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.9.5 + * + * @param connection_handle The handle of the connection to send this request to. + * @param execute If true, execute the write request queue otherwise cancel it. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t execute_write_queue( + connection_handle_t connection_handle, + bool execute + ) = 0; + + /** + * Register a callback which will handle messages from the server. + * + * @param cb The callback object which will handle messages from the server. + * It accept two parameters in input: The handle of the connection where the + * message was received and the message received. Real type of the message + * can be obtained from its opcode. + */ + void when_server_message_received( + mbed::Callback cb + ) { + _server_message_cb = cb; + } + + /** + * Register a callback handling transaction timeout. + * + * @param cb The callback handling timeout of a transaction. It accepts as + * a parameter the connection handle involved in the timeout. + * + * @note No more attribute protocol requests, commands, indication or + * notification shall be sent over a connection implied in a transaction + * timeout. To send a new ATT message, the conenction should be + * reestablished. + */ + void when_transaction_timeout( + mbed::Callback cb + ) { + _transaction_timeout_cb = cb; + } + +protected: + GattClient() { } + + virtual ~GattClient() { } + + /** + * Upon server message reception an implementation shall call this function. + * + * @param connection_handle The handle of the connection which has received + * the server message. + * @param server_message The message received from the server. + */ + void on_server_event( + connection_handle_t connection_handle, + const AttServerMessage& server_message + ) { + if (_server_message_cb) { + _server_message_cb(connection_handle, server_message); + } + } + + /** + * Upon transaction timeout an implementation shall call this function. + * + * @param connection_handle The handle of the connection of the transaction + * which has times out. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part F Section 3.3.3 + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part G Section 4.4.14 + */ + void on_transaction_timeout( + connection_handle_t connection_handle + ) { + if (_transaction_timeout_cb) { + _transaction_timeout_cb(connection_handle); + } + } + +private: + /** + * Callback called when the client receive a message from the server. + */ + mbed::Callback _server_message_cb; + + /** + * Callback called when a transaction times out. + */ + mbed::Callback _transaction_timeout_cb; + + // Disallow copy construction and copy assignment. + GattClient(const GattClient&); + GattClient& operator=(const GattClient&); +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GATT_CLIENT_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h new file mode 100644 index 00000000000..a0f3346dead --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SimpleAttServerMessage.h @@ -0,0 +1,232 @@ +/* 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 BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ +#define BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ + +#include "AttServerMessage.h" + +namespace ble { +namespace pal { + +/** + * Simple implementation of ble::pal::AttFindInformationResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindInformationResponse : public AttFindInformationResponse { + /** + * Format of the UUID in the response. + */ + enum Format { + FORMAT_16_BIT_UUID = 0x01,//!< FORMAT_16_BIT_UUID + FORMAT_128_BIT_UUID = 0x02//!< FORMAT_128_BIT_UUID + }; + + /** + * Construct an AttFindInformationResponse from format and an array of bytes + * containing the information data. + * @param format The format of the information data. + * @param information_data The information data whose format is determined + * by the Format field + */ + SimpleAttFindInformationResponse( + Format format, ArrayView information_data + ) : AttFindInformationResponse(), + _format(format), _information_data(information_data), + _item_size(information_data_item_size()) { + } + + /** + * @see ble::pal::AttFindInformationResponse::size + */ + virtual size_t size() const { + return _information_data.size() / _item_size; + } + + /** + * @see ble::pal::AttFindInformationResponse::operator[] + */ + virtual information_data_t operator[](size_t index) const { + const uint8_t* item = &_information_data[index * _item_size]; + + information_data_t result; + memcpy(&result.handle, item, sizeof(result.handle)); + + if (_format == FORMAT_16_BIT_UUID) { + uint16_t short_uuid = 0; + memcpy(&short_uuid, item + 2, sizeof(short_uuid)); + result.uuid = UUID(short_uuid); + } else { + result.uuid = UUID(item + 2, UUID::LSB); + } + + return result; + } + +private: + size_t information_data_item_size() const { + return sizeof(attribute_handle_t) + ((_format == FORMAT_16_BIT_UUID) ? 2 : 16); + } + + const Format _format; + const ArrayView _information_data; + const size_t _item_size; +}; + + +/** + * Simple implementation of ble::pal::AttFindByTypeValueResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttFindByTypeValueResponse : public AttFindByTypeValueResponse { + /** + * Construct a AttFindByTypeValueResponse from a raw array containing the + * Handle Informations. + * @param handles raw array containing one or more Handle Informations. + */ + SimpleAttFindByTypeValueResponse(ArrayView handles) : + AttFindByTypeValueResponse(), _handles(handles) { + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::size + */ + virtual std::size_t size() const { + return _handles.size() / item_size; + } + + /** + * @see ble::pal::AttFindByTypeValueResponse::operator[] + */ + virtual attribute_handle_range_t operator[](size_t index) const { + attribute_handle_range_t result; + const uint8_t* item = &_handles[index * item_size]; + memcpy(&result.begin, item, sizeof(result.begin)); + memcpy(&result.end, item + sizeof(result.begin), sizeof(result.end)); + return result; + } + +private: + static const size_t item_size = 4; + const ArrayView _handles; +}; + + +/** + * Simple implementation of ble::pal::AttReadByTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByTypeResponse : public AttReadByTypeResponse { + /** + * Construct an AttReadByTypeResponse from the size of each attribute + * handle-value pair and a list of attribute data. + * @param element_size The size of each attribute-handle pair. + * @param attribute_data Raw bytes array containing the list of attribute + * data. + */ + SimpleAttReadByTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t handle; + memcpy(&handle, item, sizeof(handle)); + + attribute_data_t result = { + handle, + ArrayView( + item + sizeof(handle), + _element_size - sizeof(handle) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + + +/** + * Simple implementation of ble::pal::AttReadByGroupTypeResponse. + * It should fit for any vendor stack exposing a proper ATT interface. + */ +struct SimpleAttReadByGroupTypeResponse : public AttReadByGroupTypeResponse { + /** + * Construct an instance of AttReadByGroupTypeResponse from the size of each + * attribute data and a byte array containing the list of attribute data. + * @param element_size The size of each Attribute Data + * @param attribute_data Byte array containing the list of Attribute Data. + */ + SimpleAttReadByGroupTypeResponse( + uint8_t element_size, ArrayView attribute_data + ) : AttReadByGroupTypeResponse(), + _attribute_data(attribute_data), _element_size(element_size) { + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::size + */ + virtual size_t size() const { + return _attribute_data.size() / _element_size; + } + + /** + * @see ble::pal::AttReadByGroupTypeResponse::operator[] + */ + virtual attribute_data_t operator[](size_t index) const { + const uint8_t* item = &_attribute_data[index * _element_size]; + uint16_t begin; + uint16_t end; + + memcpy(&begin, item, sizeof(begin)); + memcpy(&end, item + sizeof(begin), sizeof(end)); + + attribute_data_t result = { + { begin, end }, + ArrayView( + item + sizeof(begin) + sizeof(end), + _element_size - (sizeof(begin) + sizeof(end)) + ) + }; + + return result; + } + +private: + ArrayView _attribute_data; + uint8_t _element_size; +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_SIMPLEATTSERVERMESSAGE_H_ */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp new file mode 100644 index 00000000000..595babcccc0 --- /dev/null +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -0,0 +1,1342 @@ +/* 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. + */ + +#include +#include + +#include +#include +#include "ble/generic/GenericGattClient.h" +#include "ble/blecommon.h" +#include + +using ble::pal::AttServerMessage; +using ble::pal::AttReadResponse; +using ble::pal::AttReadBlobResponse; +using ble::pal::AttReadByTypeResponse; +using ble::pal::AttReadByGroupTypeResponse; +using ble::pal::AttFindByTypeValueResponse; +using ble::pal::AttErrorResponse; +using ble::pal::AttributeOpcode; +using ble::pal::AttWriteResponse; +using ble::pal::AttPrepareWriteResponse; +using ble::pal::AttExecuteWriteResponse; +using ble::pal::AttHandleValueIndication; +using ble::pal::AttHandleValueNotification; +using ble::pal::AttFindInformationResponse; + +namespace ble { +namespace generic { + +/* + * Type of procedures which can be launched by the client. + */ +enum procedure_type_t { + COMPLETE_DISCOVERY_PROCEDURE, + READ_PROCEDURE, + WRITE_PROCEDURE, + DESCRIPTOR_DISCOVERY_PROCEDURE +}; + + +/* + * Base class for a procedure control block + */ +struct procedure_control_block_t { + /* + * Base constructor for procedure control block. + */ + procedure_control_block_t(procedure_type_t type, Gap::Handle_t handle) : + type(type), connection_handle(handle), next(NULL) { } + + virtual ~procedure_control_block_t() { } + + /* + * Entry point of the control block stack machine. + */ + virtual void handle(GenericGattClient* client, const AttServerMessage& message) = 0; + + /* + * Function call in case of timeout + */ + virtual void handle_timeout_error(GenericGattClient* client) = 0; + + procedure_type_t type; + Gap::Handle_t connection_handle; + procedure_control_block_t* next; +}; + + +/* + * Procedure control block for the discovery process. + */ +struct discovery_control_block_t : public procedure_control_block_t { + discovery_control_block_t( + Gap::Handle_t handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + UUID matching_service_uuid, + UUID matching_characteristic_uuid + ) : procedure_control_block_t(COMPLETE_DISCOVERY_PROCEDURE, handle), + service_callback(service_callback), + characteristic_callback(characteristic_callback), + matching_service_uuid(matching_service_uuid), + matching_characteristic_uuid(matching_characteristic_uuid), + services_discovered(NULL), + done(false) { + } + + virtual ~discovery_control_block_t() { + while(services_discovered) { + service_t* tmp = services_discovered->next; + delete services_discovered; + services_discovered = tmp; + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + // if end of discovery has been requested, ends it immediately + if (done) { + terminate(client); + return; + } + + switch(message.opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + handle_service_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + handle_characteristic_discovered( + client, static_cast(message) + ); + break; + case AttributeOpcode::ERROR_RESPONSE: { + const AttErrorResponse& error = static_cast(message); + if (error.error_code != AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client); + } + + switch (error.request_opcode) { + case AttributeOpcode::READ_BY_GROUP_TYPE_REQUEST: + case AttributeOpcode::FIND_BY_TYPE_VALUE_REQUEST: + start_characteristic_discovery(client); + break; + case AttributeOpcode::READ_BY_TYPE_REQUEST: + handle_all_characteristics_discovered(client); + break; + default: + // error + break; + } + } break; + default: + // error + break; + } + } + + template + void handle_service_discovered(GenericGattClient* client, const Response& response) { + if (!response.size()) { + terminate(client); + return; + } + + uint16_t end_handle = 0x0000; + for (size_t i = 0; i < response.size(); ++i) { + uint16_t start_handle = get_start_handle(response[i]); + end_handle = get_end_handle(response[i]); + UUID uuid = get_uuid(response[i]); + + if (!characteristic_callback) { + DiscoveredService discovered_service; + discovered_service.setup(uuid, start_handle, end_handle); + service_callback(&discovered_service); + } else { + service_t* discovered_service = new (std::nothrow) service_t( + start_handle, end_handle, uuid + ); + + if (discovered_service == NULL) { + terminate(client); + return; + } + + insert_service(discovered_service); + } + } + + if (end_handle == 0xFFFF) { + start_characteristic_discovery(client); + } else { + ble_error_t err = client->_pal_client->discover_primary_service( + connection_handle, end_handle + 1 + ); + + if (err) { + terminate(client); + } + } + } + + void start_characteristic_discovery(GenericGattClient* client) { + if (!services_discovered) { + terminate(client); + return; + } + + if (!characteristic_callback) { + terminate(client); + return; + } + + if (service_callback) { + DiscoveredService discovered_service; + discovered_service.setup( + services_discovered->uuid, + services_discovered->begin, + services_discovered->end + ); + service_callback(&discovered_service); + } + + last_characteristic = characteristic_t(); + client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + services_discovered->begin, + services_discovered->end + ) + ); + } + + void handle_characteristic_discovered(GenericGattClient* client, const AttReadByTypeResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + if (last_characteristic.is_valid() == false) { + last_characteristic.set_last_handle(response[i].handle - 1); + if (matching_characteristic_uuid == UUID() + || last_characteristic.getUUID() == matching_characteristic_uuid) { + characteristic_callback(&last_characteristic); + } + } + + last_characteristic = characteristic_t( + client, connection_handle, response[i].handle, response[i].value + ); + } + + // check if all the characteristics of the service has been discovered + if (last_characteristic.getValueHandle() == services_discovered->end) { + handle_all_characteristics_discovered(client); + } else { + ble_error_t err = client->_pal_client->discover_characteristics_of_a_service( + connection_handle, + attribute_handle_range( + last_characteristic.getValueHandle() + 1, + services_discovered->end + ) + ); + + if (err) { + terminate(client); + } + } + } + + void handle_all_characteristics_discovered(GenericGattClient* client) { + if (last_characteristic.is_valid() == false) { + if (matching_characteristic_uuid == UUID() + || matching_characteristic_uuid == last_characteristic.getUUID()) { + last_characteristic.set_last_handle(services_discovered->end); + characteristic_callback(&last_characteristic); + } + } + + service_t* old = services_discovered; + services_discovered = services_discovered->next; + delete old; + + if (!services_discovered) { + terminate(client); + } else { + start_characteristic_discovery(client); + } + } + + void terminate(GenericGattClient* client) { + // unknown error, terminate the procedure immediately + client->remove_control_block(this); + Gap::Handle_t handle = connection_handle; + delete this; + client->on_termination(handle); + } + + uint16_t get_start_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.begin; + } + + uint16_t get_start_handle(const attribute_handle_range_t& range) { + return range.begin; + } + + uint16_t get_end_handle(const AttReadByGroupTypeResponse::attribute_data_t& data) { + return data.group_range.end; + } + + uint16_t get_end_handle(const attribute_handle_range_t& range) { + return range.end; + } + + UUID get_uuid(const AttReadByGroupTypeResponse::attribute_data_t& data) { + if (data.value.size() == 2) { + return UUID(data.value[0] | data.value[1] << 8); + } else { + return UUID(data.value.data(), UUID::LSB); + } + } + + UUID get_uuid(const attribute_handle_range_t& range) { + return matching_service_uuid; + } + + struct service_t { + service_t(uint16_t begin, uint16_t end, const UUID& uuid) : + begin(begin), end(end), uuid(uuid), next(NULL) { } + uint16_t begin; + uint16_t end; + UUID uuid; + service_t* next; + }; + + struct characteristic_t : DiscoveredCharacteristic { + characteristic_t() : DiscoveredCharacteristic() { + lastHandle = 0x0001; + } + + characteristic_t( + GattClient* client, + Gap::Handle_t connection_handle, + uint16_t decl_handle, + const ArrayView value + ) : DiscoveredCharacteristic() { + gattc = client; + uuid = get_uuid(value); + props = get_properties(value); + declHandle = decl_handle; + valueHandle = get_value_handle(value); + lastHandle = 0x0000; + connHandle = connection_handle; + } + + static UUID get_uuid(const ArrayView& value) { + if (value.size() == 5) { + return UUID(value[3] | (value[4] << 8)); + } else { + return UUID(value.data() + 3, UUID::LSB); + } + } + + static DiscoveredCharacteristic::Properties_t get_properties(const ArrayView& value) { + uint8_t raw_properties = value[0]; + DiscoveredCharacteristic::Properties_t result; + result._broadcast = (raw_properties & (1 << 0)) ? true : false; + result._read = (raw_properties & (1 << 1)) ? true : false; + result._writeWoResp = (raw_properties & (1 << 2)) ? true : false; + result._write = (raw_properties & (1 << 3)) ? true : false; + result._notify = (raw_properties & (1 << 4)) ? true : false; + result._indicate = (raw_properties & (1 << 5)) ? true : false; + result._authSignedWrite = (raw_properties & (1 << 6)) ? true : false; + return result; + } + + static uint16_t get_value_handle(const ArrayView& value) { + return value[1] | (value[2] << 8); + } + + void set_last_handle(uint16_t last_handle) { + lastHandle = last_handle; + } + + bool is_valid() const { + return lastHandle != 0x0000; + } + }; + + void insert_service(service_t* service) { + if (services_discovered == NULL) { + services_discovered = service; + return; + } + + service_t* current = services_discovered; + while (current->next) { + current = current->next; + } + current->next = service; + } + + ServiceDiscovery::ServiceCallback_t service_callback; + ServiceDiscovery::CharacteristicCallback_t characteristic_callback; + UUID matching_service_uuid; + UUID matching_characteristic_uuid; + service_t* services_discovered; + characteristic_t last_characteristic; + bool done; +}; + + +struct read_control_block_t : public procedure_control_block_t { + read_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, uint16_t offset + ) : procedure_control_block_t(READ_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), + offset(offset), current_offset(offset), data(NULL) { + } + + virtual ~read_control_block_t() { + if (data != NULL) { + free(data); + } + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattReadCallbackParams& response) { + client->remove_control_block(this); + client->processReadResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::READ_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + case AttributeOpcode::READ_BLOB_RESPONSE: + handle_read_response(client, static_cast(message)); + break; + + default: { + // should not happen, terminate the procedure and notify client with an error + // in such case + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } break; + } + } + + template + void handle_read_response(GenericGattClient* client, const ResponseType& read_response) { + uint16_t mtu_size = client->get_mtu(connection_handle); + + // end of responses ? + if ((uint16_t) read_response.size() < (mtu_size - 1)) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + 0, // size of 0 + NULL, // no data + BLE_ERROR_NONE, + }; + + // is it the first response, or is there any other response already + // in the object ? + if (data == NULL) { + response.len = (uint16_t) read_response.size(); + response.data = read_response.data(); + } else { + // copy the data in the existing buffer + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + response.len = (current_offset + read_response.size()) - offset; + response.data = data; + } + terminate(client, response); + } else { + // allocation which will contain the response data plus the next one. + data = (uint8_t*) realloc(data, (current_offset - offset) + ((mtu_size - 1) * 2)); + if (data == NULL) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + AttErrorResponse::INSUFFICIENT_RESOURCES, + NULL, + BLE_ERROR_NO_MEM, + }; + terminate(client, response); + return; + } + + memcpy(data + (current_offset - offset), read_response.data(), read_response.size()); + current_offset = current_offset + read_response.size(); + ble_error_t err = client->_pal_client->read_attribute_blob( + connection_handle, + attribute_handle, + current_offset + ); + + if (err) { + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + AttErrorResponse::UNLIKELY_ERROR, + 0, // size of 0 + NULL, // no data + BLE_ERROR_UNSPECIFIED, + + }; + terminate(client, response); + } + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::READ_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + case AttErrorResponse::INVALID_OFFSET: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + case AttErrorResponse::ATTRIBUTE_NOT_LONG: + status = BLE_ERROR_PARAM_OUT_OF_RANGE; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + GattReadCallbackParams response = { + connection_handle, + attribute_handle, + offset, + error.error_code, + /* data */ NULL, + status + }; + + terminate(client, response); + } + + uint16_t attribute_handle; + uint16_t offset; + uint16_t current_offset; + uint8_t* data; +}; + +/* + * Control block for the write process + */ +struct write_control_block_t : public procedure_control_block_t { + write_control_block_t( + Gap::Handle_t connection_handle, uint16_t attribute_handle, + uint8_t* data, uint16_t len + ) : procedure_control_block_t(WRITE_PROCEDURE, connection_handle), + attribute_handle(attribute_handle), len(len), offset(0), data(data), + prepare_success(false), status(BLE_ERROR_UNSPECIFIED), error_code(0xFF) { + } + + virtual ~write_control_block_t() { + free(data); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + 0x00 + }; + terminate(client, response); + } + + void terminate(GenericGattClient* client, const GattWriteCallbackParams& response) { + client->remove_control_block(this); + client->processWriteResponse(&response); + delete this; + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + break; + + case AttributeOpcode::WRITE_RESPONSE: + handle_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + handle_prepare_write_response(client, static_cast(message)); + break; + + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: + handle_execute_write_response(client, static_cast(message)); + break; + + default: { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_UNSPECIFIED, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } break; + } + } + + void handle_write_response(GenericGattClient* client, const AttWriteResponse& write_response) { + GattWriteCallbackParams response = { + connection_handle, attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + BLE_ERROR_NONE, 0x00 + }; + + terminate(client, response); + } + + void handle_prepare_write_response(GenericGattClient* client, const AttPrepareWriteResponse& write_response) { + ble_error_t err = BLE_ERROR_UNSPECIFIED; + + uint16_t mtu_size = client->get_mtu(connection_handle); + offset = write_response.offset + write_response.partial_value.size(); + if (offset < len) { + err = client->_pal_client->queue_prepare_write( + connection_handle, attribute_handle, + make_const_ArrayView( + data + offset, + std::min((len - offset), (mtu_size - 5)) + ), + offset + ); + } else { + err = client->_pal_client->execute_write_queue( + connection_handle, true + ); + } + + if (err) { + clear_prepare_queue(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void handle_execute_write_response(GenericGattClient* client, const AttExecuteWriteResponse& execute_response) { + if (prepare_success) { + status = BLE_ERROR_NONE; + error_code = 0x00; + } + + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error_code + }; + + terminate(client, response); + } + + void clear_prepare_queue(GenericGattClient* client, ble_error_t s, uint8_t e) { + prepare_success = false; + status = s; + error_code = e; + ble_error_t err = client->_pal_client->execute_write_queue( + connection_handle, false + ); + + if (err) { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + err, + AttErrorResponse::UNLIKELY_ERROR + }; + + terminate(client, response); + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + ble_error_t status = BLE_ERROR_UNSPECIFIED; + + switch (error.error_code) { + case AttErrorResponse::INVALID_HANDLE: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INVALID_ATTRIBUTE_VALUE_LENGTH: + status = BLE_ERROR_INVALID_PARAM; + break; + case AttErrorResponse::INSUFFICIENT_AUTHORIZATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_AUTHENTICATION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION_KEY_SIZE: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::INSUFFICIENT_ENCRYPTION: + status = BLE_ERROR_INVALID_STATE; + break; + case AttErrorResponse::WRITE_NOT_PERMITTED: + status = BLE_ERROR_OPERATION_NOT_PERMITTED; + break; + default: + status = BLE_ERROR_UNSPECIFIED; + break; + } + + if (error.request_opcode == AttributeOpcode(AttributeOpcode::PREPARE_WRITE_REQUEST)) { + clear_prepare_queue(client, status, error.error_code); + } else { + GattWriteCallbackParams response = { + connection_handle, + attribute_handle, + GattWriteCallbackParams::OP_WRITE_REQ, + status, + error.error_code + }; + + terminate(client, response); + } + } + + uint16_t attribute_handle; + uint16_t len; + uint16_t offset; + uint8_t* data; + bool prepare_success; + ble_error_t status; + uint8_t error_code; +}; + +/* + * Control block for the descriptor discovery process + */ +struct descriptor_discovery_control_block_t : public procedure_control_block_t { + descriptor_discovery_control_block_t( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback + ) : procedure_control_block_t(DESCRIPTOR_DISCOVERY_PROCEDURE, characteristic.getConnectionHandle()), + characteristic(characteristic), + discovery_cb(discoveryCallback), + termination_cb(terminationCallback), + next_handle(characteristic.getValueHandle() + 1), + done(false) { + } + + virtual ~descriptor_discovery_control_block_t() { } + + ble_error_t start(GenericGattClient* client) { + return client->_pal_client->discover_characteristics_descriptors( + connection_handle, + attribute_handle_range( + next_handle, + characteristic.getLastHandle() + ) + ); + } + + virtual void handle_timeout_error(GenericGattClient* client) { + terminate(client, BLE_ERROR_UNSPECIFIED); + } + + virtual void handle(GenericGattClient* client, const AttServerMessage& message) { + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + handle_error(client, static_cast(message)); + return; + + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + handle_response(client, static_cast(message)); + return; + + default: + break; + } + } + + void handle_error(GenericGattClient* client, const AttErrorResponse& error) { + if (error.error_code == AttErrorResponse::ATTRIBUTE_NOT_FOUND) { + terminate(client, BLE_ERROR_NONE); + } else { + terminate(client, BLE_ERROR_UNSPECIFIED, error.error_code); + } + } + + void handle_response(GenericGattClient* client, const AttFindInformationResponse& response) { + for (size_t i = 0; i < response.size(); ++i) { + DiscoveredCharacteristicDescriptor descriptor( + client, connection_handle, response[i].handle, response[i].uuid + ); + CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = { + characteristic, + descriptor + }; + discovery_cb(¶ms); + if (done) { + terminate(client, BLE_ERROR_NONE); + return; + } + + if (response[i].handle == characteristic.getLastHandle()) { + terminate(client, BLE_ERROR_NONE); + return; + } + next_handle = response[i].handle + 1; + } + + ble_error_t err = start(client); + if (err) { + terminate(client, err, AttErrorResponse::UNLIKELY_ERROR); + } + } + + void terminate(GenericGattClient* client, ble_error_t status, uint8_t error_code = 0x00) { + client->remove_control_block(this); + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + status, + error_code + }; + termination_cb(¶ms); + delete this; + } + + DiscoveredCharacteristic characteristic; + CharacteristicDescriptorDiscovery::DiscoveryCallback_t discovery_cb; + CharacteristicDescriptorDiscovery::TerminationCallback_t termination_cb; + uint16_t next_handle; + bool done; +}; + + +GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : + _pal_client(pal_client), + _termination_callback(), + control_blocks(NULL) { + _pal_client->when_server_message_received( + mbed::callback(this, &GenericGattClient::on_server_message_received) + ); + _pal_client->when_transaction_timeout( + mbed::callback(this, &GenericGattClient::on_transaction_timeout) + ); +} + +ble_error_t GenericGattClient::launchServiceDiscovery( + Gap::Handle_t connection_handle, + ServiceDiscovery::ServiceCallback_t service_callback, + ServiceDiscovery::CharacteristicCallback_t characteristic_callback, + const UUID& matching_service_uuid, + const UUID& matching_characteristic_uuid +) { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + // terminate and return if there is no callback to call + if (!service_callback && !characteristic_callback) { + on_termination(connection_handle); + return BLE_ERROR_NONE; + } + + discovery_control_block_t* discovery_pcb = new(std::nothrow) discovery_control_block_t( + connection_handle, + service_callback, + characteristic_callback, + matching_service_uuid, + matching_characteristic_uuid + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + // note: control block inserted prior the request because they are part of + // of the transaction and the callback can be call synchronously + insert_control_block(discovery_pcb); + + // launch the request + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (matching_service_uuid == UUID()) { + err = _pal_client->discover_primary_service( + connection_handle, + 0x0001 + ); + } else { + err = _pal_client->discover_primary_service_by_service_uuid( + connection_handle, + 0x0001, + matching_service_uuid + ); + } + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isServiceDiscoveryActive() const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateServiceDiscovery() +{ + procedure_control_block_t* pcb = control_blocks; + while (pcb) { + if (pcb->type == COMPLETE_DISCOVERY_PROCEDURE) { + static_cast(pcb)->done = true; + } + pcb = pcb->next; + } +} + +ble_error_t GenericGattClient::read( + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + uint16_t offset) const +{ + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + read_control_block_t* read_pcb = new(std::nothrow) read_control_block_t( + connection_handle, + attribute_handle, + offset + ); + + if (read_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(read_pcb); + + ble_error_t err = BLE_ERROR_NONE; + + if (offset == 0) { + err = _pal_client->read_attribute_value( + connection_handle, attribute_handle + ); + } else { + err = _pal_client->read_attribute_blob( + connection_handle, attribute_handle, offset + ); + } + + if (err) { + remove_control_block(read_pcb); + delete read_pcb; + } + + return err; +} + +ble_error_t GenericGattClient::write( + GattClient::WriteOp_t cmd, + Gap::Handle_t connection_handle, + GattAttribute::Handle_t attribute_handle, + size_t length, + const uint8_t* value +) const { + // verify that there is no other procedures going on this connection + if (get_control_block(connection_handle)) { + return BLE_ERROR_INVALID_STATE; + } + + 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 (length > (uint16_t)(mtu - 3)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } + + write_control_block_t* write_pcb = new(std::nothrow) write_control_block_t( + connection_handle, + attribute_handle, + data, + length + ); + + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } + + insert_control_block(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 - 5), + /* offset */ 0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } + + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } + + return err; + } + + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::onServiceDiscoveryTermination( + ServiceDiscovery::TerminationCallback_t callback +) { + _termination_callback = callback; +} + +ble_error_t GenericGattClient::discoverCharacteristicDescriptors( + const DiscoveredCharacteristic& characteristic, + const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback, + const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback +) { + // verify that there is no other procedures going on this connection + if (get_control_block(characteristic.getConnectionHandle())) { + return BLE_ERROR_INVALID_STATE; + } + + if (characteristic.getValueHandle() == characteristic.getLastHandle()) { + CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = { + characteristic, + BLE_ERROR_NONE, + /* error code */ 0x00 + }; + + terminationCallback(¶ms); + return BLE_ERROR_NONE; + } + + descriptor_discovery_control_block_t* discovery_pcb = + new(std::nothrow) descriptor_discovery_control_block_t( + characteristic, + discoveryCallback, + terminationCallback + ); + + if (discovery_pcb == NULL) { + return BLE_ERROR_NO_MEM; + } + + insert_control_block(discovery_pcb); + + ble_error_t err = discovery_pcb->start(this); + + if (err) { + remove_control_block(discovery_pcb); + delete discovery_pcb; + } + + return err; +} + +bool GenericGattClient::isCharacteristicDescriptorDiscoveryActive( + const DiscoveredCharacteristic& characteristic +) const { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE && + static_cast(pcb)->characteristic == characteristic) { + return true; + } + pcb = pcb->next; + } + + return false; +} + +void GenericGattClient::terminateCharacteristicDescriptorDiscovery( + const DiscoveredCharacteristic& characteristic +) { + procedure_control_block_t* pcb = control_blocks; + + while (pcb) { + if (pcb->type == DESCRIPTOR_DISCOVERY_PROCEDURE) { + descriptor_discovery_control_block_t* dpcb = + static_cast(pcb); + if (dpcb->characteristic == characteristic) { + dpcb->done = true; + return; + } + } + + pcb = pcb->next; + } + +} + +ble_error_t GenericGattClient::reset(void) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { + if (_termination_callback) { + _termination_callback(connection_handle); + } +} + +void GenericGattClient::on_server_message_received( + connection_handle_t connection_handle, + const AttServerMessage& message +) { + switch(message.opcode) { + case AttributeOpcode::ERROR_RESPONSE: + case AttributeOpcode::EXCHANGE_MTU_RESPONSE: + case AttributeOpcode::FIND_INFORMATION_RESPONSE: + case AttributeOpcode::FIND_BY_VALUE_TYPE_RESPONSE: + case AttributeOpcode::READ_BY_TYPE_RESPONSE: + case AttributeOpcode::READ_RESPONSE: + case AttributeOpcode::READ_BLOB_RESPONSE: + case AttributeOpcode::READ_MULTIPLE_RESPONSE: + case AttributeOpcode::READ_BY_GROUP_TYPE_RESPONSE: + case AttributeOpcode::WRITE_RESPONSE: + case AttributeOpcode::PREPARE_WRITE_RESPONSE: + case AttributeOpcode::EXECUTE_WRITE_RESPONSE: { + on_server_response(connection_handle, message); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + on_server_event(connection_handle, message); + } break; + + default: + // invalid message receive + return; + } +} + +void GenericGattClient::on_server_response( + connection_handle_t connection, + const AttServerMessage& message +) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle(this, message); +} + +void GenericGattClient::on_server_event(connection_handle_t connection, const AttServerMessage& message) { + GattHVXCallbackParams callbacks_params = { + (Gap::Handle_t) connection, 0 + }; + + switch (message.opcode) { + case AttributeOpcode::HANDLE_VALUE_NOTIFICATION: { + const AttHandleValueNotification& notification = + static_cast(message); + callbacks_params.handle = notification.attribute_handle; + callbacks_params.type = BLE_HVX_NOTIFICATION; + callbacks_params.len = notification.attribute_value.size(); + callbacks_params.data = notification.attribute_value.data(); + } break; + + case AttributeOpcode::HANDLE_VALUE_INDICATION: { + const AttHandleValueIndication& indication = + static_cast(message); + callbacks_params.handle = indication.attribute_handle; + callbacks_params.type = BLE_HVX_INDICATION; + callbacks_params.len = indication.attribute_value.size(); + callbacks_params.data = indication.attribute_value.data(); + } break; + + default: + return; + } + + processHVXEvent(&callbacks_params); +} + +void GenericGattClient::on_transaction_timeout(connection_handle_t connection) { + procedure_control_block_t* pcb = get_control_block(connection); + if (pcb == NULL) { + return; + } + + pcb->handle_timeout_error(this); +} + +procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +const procedure_control_block_t* GenericGattClient::get_control_block(Gap::Handle_t connection) const { + procedure_control_block_t* it = control_blocks; + while (it && it->connection_handle != connection) { + it = it->next; + } + return it; +} + +void GenericGattClient::insert_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + control_blocks = cb; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next) { + current = current->next; + } + current->next = cb; +} + +void GenericGattClient::remove_control_block(procedure_control_block_t* cb) const { + if (control_blocks == NULL) { + return; + } + + if (cb == control_blocks) { + control_blocks = control_blocks->next; + return; + } + + procedure_control_block_t* current = control_blocks; + while (current->next && current->next != cb) { + current = current->next; + } + + if (current->next == NULL) { + return; + } + + current->next = cb->next; + cb->next = NULL; +} + +uint16_t GenericGattClient::get_mtu(Gap::Handle_t connection) const { + uint16_t result = 23; + if(_pal_client->get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) { + result = 23; + } + return result; +} + +} // namespace pal +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp index 299b029f4ec..057b151edac 100644 --- a/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_ARM_SSG/TARGET_BEETLE/source/ArmGattServer.cpp @@ -367,11 +367,11 @@ void ArmGattServer::attCback(attEvt_t *pEvt) uint8_t ArmGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -410,12 +410,12 @@ uint8_t ArmGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_ } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h new file mode 100644 index 00000000000..da4b345a628 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -0,0 +1,153 @@ +/* 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 CORDIO_BLE_H_ +#define CORDIO_BLE_H_ + +#include "ble/BLE.h" +#include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" + +#include "CordioHCIDriver.h" +#include "CordioGap.h" +#include "CordioGattServer.h" +#include "CordioSecurityManager.h" +#include "CordioPalAttClient.h" +#include "ble/pal/AttClientToGattClientAdapter.h" +#include "ble/generic/GenericGattClient.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see BLEInstanceBase + */ +class BLE : public ::BLEInstanceBase { + /** + * Construction with an HCI driver. + */ + BLE(CordioHCIDriver& hci_driver); + + /** + * Destructor + */ + virtual ~BLE(); + +public: + + /** + * Access to the singleton containing the implementation of BLEInstanceBase + * for the Cordio stack. + */ + static BLE& deviceInstance(); + + /** + * @see BLEInstanceBase::init + */ + virtual ble_error_t init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> initCallback + ); + + /** + * @see BLEInstanceBase::hasInitialized + */ + virtual bool hasInitialized() const; + + /** + * @see BLEInstanceBase::shutdown + */ + virtual ble_error_t shutdown(); + + /** + * @see BLEInstanceBase::getVersion + */ + virtual const char *getVersion(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual Gap& getGap(); + + /** + * @see BLEInstanceBase::getGap + */ + virtual const Gap& getGap() const; + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual GattServer &getGattServer(); + + /** + * @see BLEInstanceBase::getGattServer + */ + virtual const GattServer &getGattServer() const; + + /** + * @see BLEInstanceBase::getGattClient + */ + virtual ::GattClient &getGattClient(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; + + /** + * @see BLEInstanceBase::waitForEvent + */ + virtual void waitForEvent(); + + /** + * @see BLEInstanceBase::processEvents + */ + virtual void processEvents(); + +private: + static void stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg); + static void device_manager_cb(dmEvt_t* dm_event); + static void connection_handler(dmEvt_t* dm_event); + static void timeoutCallback(); + + void stack_setup(); + void start_stack_reset(); + void callDispatcher(); + + static CordioHCIDriver* _hci_driver; + static FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> _init_callback; + + enum { + NOT_INITIALIZED, + INITIALIZING, + INITIALIZED + } initialization_status; + + ::BLE::InstanceID_t instanceID; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + + +#endif /* CORDIO_BLE_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h new file mode 100644 index 00000000000..ab139d5b908 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGap.h @@ -0,0 +1,262 @@ +/* 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 CORDIO_GAP_H_ +#define CORDIO_GAP_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GapAdvertisingParams.h" +#include "ble/GapAdvertisingData.h" +#include "ble/Gap.h" +#include "ble/GapScanningParams.h" +#include "dm_api.h" +#include "att_api.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * @see ::Gap + */ +class Gap : public ::Gap +{ +public: + /** + * Return the Gap singleton implementing ::Gap for the Cordio stac. + */ + static Gap &getInstance(); + + /** + * This function shall be called once the stack has been initialized + */ + void initialize(); + + /** + * @see ::Gap::setAddress + */ + virtual ble_error_t setAddress(AddressType_t type, const Address_t address); + + /** + * @see ::Gap::getAddress + */ + virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); + + /** + * @see ::Gap::setAdvertisingData + */ + virtual ble_error_t setAdvertisingData( + const GapAdvertisingData&, const GapAdvertisingData& + ); + + /** + * @see ::Gap::connect + */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams + ); + + /** + * @see ::Gap::getMinAdvertisingInterval + */ + virtual uint16_t getMinAdvertisingInterval() const; + + /** + * @see ::Gap::getMinNonConnectableAdvertisingInterval + */ + virtual uint16_t getMinNonConnectableAdvertisingInterval() const; + + /** + * @see ::Gap::getMaxAdvertisingInterval + */ + virtual uint16_t getMaxAdvertisingInterval() const; + + /** + * @see ::Gap::startAdvertising + */ + virtual ble_error_t startAdvertising(const GapAdvertisingParams &); + + /** + * @see ::Gap::stopAdvertising + */ + virtual ble_error_t stopAdvertising(); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect( + Handle_t connectionHandle, + DisconnectionReason_t reason + ); + + /** + * @see ::Gap::disconnect + */ + virtual ble_error_t disconnect(DisconnectionReason_t reason); + + /** + * @see ::Gap::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::Gap::getDeviceName + */ + virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); + + /** + * @see ::Gap::setAppearance + */ + virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::Gap::getAppearance + */ + virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); + + /** + * @see ::Gap::setTxPower + */ + virtual ble_error_t setTxPower(int8_t txPower); + + /** + * @see ::Gap::getPermittedTxPowerValues + */ + virtual void getPermittedTxPowerValues( + const int8_t **valueArrayPP, size_t *countP + ); + + /** + * Set the internal connection handle + */ + void setConnectionHandle(uint16_t m_connectionHandle); + + /** + * Get the current connection handle + */ + uint16_t getConnectionHandle(); + + /** + * @see ::Gap::getPreferredConnectionParams + */ + virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); + + /** + * @see ::Gap::setPreferredConnectionParams + */ + virtual ble_error_t setPreferredConnectionParams( + const ConnectionParams_t *params + ); + + /** + * @see ::Gap::updateConnectionParams + */ + virtual ble_error_t updateConnectionParams( + Handle_t handle, const ConnectionParams_t *params + ); + + /** + * @see ::Gap::startRadioScan + */ + virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); + + /** + * @see ::Gap::stopScan + */ + virtual ble_error_t stopScan(); + + /** + * Called when advertising is stopped. + */ + void advertisingStopped(); + + // Whitelist management + + /** + * @see ::Gap::getMaxWhitelistSize + */ + virtual uint8_t getMaxWhitelistSize(void) const; + + /** + * @see ::Gap::getWhitelist + */ + virtual ble_error_t getWhitelist(Whitelist_t &whitelist) const; + + /** + * @see ::Gap::setWhitelist + */ + virtual ble_error_t setWhitelist(const Whitelist_t &whitelist); + + /** + * @see ::Gap::setAdvertisingPolicyMode + */ + virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode); + + /** + * @see ::Gap::getAdvertisingPolicyMode + */ + virtual AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const; + + /** + * @see ::Gap::setScanningPolicyMode + */ + virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode); + + /** + * @see ::Gap::getScanningPolicyMode + */ + virtual ScanningPolicyMode_t getScanningPolicyMode(void) const; + + /** + * @see ::Gap::setInitiatorPolicyMode + */ + virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode); + + /** + * @see ::Gap::getInitiatorPolicyMode + */ + virtual InitiatorPolicyMode_t getInitiatorPolicyMode(void) const; + + /** + * @see ::Gap::reset + */ + virtual ble_error_t reset(void); + +private: + Gap(); + + Gap(Gap const &); + void operator=(Gap const &); + + uint16_t m_connectionHandle; + addr_type_t m_type; + Address_t m_addr; + + AdvertisingPolicyMode_t advertising_policy_mode; + ScanningPolicyMode_t scanning_policy_mode; + InitiatorPolicyMode_t initiator_policy_mode; + Whitelist_t whitelist; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GAP_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h new file mode 100644 index 00000000000..26dc08a78e8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -0,0 +1,217 @@ +/* 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 CORDIO_GATT_SERVER_H_ +#define CORDIO_GATT_SERVER_H_ + +#include +#include "ble/blecommon.h" +#include "ble/GattServer.h" +#include "ble/Gap.h" +#include "wsf_types.h" +#include "att_api.h" + +/*! client characteristic configuration descriptors settings */ +#define MAX_CCC_CNT 20 + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Cordio implementation of ::GattServer + */ +class GattServer : public ::GattServer +{ +public: + /** + * Return the singleton of the Cordio implementation of ::GattServer. + */ + static GattServer &getInstance(); + + /** + * Initialize the GattServer and add mandatory services (generic access and + * generic attribute service). + */ + void initialize(); + + /** + * @see ::GattServer::addService + */ + virtual ble_error_t addService(GattService &); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], + uint16_t *lengthP + ); + + /** + * @see ::GattServer::read + */ + virtual ble_error_t read( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t attributeHandle, + uint8_t buffer[], uint16_t *lengthP + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + GattAttribute::Handle_t, + const uint8_t[], uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::write + */ + virtual ble_error_t write( + Gap::Handle_t connectionHandle, + GattAttribute::Handle_t, + const uint8_t[], + uint16_t, + bool localOnly = false + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + const GattCharacteristic &characteristic, bool *enabledP + ); + + /** + * @see ::GattServer::areUpdatesEnabled + */ + virtual ble_error_t areUpdatesEnabled( + Gap::Handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabledP + ); + + /** + * @see ::GattServer::isOnDataReadAvailable + */ + virtual bool isOnDataReadAvailable() const; + + /** + * @see ::GattServer::getPreferredConnectionParams + */ + virtual ::Gap::ConnectionParams_t getPreferredConnectionParams(); + + /** + * @see ::GattServer::setPreferredConnectionParams + */ + virtual void setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params); + + /** + * @see ::GattServer::setDeviceName + */ + virtual ble_error_t setDeviceName(const uint8_t *deviceName); + + /** + * @see ::GattServer::getDeviceName + */ + virtual void getDeviceName(const uint8_t*& name, uint16_t& length); + + /** + * @see ::GattServer::setAppearance + */ + virtual void setAppearance(GapAdvertisingData::Appearance appearance); + + /** + * @see ::GattServer::getAppearance + */ + virtual GapAdvertisingData::Appearance getAppearance(); + + /** + * @see ::GattServer::reset + */ + virtual ble_error_t reset(void); + +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); + void add_generic_access_service(); + void add_generic_attribute_service(); + void* alloc_block(size_t block_size); + + 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; + 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; + + struct { + attsGroup_t service; + attsAttr_t attributes[7]; + uint8_t device_name_declaration_value[5]; + uint16_t device_name_length; + uint8_t appearance_declaration_value[5]; + uint16_t appearance; + uint8_t ppcp_declaration_value[5]; + uint8_t ppcp[8]; + + uint8_t*& device_name_value() { + return attributes[2].pValue; + } + } generic_access_service; + + struct { + attsGroup_t service; + attsAttr_t attributes[4]; + uint8_t service_changed_declaration[5]; + } generic_attribute_service; + + internal_service_t* registered_service; + alloc_block_t* allocated_blocks; + + uint16_t currentHandle; + +private: + GattServer(); + + GattServer(const GattServer &); + const GattServer& operator=(const GattServer &); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_GATT_SERVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h new file mode 100644 index 00000000000..401cffa8b83 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -0,0 +1,622 @@ +/* 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 CORDIO_PAL_ATT_CLIENT_ +#define CORDIO_PAL_ATT_CLIENT_ + +#include "ble/pal/AttClient.h" +#include "ble/pal/SimpleAttServerMessage.h" +#include "att_api.h" +#include "att_defs.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace cordio { + +class CordioAttClient : public ::ble::pal::AttClient { + +public: + CordioAttClient() : ::ble::pal::AttClient() { } + virtual ~CordioAttClient() { } + + /** + * @see ble::pal::AttClient::exchange_mtu_request + */ + virtual ble_error_t exchange_mtu_request(connection_handle_t connection) + { + AttcMtuReq(connection, pAttCfg->mtu); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::GattClient::get_mtu_size + */ + virtual ble_error_t get_mtu_size( + connection_handle_t connection_handle, + uint16_t& mtu_size + ) { + mtu_size = AttGetMtu(connection_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_information_request + */ + virtual ble_error_t find_information_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range + ) { + AttcFindInfoReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::find_by_type_value_request + */ + virtual ble_error_t find_by_type_value_request( + connection_handle_t connection_handle, + attribute_handle_range_t discovery_range, + uint16_t type, + const ArrayView& value + ) { + AttcFindByTypeValueReq( + connection_handle, + discovery_range.begin, + discovery_range.end, + type, + value.size(), + const_cast(value.data()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_type_request + */ + virtual ble_error_t read_by_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& type + ) { + AttcReadByTypeReq( + connection_handle, + read_range.begin, + read_range.end, + type.getLen(), + const_cast(type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_request + */ + virtual ble_error_t read_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle + ) { + AttcReadReq(connection_handle, attribute_handle); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_blob_request + */ + virtual ble_error_t read_blob_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset + ) { + AttcReadLongReq( + connection_handle, + attribute_handle, + offset, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_multiple_request + */ + virtual ble_error_t read_multiple_request( + connection_handle_t connection_handle, + const ArrayView& attribute_handles + ) { + AttcReadMultipleReq( + connection_handle, + attribute_handles.size(), + const_cast(attribute_handles.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::read_by_group_type_request + */ + virtual ble_error_t read_by_group_type_request( + connection_handle_t connection_handle, + attribute_handle_range_t read_range, + const UUID& group_type + ) { + AttcReadByGroupTypeReq( + connection_handle, + read_range.begin, + read_range.end, + group_type.getLen(), + const_cast(group_type.getBaseUUID()), + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_request + */ + virtual ble_error_t write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteReq( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::write_command + */ + virtual ble_error_t write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcWriteCmd( + connection_handle, + attribute_handle, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::signed_write_command + */ + virtual ble_error_t signed_write_command( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + const ArrayView& value + ) { + AttcSignedWriteCmd( + connection_handle, + attribute_handle, + /* sign counter from flash or AttsGetSignCounter() ? */ 0, + value.size(), + const_cast(value.data()) + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::prepare_write_request + */ + virtual ble_error_t prepare_write_request( + connection_handle_t connection_handle, + attribute_handle_t attribute_handle, + uint16_t offset, + const ArrayView& value + ) { + AttcPrepareWriteReq( + connection_handle, + attribute_handle, + offset, + value.size(), + const_cast(value.data()), + false, + false + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::execute_write_request + */ + virtual ble_error_t execute_write_request( + connection_handle_t connection_handle, + bool execute + ) { + AttcExecuteWriteReq( + connection_handle, + execute + ); + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::initialize + */ + virtual ble_error_t initialize() + { + return BLE_ERROR_NONE; + } + + /** + * @see ble::pal::AttClient::terminate + */ + virtual ble_error_t terminate() + { + return BLE_ERROR_NONE; + } + + // singleton of the ARM Cordio client + static CordioAttClient& get_client() + { + static CordioAttClient _client; + return _client; + } + +private: + // convert an array of byte to an uint16_t + static uint16_t to_uint16_t(const uint8_t* array) + { + uint16_t result; + memcpy(&result, array, sizeof(result)); + return result; + } + + /** + * Type of an event handler. + * @param The event to handle + * @return true if the event has been handled and false otherwise. + */ + typedef bool (*event_handler_t)(const attEvt_t*); + +public: + /** + * Callback which handle attEvt_t and forward them to on_server_event. + */ + static void att_client_handler(const attEvt_t* event) + { + // all handlers are stored in a static array + static const event_handler_t handlers[] = { + &timeout_event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler + }; + + // event->hdr.param: connection handle + // event->header.event: opcode from the request + // event->header.status: success or error code ... + // event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses. + // event->handle: handle for server initiated responses + + // traverse all handlers and execute them with the event in input. + // exit if an handler has handled the event. + for(size_t i = 0; i < (sizeof(handlers)/sizeof(handlers[0])); ++i) { + if (handlers[i](event)) { + return; + } + } + } + +private: + /** + * Event handler generator. + * @tparam Description of an event converter. It contains two static member + * function: + * - bool can_convert(const attEvt_t* event): return true if the event can + * be converted by the converter + * - convert(const attEvt_t* event): return the + * AttServerMessage converted from event. + * @param event + * @return + */ + template + static bool event_handler(const attEvt_t* event) + { + if (T::can_convert(event)) { + generated_handler(event, T::convert); + return true; + } + return false; + } + + static bool timeout_event_handler(const attEvt_t* event) + { + if(event->hdr.status != ATT_ERR_TIMEOUT) { + return false; + } + + get_client().on_transaction_timeout(event->hdr.param); + return true; + } + + template + static void generated_handler( + const attEvt_t* event, ResultType (*convert)(const attEvt_t*) + ) { + get_client().on_server_event( + event->hdr.param, + convert(event) + ); + } + + /** + * Traits defining can_convert for non ErrorResponse events. + */ + template + struct ResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && event->hdr.event == RequestID) { + return true; + } + return false; + } + }; + + /** + * Converter for an AttErrorResponse. + */ + struct ErrorResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status != ATT_SUCCESS) { + return true; + } + return false; + } + + static AttErrorResponse convert(const attEvt_t* event) + { + return AttErrorResponse( + static_cast(event->hdr.event * 2), + event->handle, + event->hdr.status + ); + } + }; + + /** + * Converter for an AttExchangeMTUResponse. + */ + struct ExchangeMtuResponseConverter { + static bool can_convert(const attEvt_t* event) + { + if(event->hdr.status == ATT_SUCCESS && + event->hdr.event == ATT_MTU_UPDATE_IND) { + return true; + } + return false; + } + + static AttExchangeMTUResponse convert(const attEvt_t* event) + { + return AttExchangeMTUResponse(event->mtu); + } + }; + + /** + * Converter for a SimpleAttFindInformationResponse. + */ + struct FindInformationResponseConverter : ResponseConverter { + static SimpleAttFindInformationResponse convert(const attEvt_t* event) + { + return SimpleAttFindInformationResponse( + static_cast(event->pValue[0]), + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a SimpleAttFindByTypeValueResponse. + */ + struct FindByTypeValueResponseConverter : ResponseConverter { + static SimpleAttFindByTypeValueResponse convert(const attEvt_t* event) + { + return SimpleAttFindByTypeValueResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByTypeResponse. + */ + struct ReadByTypeResponseConverter : ResponseConverter { + static SimpleAttReadByTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttReadResponse. + */ + struct ReadResponseConverter : ResponseConverter { + static AttReadResponse convert(const attEvt_t* event) + { + return AttReadResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadBlobResponse. + */ + struct ReadBlobResponseConverter : ResponseConverter { + static AttReadBlobResponse convert(const attEvt_t* event) + { + return AttReadBlobResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttReadMultipleResponse. + */ + struct ReadMultipleResponseConverter : ResponseConverter { + static AttReadMultipleResponse convert(const attEvt_t* event) + { + return AttReadMultipleResponse( + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a SimpleAttReadByGroupTypeResponse. + */ + struct ReadBygroupTypeResponseConverter : ResponseConverter { + static SimpleAttReadByGroupTypeResponse convert(const attEvt_t* event) + { + return SimpleAttReadByGroupTypeResponse( + event->pValue[0], + make_const_ArrayView( + event->pValue + 1, + event->valueLen - 1 + ) + ); + } + }; + + /** + * Converter for a AttWriteResponse. + */ + struct WriteResponseConverter : ResponseConverter { + static AttWriteResponse convert(const attEvt_t* event) + { + return AttWriteResponse(); + } + }; + + /** + * Converter for a AttPrepareWriteResponse. + */ + struct PrepareWriteResponseConverter : ResponseConverter { + static AttPrepareWriteResponse convert(const attEvt_t* event) + { + // WARNING: Not sure if correct, the stack erase the length parameter + return AttPrepareWriteResponse( + event->handle, + to_uint16_t(event->pValue + 2), + // FIXME: the stack set the lenght to 0, the data won't be seen ... + make_const_ArrayView( + event->pValue + 4, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttExecuteWriteResponse. + */ + struct ExecuteWriteResponseConverter : ResponseConverter { + static AttExecuteWriteResponse convert(const attEvt_t* event) + { + return AttExecuteWriteResponse(); + } + }; + + /** + * Converter for a AttHandleValueNotification. + */ + struct HandleValueNotificationConverter : ResponseConverter { + static AttHandleValueNotification convert(const attEvt_t* event) + { + return AttHandleValueNotification( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; + + /** + * Converter for a AttHandleValueIndication. + */ + struct HandleValueIndicationConverter : ResponseConverter { + static AttHandleValueIndication convert(const attEvt_t* event) + { + return AttHandleValueIndication( + event->handle, + make_const_ArrayView( + event->pValue, + event->valueLen + ) + ); + } + }; +}; + +} // cordio +} // vendor +} // pal +} // ble + +#endif /* CORDIO_PAL_ATT_CLIENT_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h new file mode 100644 index 00000000000..6522a0f50b3 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioSecurityManager.h @@ -0,0 +1,48 @@ +/* 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 CORDIO_SECURITY_MANAGER_H_ +#define CORDIO_SECURITY_MANAGER_H_ + +#include + +#include "ble/SecurityManager.h" + +namespace ble { +namespace vendor { +namespace cordio { + +class SecurityManager : public ::SecurityManager +{ +public: + static SecurityManager &getInstance() + { + static SecurityManager m_instance; + return m_instance; + } + +public: + SecurityManager() + { + /* empty */ + } +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_SECURITY_MANAGER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md new file mode 100644 index 00000000000..b6c208d2dc7 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/README.md @@ -0,0 +1,29 @@ +# BLE API Cordio Implementation + +The BLE API Cordio implementation allows Cordio licensee to easily deliver a +complete and up to date implementation of mbed BLE to their custommers using +mbed OS. + +To deliver a BLE port, vendors simply have to provide an HCI driver taillored +for the BLE module present on the board they want to support. + +## Source Organization + +The root contains the public header of the classes implementing BLE API public +interface. + +* `doc`: Documentation such as the HCI extension guide and the +porting guide. +* `driver`: HCI driver and transport interfaces. Also contains standard driver +implementation. +* `sources`: BLE API Implementation files +* `stack`: Cordio stack + * `cordio_stack`: Headerd of the cordio stack + * `lib`: precompiled libraries of the cordio stack + * `mbed_os_adaptation`: Headers of the interface responsible for the bridge + between BLE API and the Cordio stack. + +## Documentation + +* [HCI architecture](doc/HCIAbstraction.md) +* [Porting guide](doc/PortingGuide.md) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md new file mode 100644 index 00000000000..1a69a0d44c1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/HCIAbstraction.md @@ -0,0 +1,44 @@ +# HCI abstraction architecture + +The HCI driver is split into two interfaces: +* `CordioHCIDriver`: It is the driver for a BLE controller. It contains +the primitive necessary to start and initialize the controller. +* `CordioHCITransport`: It is the transport interface which is used by the HCI +driver to communicate with the controller. + +A `CordioHCITransport` is injected into a `CordioHCIDriver` at construction +time. A `CordioHCIDriver` is also injected at construction time of a `BLECordio` +instance. + +This can be summarized in the following diagram: + +![](resources/architecture.png) + +## CordioHCITransportDriver + +The single responsabilities of this a driver is to handle the communication with +the Bluetooth module. Basically, sending and reading bytes. + +Given that the Bluetooth specification define standard transport interface, an +implementation of the H4 interface is bundled in this port. It might be extended +in the future with an implementation of the H5 interface. However there is no +plan to provide the SDIO implementation at the moment. + +This interface is defined in the header file +[CordioHCITransportDriver.h](../driver/CordioHCITransportDriver.h) + +## CordioHCIDriver + +The responsibilities of this driver are: +* Provide the memory which will used by the Bluetooth stack. +* Initialize the bluetooth controller. +* Handle the reset/startup sequence of the bluetooth controller. + +This interface is defined in the header file +[CordioHCIDriver.h](../driver/CordioHCIDriver.h) + +A partial implementation is present in the file +[CordioHCIDriver.cpp](../driver/CordioHCIDriver.cpp). It defines the function +delivering memory to the stack and a complete reset sequence. However it does +not define any initialization for the Bluetooth controller, this part being +specific to the controller used. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md new file mode 100644 index 00000000000..dea13bcdf02 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/PortingGuide.md @@ -0,0 +1,551 @@ +# Porting guide + +Enabling the mbed BLE Cordio port for a given target is a two step process: +* The target shall be configured to include Cordio BLE port and Cordio libraries +during the build process. +* An implementation of the `CordioHCIDriver` class targeting the bluetooth +controller used shall be provided. + +## Target configuration + +This step happens in the file defining all mbed os targets. The file is located +in `targets/target.json`. + +### Add BLE feature + +First of all support for BLE has to be added to the target. This is achieved by +adding the string `BLE` in the list of `features` of the target. Once this +value has been added the sources of BLE api are added to the list of sources +compiled for the target. + +```json + "TARGET_NAME": { + "features": ["target features ...", "BLE"] + } +``` + +### Include Cordio BLE implementation + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE"] + } +``` + +### Include prebuilt libraries + +Last, the target shall also include the cordio libraries into the build. + +Four prebuilt libraries are provided: +* `wscore`: which contains the base component used by the Cordio stack. +* `wsstack`: The BLE stack itself, if contains the GAP and GATT layer as well as +the Security manager implementation. +* `wssec`: The low level implementation of the security layer. +* `wshci`: The HCI layer. + +The `wssec` and `wshci` libraries are delivered in feature folders. It allows +vendors to override those library if necessary. This can be required if the port +use specific crypto routine or require an highly modified HCI layer. + +To include the default library in the target, the features have to be added in +this list of the features of the target: +* `WSSEC`: Include the default `wssec` library. +* `WSHCI`: Include the default `wshci` library. + +The target should also compile the sources of the BLE Cordio port. It is +achieved by adding the string `CORDIO` in the list of the `extra_labels` +property of the target. + +```json + "TARGET_NAME": { + "extra_labels": ["target extra labels ...", "CORDIO"], + "features": ["target features ...", "BLE", "WSHCI", "WSSEC"] + } +``` + +## CordioHCIDriver implementation: + +A port shall include an HCI driver for the BLE module used by the target and +a factory function which create the BLE instance used by the user of BLE API. + +### Create source folder + +The port shall live in the folder of BLE API which host targets port : +`features/FEATURE_BLE/targets`. + +To isolate the port code from other code a folder containing the port code has +to be created. The name of this folder shall start with `TARGET_` and end with +the target name in capital. + +### Create the HCI driver + +The HCI driver is split in two entities: one which handle HCI communication with +the Bluetooth module and the other handling the initialization, reset sequence +and memory dedicated for the Bluetooth controller. + +More information about the architecture can be found in the +[HCI abstraction architecture](HCIAbstraction.md) document. + +#### HCITransport + +> **Note:** If the Bluetooth controller uses an H4 communication interface, this +step can be skipped. + +An empty transport driver can be coded as: + +```c++ +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class TransportDriver : public cordio::CordioHCITransportDriver { +public: + TransportDriver(/* specific constructor arguments*/); + + virtual ~TransportDriver(); + + virtual void initialize(); + + virtual void terminate(); + + virtual uint16_t write(uint8_t packet_type, uint16_t len, uint8_t *data); + +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +It shall inherits publicly from the base class `CordioHCITransportDriver`. + +* **Initialization/termination:** The functions `initialize` and `terminate` are +responsible for initializing and terminating the transport driver. It is not +necessary to initialize the transport in the constructor. + +* **Sending data** The function `write` shall sends data in input to the +Bluetooth controller and return the number of bytes in the `data` buffer sent. +Depending on the type of transport being implemented, the packet `type` might +have to be sent to the controller before the packet data. + +* **Receiving data**: HCI data from the Bluetooth controller shall be injected +in the system by invoking the function `on_data_received`. This function is +a static one and is provided by the base class. Its prototype is: + +```c++ +void on_data_received(uint8_t* data_received, uint16_t length_of_data_received); +``` + +#### HCIDriver + +The skeleton of driver is: + +```c++ +#include "CordioHCIDriver.h" + +namespace ble { +namespace vendor { +namespace target_name { + +class HCIDriver : public cordio::CordioHCIDriver { +public: + HCIDriver( + cordio::CordioHCITransportDriver& transport_driver, + /* specific constructor arguments*/ + ); + + virtual ~HCIDriver(); + + virtual void do_initialize(); + + virtual void do_terminate(); + + virtual buf_pool_desc_t get_buffer_pool_description(); + + virtual void start_reset_sequence(); + + virtual void handle_reset_sequence(uint8_t *msg); +private: + // private driver declarations +}; + +} // namespace target_name +} // namespace vendor +} // namespace ble +``` + +##### Initialization process + +The initialization/termination process is achieved by the couple of functions +`do_initialize` and `do_terminate`. Those function manages the state of the +bluetooth controller. + +> **Important:** It is unnecessary to initialize or terminate the hci transport +in those function because it is handled by the base class. The HCI transport is +initialized right before the call to `do_initialize` and is terminated right +after the call to `do_terminate`. + +##### Memory pool + +The implementation of the function `get_buffer_pool_description` in the base +class will return a buffer of 1040 bytes divided in different memory pools: + +| Chunk size (bytes) | Number of chunks | +|--------------------|------------------| +| 16 | 8 | +| 32 | 4 | +| 64 | 2 | +| 128 | 2 | +| 272 | 1 | + +A port shall override this function if the memory provided by the base class +doesn't match what is required by the Bluetooth controller driven. + +```c++ +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() { + static uint8_t buffer[/* buffer size */]; + static const wsfBufPoolDesc_t pool_desc[] = { + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + { /* chunk size */, /* number of chunks */ }, + }; + + return buf_pool_desc_t(buffer, pool_desc); +} +``` + +##### Reset sequence + +The reset sequence process is handled by three functions: + +* `start_reset_sequence`: This function start the process. The basic +implementation sends an HCI reset command to the Bluetooth controller. The +function shall be overridden in the driver if the bluetooth controller requires +more than just sending the standard reset command. + +* `handle_reset_sequence`: Entry point to the state machine handling the reset +process. Every time an HCI packet is received during the reset sequence, this +function is called with the HCI packet received. It's purpose is to prepare the +Bluetooth controller and set the parameters the stack needs to operate properly. +This function can be overridden if necessary. + +* `signal_reset_sequence_done`: This function shall be called once the reset +sequence is achieved. It cannot be overridden. + +###### Controller parameters to set + +This instruct the controller which events are relevant for the stack. + +The following parameters should be set in the controller (if supported): +* event mask: The reset sequence should issue the call +`HciSetEventMaskCmd((uint8_t *) hciEventMask)` +* LE event mask: The call `HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask)` +should be issued. +* 2nd page of events mask: Can be achieved by invoking +`HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2)`. + + +###### Stack runtime parameters + +Some stack parameters shall be acquired at runtime from the controller: + +* Bluetooth address: Can be queried with `HciReadBdAddrCmd`. Response shall be +copied into `hciCoreCb.bdAddr` with `BdaCpy`. +* Buffer size of the controller: Can be obtained by `HciLeReadBufSizeCmd`. The +return parameter *HC_ACL_Data_Packet_Length* shall be copied into +`hciCoreCb.bufSize` and the response parameter +`HC_Synchronous_Data_Packet_Length`shall be copied into `hciCoreCb.numBufs`. +The value of `hciCoreCb.availBufs` shall be initialized with `hciCoreCb.numBufs`. +* Supported state: Queried with `HciLeReadSupStatesCmd`, the response shall go +into `hciCoreCb.leStates`. +* Whitelist size: Queried with `HciLeReadWhiteListSizeCmd` the response shall go +into `hciCoreCb.whiteListSize`. +* LE features supported: Obtained with `HciLeReadLocalSupFeatCmd`. The response +shall be stored into `hciCoreCb.leSupFeat`. +* Resolving list size: Obtained with `hciCoreReadResolvingListSize`. The response +shall go into `hciCoreCb.resListSize`. +* Max data length: Acquired with `hciCoreReadMaxDataLen`. The response parameter +`supportedMaxTxOctets` and `supportedMaxTxTime` shall be pass to the function +`HciLeWriteDefDataLen`. + + +The default implementation is: + +```c++ +void HCIDriver::handle_reset_sequence(uint8_t *pMsg) { + // only accept command complete event: + if (*pMsg != HCI_CMD_CMPL_EVT) { + return; + } + + uint16_t opcode; + static uint8_t randCnt; + + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); // copy opcode + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) + { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + // set the event mask to control which events are generated by the + // controller for the host + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + // set the event mask to control which LE events are generated by + // the controller for the host + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + // set the event mask to control which events are generated by the + // controller for the host (2nd page of flags ) + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + // Ask the Bluetooth address of the controller + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + // Store the Bluetooth address in the stack runtime parameter + BdaCpy(hciCoreCb.bdAddr, pMsg); + + // Read the size of the buffer of the controller + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + // Store the buffer parameters in the stack runtime parameters + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + // read the states and state combinations supported by the link + // layer of the controller + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + // store supported state and combination in the runtime parameters + // of the stack + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + // read the total of whitelist entries that can be stored in the + // controller. + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + // store the number of whitelist entries in the stack runtime + // parameters + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + // Read the LE features supported by the controller + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + // Store the set of LE features supported by the controller + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + // read the total number of address translation entries which can be + // stored in the controller resolving list. + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + // store the number of address translation entries in the stack + // runtime parameter + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + // read the Controller’s maximum supported payload octets and packet + // duration times for transmission and reception + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: + { + // store payload definition in the runtime stack parameters. + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } + break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) + { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + else + { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + // handle extended command + if (hciCoreCb.extResetSeq) + { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) + { + randCnt++; + HciLeRandCmd(); + } + else + { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } +} + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) + { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } + else + { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) + { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } + else + { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} +``` + + + +### HCI accessor function + +The HCI driver is injected in the `CordioBLE` class at construction site. +Given that the CordioBLE class doesn't know what class shall be used to +construct the driver nor it knows how to construct it, the port shall provide a +function returning a reference to the HCI driver. + +This function lives in the global namespace and its signature is: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver(); +``` + +A common implementation might be: + +```c++ +ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() { + static ble::vendor::target_name::TransportDriver transport_driver( + /* transport parameters */ + ); + + static ble::vendor::target_name::HCIDriver hci_driver( + transport_driver, /* other hci driver parameters */ + ); + + return hci_driver; +} +``` + +## Examples + +Implementation examples might be found for: +* [ST BlueNRG module](../../TARGET_NUCLEO_F401RE/BlueNrgHCIDriver.cpp): It uses +a custom transport driver and a vendor specific is sent right after the answer +to the reset command to switch the controller to link layer mode only. +* [EM9301 module](../../TARGET_Maxim/TARGET_MAX32620HSP/EM9301HCIDriver.cpp): +it uses a custom transport driver and doesn't doesn't send the command *Set +Event Mask Page 2* to the controller during the reset sequence because this +command is not supported by the controller. +* [PAN1326](../../TARGET_Maxim/TARGET_MAX32630FTHR/CC2564HCIDriver.cpp): It +uses the H4 transport driver. The reset sequence start by sending a +*service pack* then once the service pack has been transferred it continue +with the regular reset sequence. + + + + + + + + + + + + + + + + + diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png new file mode 100644 index 00000000000..f3bc8634c6c Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture.png differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png new file mode 100644 index 00000000000..7e765aa2604 Binary files /dev/null and b/features/FEATURE_BLE/targets/TARGET_CORDIO/doc/resources/architecture_layer.png differ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp new file mode 100644 index 00000000000..9ca29a336ed --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp @@ -0,0 +1,261 @@ +/* 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. + */ + +#include +#include + +#include "CordioHCIDriver.h" +#include "hci_api.h" +#include "hci_cmd.h" +#include "hci_core.h" +#include "bstream.h" +#include "hci_mbed_os_adaptation.h" + +#define HCI_RESET_RAND_CNT 4 + +namespace ble { +namespace vendor { +namespace cordio { + +namespace { + +static void hciCoreReadMaxDataLen(void) +{ + /* if LE Data Packet Length Extensions is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) { + /* send next command in sequence */ + HciLeReadMaxDataLen(); + } else { + /* send next command in sequence */ + HciLeRandCmd(); + } +} + +static void hciCoreReadResolvingListSize(void) +{ + /* if LL Privacy is supported by Controller and included */ + if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) && + (hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) { + /* send next command in sequence */ + HciLeReadResolvingListSize(); + } else { + hciCoreCb.resListSize = 0; + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + } +} + +} // end of anonymous namespace + + +CordioHCIDriver::CordioHCIDriver(CordioHCITransportDriver& transport_driver) : + _transport_driver(transport_driver) { } + +void CordioHCIDriver::initialize() +{ + _transport_driver.initialize(); + do_initialize(); +} + +void CordioHCIDriver::terminate() +{ + do_terminate(); + _transport_driver.terminate(); +} + +buf_pool_desc_t CordioHCIDriver::get_buffer_pool_description() +{ + static union { + uint8_t buffer[2250]; + uint64_t align; + }; + static const wsfBufPoolDesc_t pool_desc[] = { + { 16, 16 }, + { 32, 16 }, + { 64, 8 }, + { 128, 4 }, + { 272, 1 } + }; + + return buf_pool_desc_t(buffer, pool_desc); +} + +void CordioHCIDriver::start_reset_sequence() +{ + /* send an HCI Reset command to start the sequence */ + HciResetCmd(); +} + +void CordioHCIDriver::handle_reset_sequence(uint8_t *pMsg) +{ + uint16_t opcode; + static uint8_t randCnt; + + /* if event is a command complete event */ + if (*pMsg == HCI_CMD_CMPL_EVT) { + /* parse parameters */ + pMsg += HCI_EVT_HDR_LEN; + pMsg++; /* skip num packets */ + BSTREAM_TO_UINT16(opcode, pMsg); + pMsg++; /* skip status */ + + /* decode opcode */ + switch (opcode) { + case HCI_OPCODE_RESET: + /* initialize rand command count */ + randCnt = 0; + + /* send next command in sequence */ + HciSetEventMaskCmd((uint8_t *) hciEventMask); + break; + + case HCI_OPCODE_SET_EVENT_MASK: + /* send next command in sequence */ + HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask); + break; + + case HCI_OPCODE_LE_SET_EVENT_MASK: + /* send next command in sequence */ + HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2); + break; + + case HCI_OPCODE_SET_EVENT_MASK_PAGE2: + /* send next command in sequence */ + HciReadBdAddrCmd(); + break; + + case HCI_OPCODE_READ_BD_ADDR: + /* parse and store event parameters */ + BdaCpy(hciCoreCb.bdAddr, pMsg); + + /* send next command in sequence */ + HciLeReadBufSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_BUF_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg); + BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg); + + /* initialize ACL buffer accounting */ + hciCoreCb.availBufs = hciCoreCb.numBufs; + + /* send next command in sequence */ + HciLeReadSupStatesCmd(); + break; + + case HCI_OPCODE_LE_READ_SUP_STATES: + /* parse and store event parameters */ + memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN); + + /* send next command in sequence */ + HciLeReadWhiteListSizeCmd(); + break; + + case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg); + + /* send next command in sequence */ + HciLeReadLocalSupFeatCmd(); + break; + + case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT: + /* parse and store event parameters */ + BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg); + + /* send next command in sequence */ + hciCoreReadResolvingListSize(); + break; + + case HCI_OPCODE_LE_READ_RES_LIST_SIZE: + /* parse and store event parameters */ + BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg); + + /* send next command in sequence */ + hciCoreReadMaxDataLen(); + break; + + case HCI_OPCODE_LE_READ_MAX_DATA_LEN: { + uint16_t maxTxOctets; + uint16_t maxTxTime; + + BSTREAM_TO_UINT16(maxTxOctets, pMsg); + BSTREAM_TO_UINT16(maxTxTime, pMsg); + + /* use Controller's maximum supported payload octets and packet duration times + * for transmission as Host's suggested values for maximum transmission number + * of payload octets and maximum packet transmission time for new connections. + */ + HciLeWriteDefDataLen(maxTxOctets, maxTxTime); + } break; + + case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN: + if (hciCoreCb.extResetSeq) { + /* send first extended command */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } else { + /* initialize extended parameters */ + hciCoreCb.maxAdvDataLen = 0; + hciCoreCb.numSupAdvSets = 0; + hciCoreCb.perAdvListSize = 0; + + /* send next command in sequence */ + HciLeRandCmd(); + } + break; + + case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN: + case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS: + case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE: + if (hciCoreCb.extResetSeq) { + /* send next extended command in sequence */ + (*hciCoreCb.extResetSeq)(pMsg, opcode); + } + break; + + case HCI_OPCODE_LE_RAND: + /* check if need to send second rand command */ + if (randCnt < (HCI_RESET_RAND_CNT-1)) { + randCnt++; + HciLeRandCmd(); + } else { + /* last command in sequence; set resetting state and call callback */ + signal_reset_sequence_done(); + } + break; + + default: + break; + } + } +} + +void CordioHCIDriver::signal_reset_sequence_done() +{ + hci_mbed_os_signal_reset_sequence_done(); +} + +uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return _transport_driver.write(type, len, pData); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h new file mode 100644 index 00000000000..10ac769c82c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h @@ -0,0 +1,145 @@ +/* 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 CORDIO_HCI_DRIVER_H_ +#define CORDIO_HCI_DRIVER_H_ + +#include +#include +#include "wsf_buf.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Contain description of the memory pool used by the Cordio stack. + */ +struct buf_pool_desc_t { + /** + * Create a new memory pool description + * @param buffer the Buffer used by the memory pool. + * @param pool_desc How the memory is split + */ + template + buf_pool_desc_t( + uint8_t (&buffer)[BufferSize], + const wsfBufPoolDesc_t (&pool_desc)[PoolCount] + ) : buffer_memory(buffer), buffer_size(BufferSize), + pool_description(pool_desc), pool_count(PoolCount) + { + } + + uint8_t* buffer_memory; /// Pointer to the buffer memory + size_t buffer_size; /// Size of the buffer + const wsfBufPoolDesc_t* pool_description; /// Pointer to the first element describing the pool + size_t pool_count; /// Number of pools +}; + +/** + * Base class of the HCI driver use by the BLE port of the Cordio stack. + * This class provide to the stack: + * - The buffer necessary to run BLE API + * - The reset sequence of the BLE module + * - Access to the write function of the underlying HCITransport driver. + */ +class CordioHCIDriver { +public: + /** + * Construct a new instance of an HCI driver. + * @param transport_driver The driver used to communicate with the chip. + */ + CordioHCIDriver(CordioHCITransportDriver& transport_driver); + + /** + * Driver destructor + */ + virtual ~CordioHCIDriver() { } + + /** + * Return the set of memory pool which will be used by the Cordio stack + */ + virtual buf_pool_desc_t get_buffer_pool_description(); + + /** + * Initialize the HCI driver. + * This function start by initializing the transport driver then it delegates + * what's remain of the initialization to the function do_initialize. + */ + void initialize(); + + /** + * Termination of the driver. + * It call in sequence: + * - do_terminate + * - terminate the transport driver. + */ + void terminate(); + + /** + * Start the reset sequence of the BLE module. + */ + virtual void start_reset_sequence(); + + /** + * Handle HCI messages received during the reset sequence. + * + * @param msg The HCI message received. + * @note The driver should signal to the stack that the initialization + * sequence is done by calling the function: signal_reset_sequence_done. + */ + virtual void handle_reset_sequence(uint8_t *msg); + + /** + * Signal to the stack that the reset sequence has been done. + */ + void signal_reset_sequence_done(); + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + /** + * Initialize the chip. + * The transport is up at that time. + */ + virtual void do_initialize() = 0; + + /** + * Terminate the driver + */ + virtual void do_terminate() = 0; + + CordioHCITransportDriver& _transport_driver; +}; + + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp new file mode 100644 index 00000000000..01b0b1016a8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.cpp @@ -0,0 +1,33 @@ +/* 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. + */ + +#include "CordioHCITransportDriver.h" +#include "CordioHCIDriver.h" + +extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len); + +namespace ble { +namespace vendor { +namespace cordio { + +void CordioHCITransportDriver::on_data_received(uint8_t* data, uint16_t len) +{ + hciTrSerialRxIncoming(data, len); +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h new file mode 100644 index 00000000000..a7e7499f210 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCITransportDriver.h @@ -0,0 +1,73 @@ +/* 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 CORDIO_HCI_TRANSPORT_DRIVER_H_ +#define CORDIO_HCI_TRANSPORT_DRIVER_H_ + +#include + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Base class of the HCI transport driver. + * It allow the stack to write data in the HCI channel. + */ +class CordioHCITransportDriver { +public: + /** + * Driver destructor. + */ + virtual ~CordioHCITransportDriver() { } + + /** + * Inialization of the transport. + */ + virtual void initialize() = 0; + + /** + * termination of the transport. + */ + virtual void terminate() = 0; + + /** + * Write data in the transport channel. + * + * @param type The type of packet to transmit. It might be an HCI command + * packet, ACL packet or EVT packet. Depending on the type of transport + * it can prefix the packet itself. + * @param len Number of bytes to transmit. + * @param pData pointer to the data to transmit. + * + * @return The number of bytes which have been transmited. + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData) = 0; + + /** + * The driver shall call this function whenever data bytes are received. + * + * @param data Pointer to the data received. + * @param len Number of bytes received. + */ + static void on_data_received(uint8_t* data, uint16_t len); +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_HCI_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp new file mode 100644 index 00000000000..5ceff2b12ed --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.cpp @@ -0,0 +1,70 @@ +/* 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. + */ + +#include "H4TransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +H4TransportDriver::H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) : + uart(tx, rx, baud), cts(cts), rts(rts) { } + +void H4TransportDriver::initialize() +{ + uart.format( + /* bits */ 8, + /* parity */ SerialBase::None, + /* stop bit */ 1 + ); + + uart.set_flow_control( + /* flow */ SerialBase::RTSCTS, + /* rts */ rts, + /* cts */ cts + ); + + uart.attach( + callback(this, &H4TransportDriver::on_controller_irq), + SerialBase::RxIrq + ); +} + +void H4TransportDriver::terminate() { } + +uint16_t H4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData) +{ + uint16_t i = 0; + while (i < len + 1) { + uint8_t to_write = i == 0 ? type : pData[i - 1]; + while (uart.writeable() == 0); + uart.putc(to_write); + ++i; + } + return len; +} + +void H4TransportDriver::on_controller_irq() +{ + while (uart.readable()) { + uint8_t char_received = uart.getc(); + on_data_received(&char_received, 1); + } +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h new file mode 100644 index 00000000000..6e6e1d4b011 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/driver/H4TransportDriver.h @@ -0,0 +1,76 @@ +/* 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 CORDIO_H4_TRANSPORT_DRIVER_H_ +#define CORDIO_H4_TRANSPORT_DRIVER_H_ + +#include +#include "mbed.h" +#include "CordioHCITransportDriver.h" + +namespace ble { +namespace vendor { +namespace cordio { + +/** + * Implementation of the H4 driver. + */ +class H4TransportDriver : public CordioHCITransportDriver { +public: + /** + * Initialize the transport driver. + * + * @param tx tx pin name. + * @param rx rx pin name + * @param cts cts pin name + * @param rts rts pin name. + * @param baud baud use to communicate with the ble module + */ + H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud); + + /** + * Destructor + */ + virtual ~H4TransportDriver() { } + + /** + * @see CordioHCITransportDriver::initialize + */ + virtual void initialize(); + + /** + * @see CordioHCITransportDriver::terminate + */ + virtual void terminate(); + + /** + * @see CordioHCITransportDriver::write + */ + virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData); + +private: + void on_controller_irq(); + + Serial uart; + PinName cts; + PinName rts; +}; + +} // namespace cordio +} // namespace vendor +} // namespace ble + +#endif /* CORDIO_H4_TRANSPORT_DRIVER_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp new file mode 100644 index 00000000000..ba2d5e15bd0 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -0,0 +1,452 @@ +/* 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. + */ + +#include "mbed.h" +#include "us_ticker_api.h" +#include "BLE.h" +#include "wsf_types.h" +#include "wsf_msg.h" +#include "wsf_os.h" +#include "wsf_buf.h" +#include "wsf_timer.h" +#include "hci_handler.h" +#include "dm_handler.h" +#include "l2c_handler.h" +#include "att_handler.h" +#include "smp_handler.h" +#include "l2c_api.h" +#include "att_api.h" +#include "smp_api.h" +#include "hci_drv.h" +#include "CordioBLE.h" +#include "mbed_assert.h" + +#include "CordioPalAttClient.h" + +/*! WSF handler ID */ +wsfHandlerId_t stack_handler_id; + +/* Store the Event signaling state */ +bool isEventsSignaled = false; + +/** + * Weak definition of ble_cordio_get_hci_driver. + * A runtime error is generated if the user does not define any + * ble_cordio_get_hci_driver. + */ +MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver() +{ + error("Please provide an implementation for the HCI driver"); + ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL; + return *bad_instance; +} + +/** + * Low level HCI interface between Cordio stack and the port. + */ +extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData) +{ + return ble_cordio_get_hci_driver().write(type, len, pData); +} + +extern "C" void hci_mbed_os_start_reset_sequence(void) +{ + ble_cordio_get_hci_driver().start_reset_sequence(); +} + +extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg) +{ + ble_cordio_get_hci_driver().handle_reset_sequence(msg); +} + +/* + * This function will signal to the user code by calling signalEventsToProcess. + * It is registered and called into the Wsf Stack. + */ +extern "C" void wsf_mbed_ble_signal_event(void) +{ + if(isEventsSignaled == false) { + isEventsSignaled = true; + ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE); + } +} + +/** + * BLE-API requires an implementation of the following function in order to + * obtain its transport handle. + */ +BLEInstanceBase *createBLEInstance() +{ + return (&(ble::vendor::cordio::BLE::deviceInstance())); +} + +namespace ble { +namespace vendor { +namespace cordio { + +BLE::BLE(CordioHCIDriver& hci_driver) : + initialization_status(NOT_INITIALIZED), + instanceID(::BLE::DEFAULT_INSTANCE) +{ + _hci_driver = &hci_driver; + stack_setup(); +} + +BLE::~BLE() { } + +/** + * The singleton which represents the BLE transport for the BLE. + */ +BLE& BLE::deviceInstance() +{ + static BLE instance( + ble_cordio_get_hci_driver() + ); + return instance; +} + +ble_error_t BLE::init( + ::BLE::InstanceID_t instanceID, + FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback) +{ + + switch (initialization_status) { + case NOT_INITIALIZED: + _init_callback = initCallback; + start_stack_reset(); + return BLE_ERROR_NONE; + + case INITIALIZING: + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + case INITIALIZED: + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_UNSPECIFIED; + } +} + +bool BLE::hasInitialized() const +{ + return initialization_status == INITIALIZED; +} + +ble_error_t BLE::shutdown() +{ + if (initialization_status != INITIALIZED) { + return BLE_ERROR_INITIALIZATION_INCOMPLETE; + } + + initialization_status = NOT_INITIALIZED; + _hci_driver->terminate(); + + getGattServer().reset(); + getGattClient().reset(); + getGap().reset(); + + return BLE_ERROR_NONE; +} + +const char* BLE::getVersion() +{ + static const char version[] = "generic-cordio"; + return version; +} + +Gap& BLE::getGap() +{ + return cordio::Gap::getInstance(); +} + +const Gap& BLE::getGap() const +{ + return cordio::Gap::getInstance(); +} + +GattServer& BLE::getGattServer() +{ + return cordio::GattServer::getInstance(); +} + +const GattServer& BLE::getGattServer() const +{ + return cordio::GattServer::getInstance(); +} + +::GattClient& BLE::getGattClient() +{ + static pal::AttClientToGattClientAdapter pal_client( + pal::vendor::cordio::CordioAttClient::get_client() + ); + static generic::GenericGattClient client(&pal_client); + + return client; +} + +SecurityManager& BLE::getSecurityManager() +{ + return cordio::SecurityManager::getInstance(); +} + +const SecurityManager& BLE::getSecurityManager() const +{ + return cordio::SecurityManager::getInstance(); +} + +void BLE::waitForEvent() +{ + static Timeout nextTimeout; + timestamp_t nextTimestamp; + bool_t pTimerRunning; + + callDispatcher(); + + if (wsfOsReadyToSleep()) { + // setup an mbed timer for the next cordio timeout + nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +void BLE::processEvents() +{ + if (isEventsSignaled) { + isEventsSignaled = false; + callDispatcher(); + } + } + + void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg) + { + if (msg == NULL) { + return; + } + + switch(msg->event) { + case DM_RESET_CMPL_IND: { + ::BLE::InitializationCompleteCallbackContext context = { + ::BLE::Instance(::BLE::DEFAULT_INSTANCE), + BLE_ERROR_NONE + }; + deviceInstance().getGattServer().initialize(); + deviceInstance().getGap().initialize(); + deviceInstance().initialization_status = INITIALIZED; + _init_callback.call(&context); + } break; + + case DM_ADV_START_IND: + break; + + case DM_ADV_STOP_IND: + Gap::getInstance().advertisingStopped(); + break; + + case DM_SCAN_REPORT_IND: { + hciLeAdvReportEvt_t *scan_report = (hciLeAdvReportEvt_t*) msg; + Gap::getInstance().processAdvertisementReport( + scan_report->addr, + scan_report->rssi, + (scan_report->eventType == DM_RPT_SCAN_RESPONSE) ? true : false, + (GapAdvertisingParams::AdvertisingType_t) scan_report->eventType, + scan_report->len, + scan_report->pData + ); + } break; + + case DM_CONN_OPEN_IND: { + hciLeConnCmplEvt_t* conn_evt = (hciLeConnCmplEvt_t*) msg; + dmConnId_t connection_id = conn_evt->hdr.param; + Gap::getInstance().setConnectionHandle(connection_id); + Gap::AddressType_t own_addr_type; + Gap::Address_t own_addr; + Gap::getInstance().getAddress(&own_addr_type, own_addr); + + Gap::ConnectionParams_t params = { + conn_evt->connInterval, + conn_evt->connInterval, + conn_evt->connLatency, + conn_evt->supTimeout + }; + + Gap::getInstance().processConnectionEvent( + connection_id, + (conn_evt->role == DM_ROLE_MASTER) ? Gap::CENTRAL : Gap::PERIPHERAL, + (Gap::AddressType_t) conn_evt->addrType, + conn_evt->peerAddr, + own_addr_type, + own_addr, + ¶ms + ); + } break; + + case DM_CONN_CLOSE_IND: { + dmEvt_t *disconnect_evt = (dmEvt_t*) msg; + Gap::getInstance().setConnectionHandle(DM_CONN_ID_NONE); + Gap::getInstance().processDisconnectionEvent( + disconnect_evt->hdr.param, + (Gap::DisconnectionReason_t) disconnect_evt->connClose.reason + ); + } break; + + default: + break; + } +} + +void BLE::device_manager_cb(dmEvt_t* dm_event) +{ + BLE::deviceInstance().stack_handler(0, &dm_event->hdr); +} + +/* + * AttServerInitDeInitCback callback is used to Initialize/Deinitialize + * the CCC Table of the ATT Server when a remote peer requests to Open + * or Close the connection. + */ + void BLE::connection_handler(dmEvt_t* dm_event) + { + dmConnId_t connId = (dmConnId_t)dm_event->hdr.param; + + switch (dm_event->hdr.event) { + case DM_CONN_OPEN_IND: + /* set up CCC table with uninitialized (all zero) values */ + AttsCccInitTable(connId, NULL); + break; + case DM_CONN_CLOSE_IND: + /* clear CCC table on connection close */ + AttsCccClearTable(connId); + break; + default: + break; + } +} + +void BLE::timeoutCallback() +{ + wsf_mbed_ble_signal_event(); +} + +void BLE::stack_setup() +{ + MBED_ASSERT(_hci_driver != NULL); + + wsfHandlerId_t handlerId; + + buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description(); + + // Initialize buffers with the ones provided by the HCI driver + uint16_t bytes_used = WsfBufInit( + buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory, + buf_pool_desc.pool_count, buf_pool_desc.pool_description + ); + + MBED_ASSERT(bytes_used != 0); + + WsfTimerInit(); + SecInit(); + + // Note: enable once security is supported +#if 0 + SecAesInit(); + SecCmacInit(); + SecEccInit(); +#endif + + handlerId = WsfOsSetNextHandler(HciHandler); + HciHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(DmHandler); + DmAdvInit(); + DmScanInit(); + DmConnInit(); + DmConnMasterInit(); + DmConnSlaveInit(); + DmSecInit(); + + // Note: enable once security is supported +#if 0 + DmSecLescInit(); + DmPrivInit(); +#endif + DmHandlerInit(handlerId); + + handlerId = WsfOsSetNextHandler(L2cSlaveHandler); + L2cSlaveHandlerInit(handlerId); + L2cInit(); + L2cSlaveInit(); + L2cMasterInit(); + + handlerId = WsfOsSetNextHandler(AttHandler); + AttHandlerInit(handlerId); + AttsInit(); + AttsIndInit(); + AttcInit(); + + handlerId = WsfOsSetNextHandler(SmpHandler); + SmpHandlerInit(handlerId); + SmprScInit(); + SmpiInit(); + + stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler); + + DmRegister(BLE::device_manager_cb); + DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb); + AttConnRegister(BLE::connection_handler); + AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler); +} + +void BLE::start_stack_reset() +{ + _hci_driver->initialize(); + DmDevReset(); +} + +void BLE::callDispatcher() +{ + static uint32_t lastTimeUs = us_ticker_read(); + uint32_t currTimeUs, deltaTimeMs; + + // Update the current cordio time + currTimeUs = us_ticker_read(); + deltaTimeMs = (currTimeUs - lastTimeUs) / 1000; + if (deltaTimeMs > 0) { + WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK); + lastTimeUs += deltaTimeMs * 1000; + } + + wsfOsDispatcher(); + + if (wsfOsReadyToSleep()) { + static Timeout nextTimeout; + // setup an mbed timer for the next Cordio timeout + bool_t pTimerRunning; + timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000; + if (pTimerRunning) { + nextTimeout.attach_us(timeoutCallback, nextTimestamp); + } + } +} + +CordioHCIDriver* BLE::_hci_driver = NULL; + +FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback; + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp new file mode 100644 index 00000000000..450a2def4bc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGap.cpp @@ -0,0 +1,543 @@ +/* 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. + */ + +#include + +#include "CordioGap.h" +#include "mbed.h" +#include "dm_api.h" +#include "CordioGattServer.h" +#include "hci_core.h" + +/**< Minimum Advertising interval in 625 us units, i.e. 20 ms. */ +#define BLE_GAP_ADV_INTERVAL_MIN 0x0020 + +/**< Minimum Advertising interval in 625 us units for non connectable mode, i.e. 100 ms. */ +#define BLE_GAP_ADV_NONCON_INTERVAL_MIN 0x00A0 + +/**< Maximum Advertising interval in 625 us units, i.e. 10.24 s. */ +#define BLE_GAP_ADV_INTERVAL_MAX 0x4000 + +namespace ble { +namespace vendor { +namespace cordio { + +Gap &Gap::getInstance() +{ + static Gap m_instance; + return m_instance; +} + +void Gap::initialize() +{ + uint8_t whitelist_size = HciGetWhiteListSize(); + + if (whitelist_size == 0) { + return; + } + + whitelist.addresses = new(std::nothrow) BLEProtocol::Address_t[whitelist_size]; + if (whitelist.addresses == NULL) { + return; + } + + whitelist.size = 0; + whitelist.capacity = hciCoreCb.whiteListSize; +} + +ble_error_t Gap::setAddress(AddressType_t type, const Address_t address) +{ + switch (type) { + case BLEProtocol::AddressType::PUBLIC: + // TODO: use vendor specific commands from the driver + return BLE_ERROR_OPERATION_NOT_PERMITTED; + + // See bluetooth 5, Vol 6 part, part B, 1.3.2 + case BLEProtocol::AddressType::RANDOM_STATIC: + if ((address[5] >> 6) != 3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + m_type = type; + BdaCpy(m_addr, address); + DmDevSetRandAddr(m_addr); + break; + + // should not be here, generation is supposed to be handled by the controller. + case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: + case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + m_type = type; + return BLE_ERROR_NONE; + + default: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + DmAdvSetAddrType(m_type); + DmConnSetAddrType(m_type); + DmScanSetAddrType(m_type); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAddress(AddressType_t *typeP, Address_t address) +{ + *typeP = m_type; + + if(m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE || + m_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { + return BLE_ERROR_NONE; + } + + BdaCpy(address, m_addr); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) +{ + /* Make sure we don't exceed the advertising payload length */ + if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + /* Make sure we have a payload! */ + if (advData.getPayloadLen() == 0) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* set advertising and scan response data for discoverable mode */ + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_ADV, advData.getPayloadLen(), (uint8_t*)advData.getPayload()); + DmAdvSetData(DM_ADV_HANDLE_DEFAULT, HCI_ADV_DATA_OP_COMP_FRAG, DM_DATA_LOC_SCAN, scanResponse.getPayloadLen(), (uint8_t*)scanResponse.getPayload()); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams +) { + // prepare the scan interval + if (scanParams != NULL) { + DmConnSetScanInterval(scanParams->getInterval(), scanParams->getWindow()); + } + + if (connectionParams != NULL) { + hciConnSpec_t conn_spec = { + /* connIntervalMin */ connectionParams->minConnectionInterval, + /* connIntervalMax */ connectionParams->maxConnectionInterval, + /* connLatency */ connectionParams->slaveLatency, + /* supTimeout */ connectionParams->connectionSupervisionTimeout, + /* minCeLen */ DM_GAP_CONN_EST_MIN_CE_LEN, + /* maxCeLen */ DM_GAP_CONN_EST_MAX_CE_LEN + }; + DmConnSetConnSpec(&conn_spec); + } + + DmScanStop(); + dmConnId_t connection_id = DmConnOpen( + DM_CLIENT_ID_APP, + HCI_INIT_PHY_LE_1M_BIT, + peerAddrType, + (uint8_t*) peerAddr + ); + + if (connection_id == DM_CONN_ID_NONE) { + return BLE_ERROR_INTERNAL_STACK_FAILURE; + } + + return BLE_ERROR_NONE; +} + +uint16_t Gap::getMinAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MIN; +} + +uint16_t Gap::getMinNonConnectableAdvertisingInterval() const +{ + return BLE_GAP_ADV_NONCON_INTERVAL_MIN; +} + +uint16_t Gap::getMaxAdvertisingInterval() const +{ + return BLE_GAP_ADV_INTERVAL_MAX; +} + +ble_error_t Gap::startAdvertising(const GapAdvertisingParams ¶ms) +{ + /* Make sure we support the advertising type */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { + /* ToDo: This requires a proper security implementation, etc. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /* Check interval range */ + if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) { + /* Min delay is slightly longer for unconnectable devices */ + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } else { + if ((params.getIntervalInADVUnits() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) || + (params.getIntervalInADVUnits() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + } + + /* Check timeout is zero for Connectable Directed */ + if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) { + /* Timeout must be 0 with this type, although we'll never get here */ + /* since this isn't implemented yet anyway */ + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + /* Check timeout for other advertising types */ + if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && + (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + uint16_t adv_interval_min = params.getIntervalInADVUnits(); + if (adv_interval_min == GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX) { + --adv_interval_min; + } + uint16_t adv_interval_max = adv_interval_min + 1; + + DmAdvSetInterval(DM_ADV_HANDLE_DEFAULT, adv_interval_min, adv_interval_max); + + /* Peer Addr Type 0 = Public */ + uint8_t peerAddrType = 0; + uint8_t peerAddr[6] = { 0 }; + DmAdvConfig(DM_ADV_HANDLE_DEFAULT, params.getAdvertisingType(), peerAddrType, peerAddr); + + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + uint16_t adv_durations[] = { (uint16_t) (params.getTimeout() * 1000) }; + uint8_t max_ea_events[] = { 0 }; + DmAdvStart(1, adv_handles, adv_durations, max_ea_events); + + state.advertising = 1; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopAdvertising(void) +{ + uint8_t adv_handles[] = { DM_ADV_HANDLE_DEFAULT }; + DmAdvStop(1, adv_handles); + + state.advertising = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::disconnect(DisconnectionReason_t reason) +{ + DmConnClose(DM_CLIENT_ID_APP, m_connectionHandle, reason); + + state.advertising = 0; + state.connected = 0; + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setDeviceName(const uint8_t *deviceName) +{ + return GattServer::getInstance().setDeviceName(deviceName); +} + +ble_error_t Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP) +{ + const uint8_t* name = NULL; + uint16_t length = 0; + + GattServer::getInstance().getDeviceName(name, length); + + if (deviceName != NULL) { + memcpy(deviceName, name, std::min((uint16_t) *lengthP, length)); + } + + *lengthP = length; + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAppearance(GapAdvertisingData::Appearance appearance) +{ + GattServer::getInstance().setAppearance(appearance); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::getAppearance(GapAdvertisingData::Appearance *appearanceP) +{ + *appearanceP = GattServer::getInstance().getAppearance(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setTxPower(int8_t txPower) +{ +#if 0 + HciVsSetTxPower(txPower); + return BLE_ERROR_NONE; +#else + return BLE_ERROR_NOT_IMPLEMENTED; +#endif +} + +void Gap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP) +{ + *valueArrayPP = NULL; + *countP = 0; +} + +void Gap::setConnectionHandle(uint16_t connectionHandle) +{ + m_connectionHandle = connectionHandle; +} + +uint16_t Gap::getConnectionHandle(void) +{ + return m_connectionHandle; +} + +ble_error_t Gap::getPreferredConnectionParams(ConnectionParams_t *params) +{ + *params = GattServer::getInstance().getPreferredConnectionParams(); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setPreferredConnectionParams(const ConnectionParams_t *params) +{ + // ensure that parameters are correct + // see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C] + // section 12.3 PERIPHERAL PREFERRED CONNECTION PARAMETERS CHARACTERISTIC + if (((0x0006 > params->minConnectionInterval) || (params->minConnectionInterval > 0x0C80)) && + params->minConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((params->minConnectionInterval > params->maxConnectionInterval) || (params->maxConnectionInterval > 0x0C80)) && + params->maxConnectionInterval != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (params->slaveLatency > 0x01F3) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (((0x000A > params->connectionSupervisionTimeout) || (params->connectionSupervisionTimeout > 0x0C80)) && + params->connectionSupervisionTimeout != 0xFFFF) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + GattServer::getInstance().setPreferredConnectionParams(*params); + return BLE_ERROR_NONE; +} + +ble_error_t Gap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams) +{ + if (DmConnCheckIdle(handle) != 0) { + return BLE_STACK_BUSY; + } + + hciConnSpec_t connSpec; + connSpec.connIntervalMin = newParams->minConnectionInterval; + connSpec.connIntervalMax = newParams->maxConnectionInterval; + connSpec.connLatency = newParams->slaveLatency; + connSpec.supTimeout = newParams->connectionSupervisionTimeout; + DmConnUpdate(handle, &connSpec); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::startRadioScan(const GapScanningParams &scanningParams) +{ + // not needed to start scanning if the whitelist is empty and the scanning + // policy filter all the advertising packets + if ((whitelist.size == 0) && (scanning_policy_mode == Gap::SCAN_POLICY_FILTER_ALL_ADV)) { + return BLE_ERROR_INVALID_STATE; + } + + uint16_t scan_intervals[] = { scanningParams.getInterval() }; + uint16_t scan_windows[] = { scanningParams.getWindow() }; + + DmScanSetInterval(HCI_SCAN_PHY_LE_1M_BIT, scan_intervals, scan_windows); + + uint8_t scanType = scanningParams.getActiveScanning() ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE; + uint32_t duration = (uint32_t)scanningParams.getTimeout() * 1000; + if (duration > 0xFFFF) { + // saturate to 16-bits + duration = 0xFFFF; + } + + DmScanStart(HCI_SCAN_PHY_LE_1M_BIT, DM_DISC_MODE_NONE, &scanType, TRUE, duration, 0); + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::stopScan(void) +{ + DmScanStop(); + return BLE_ERROR_NONE; +} + +void Gap::advertisingStopped(void) +{ + /* If advertising stopped due to a call to stopAdvertising(), state.advertising will + * be '0.' Otherwise, advertising must have stopped due to a timeout + */ + if (state.advertising) { + processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); + } +} + +uint8_t Gap::getMaxWhitelistSize(void) const +{ + return whitelist.capacity; +} + +ble_error_t Gap::getWhitelist(Whitelist_t &other) const +{ + // i is a shorthand for other.size + uint8_t& i = other.size; + + for (i = 0; (i < whitelist.capacity) && (i < other.capacity); ++i) { + other.addresses[i] = whitelist.addresses[i]; + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setWhitelist(const Whitelist_t& other) +{ + if (other.capacity > whitelist.capacity) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + // note : can be improved by sending the diff instead of the full list + + DmDevWhiteListClear(); + + // alias i to whitelist.size + uint8_t& i = whitelist.size; + + for (i = 0; (i < other.capacity) && (i < whitelist.capacity); ++i) { + whitelist.addresses[i] = other.addresses[i]; + DmDevWhiteListAdd( + (whitelist.addresses[i].type > 1) ? 0xFF : whitelist.addresses[i].type, + whitelist.addresses[i].address + ); + } + + return BLE_ERROR_NONE; +} + +ble_error_t Gap::setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_ADV, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + advertising_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::AdvertisingPolicyMode_t Gap::getAdvertisingPolicyMode(void) const +{ + return advertising_policy_mode; +} + +ble_error_t Gap::setScanningPolicyMode(ScanningPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_SCAN, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + scanning_policy_mode = mode; + return BLE_ERROR_NONE; + +} + +Gap::ScanningPolicyMode_t Gap::getScanningPolicyMode(void) const +{ + return scanning_policy_mode; +} + +ble_error_t Gap::setInitiatorPolicyMode(InitiatorPolicyMode_t mode) +{ + bool_t result = DmDevSetFilterPolicy( + DM_FILT_POLICY_MODE_INIT, + mode + ); + + if (result == false) { + return BLE_ERROR_INVALID_STATE; + } + + initiator_policy_mode = mode; + return BLE_ERROR_NONE; +} + +Gap::InitiatorPolicyMode_t Gap::getInitiatorPolicyMode(void) const +{ + return initiator_policy_mode; +} + +ble_error_t Gap::reset(void) +{ + this->::Gap::reset(); + delete[] whitelist.addresses; + whitelist.addresses = NULL; + whitelist.size = 0; + whitelist.capacity = 0; + return BLE_ERROR_NONE; +} + +Gap::Gap() : + ::Gap(), + m_connectionHandle(DM_CONN_ID_NONE), + m_type(BLEProtocol::AddressType::RANDOM_STATIC), + m_addr(), + advertising_policy_mode(ADV_POLICY_IGNORE_WHITELIST), + scanning_policy_mode(SCAN_POLICY_IGNORE_WHITELIST), + initiator_policy_mode(INIT_POLICY_IGNORE_WHITELIST), + whitelist() +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp new file mode 100644 index 00000000000..6f1a68da17f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -0,0 +1,763 @@ +/* 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. + */ + +#include +#include "CordioGattServer.h" +#include "CordioGap.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 { + +GattServer &GattServer::getInstance() +{ + static GattServer m_instance; + return m_instance; +} + +void GattServer::initialize() +{ + 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; + + // 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++; + } + } + + // Create cordio attribute list + internal_service->attGroup->pAttr = (attsAttr_t*)alloc_block(attListLen * sizeof(attsAttr_t)); + if (internal_service->attGroup->pAttr == NULL) { + return BLE_ERROR_BUFFER_OVERFLOW; + } + + // Create characteristics + internal_service->chars = new internal_char_t [service.getCharacteristicCount()]; + + attsAttr_t *currAtt = internal_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++; + + /* Add characteristics to the service */ + for (int i = 0; i < service.getCharacteristicCount(); i++) { + GattCharacteristic *p_char = service.getCharacteristic(i); + + /* 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; + } + } + 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); + + service.setHandle(startHandle); + + 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; + + if (AttsGetAttr(attributeHandle, &attribute_length, &attribute_value) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (buffer) { + memcpy(buffer, attribute_value, std::min(*lengthP, attribute_length)); + } + + *lengthP = attribute_length; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) +{ + // 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; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return read(attributeHandle, buffer, lengthP); +} + +ble_error_t GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + + if (!localOnly) { + if (connectionHandle != DM_CONN_ID_NONE) { + + // Check to see if this characteristic has a CCCD attribute + uint8_t idx; + for (idx = 0; idx < cccCnt; idx++) { + if (attributeHandle == cccHandles[idx]) { + break; + } + } + if (idx < cccCnt) { + // 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); + } + } + } + } + + 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) +{ + // 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; + } + } + + // This is not a CCCD. Use the non-connection specific update method. + return write(attributeHandle, buffer, len, localOnly); +} + +ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) +{ + uint16_t connectionHandle = Gap::getInstance().getConnectionHandle(); + + 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) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + 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) { + *enabledP = true; + } else { + *enabledP = false; + } + return BLE_ERROR_NONE; + } + } + } + + return BLE_ERROR_PARAM_OUT_OF_RANGE; +} + +bool GattServer::isOnDataReadAvailable() const +{ + return true; +} + +::Gap::ConnectionParams_t GattServer::getPreferredConnectionParams() +{ + ::Gap::ConnectionParams_t params = { 0 }; + memcpy(¶ms.minConnectionInterval, generic_access_service.ppcp, 2); + memcpy(¶ms.maxConnectionInterval, generic_access_service.ppcp + 2, 2); + memcpy(¶ms.slaveLatency, generic_access_service.ppcp + 4, 2); + memcpy(¶ms.connectionSupervisionTimeout, generic_access_service.ppcp + 6, 2); + return params; +} + +void GattServer::setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params) +{ + memcpy(generic_access_service.ppcp, ¶ms.minConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 2, ¶ms.maxConnectionInterval, 2); + memcpy(generic_access_service.ppcp + 4, ¶ms.slaveLatency, 2); + memcpy(generic_access_service.ppcp + 6, ¶ms.connectionSupervisionTimeout, 2); +} + +ble_error_t GattServer::setDeviceName(const uint8_t *deviceName) +{ + size_t length = 0; + + if (deviceName != NULL) { + length = strlen((const char*)deviceName); + } + + if (length == 0) { + free(generic_access_service.device_name_value()); + } else { + uint8_t* res = (uint8_t*) realloc(generic_access_service.device_name_value(), length); + if (res == NULL) { + return BLE_ERROR_NO_MEM; + } + + generic_access_service.device_name_value() = res; + memcpy(res, deviceName, length); + } + + generic_access_service.device_name_length = length; + + return BLE_ERROR_NONE; +} + +void GattServer::getDeviceName(const uint8_t*& name, uint16_t& length) +{ + length = generic_access_service.device_name_length; + name = generic_access_service.device_name_value(); +} + +void GattServer::setAppearance(GapAdvertisingData::Appearance appearance) +{ + generic_access_service.appearance = appearance; +} + +GapAdvertisingData::Appearance GattServer::getAppearance() +{ + return (GapAdvertisingData::Appearance) generic_access_service.appearance; +} + +ble_error_t GattServer::reset(void) +{ + this->::GattServer::reset(); + + while (registered_service) { + internal_service_t* s = registered_service; + registered_service = s->next; + AttsRemoveGroup(s->attGroup->startHandle); + delete s->attGroup; + delete[] s->chars; + delete s; + } + + while (allocated_blocks) { + alloc_block_t* b = allocated_blocks; + allocated_blocks = b->next; + free(b); + } + + AttsRemoveGroup(generic_access_service.service.startHandle); + AttsRemoveGroup(generic_attribute_service.service.startHandle); + free(generic_access_service.device_name_value()); + + currentHandle = 0; + cccCnt = 0; + + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + + return BLE_ERROR_NONE; +} + +void GattServer::cccCback(attsCccEvt_t *pEvt) +{ + 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); + } +} + +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::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) +{ + GattReadCallbackParams cbParams = { + connId, + handle, + offset, + *pAttr->pLen, + pAttr->pValue, + /* status */ BLE_ERROR_NONE, + }; + getInstance().handleDataReadEvent(&cbParams); + + 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 err; + + /* TODO: offset is not handled properly */ + if ((err = AttsSetAttr(handle, len, pValue)) != ATT_SUCCESS) { + return err; + } + + GattWriteCallbackParams::WriteOp_t writeOp; + switch (operation) { + case ATT_PDU_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_WRITE_REQ; + break; + case ATT_PDU_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_WRITE_CMD; + break; + case ATT_PDU_SIGNED_WRITE_CMD: + writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD; + break; + case ATT_PDU_PREP_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_PREP_WRITE_REQ; + break; + case ATT_PDU_EXEC_WRITE_REQ: + writeOp = GattWriteCallbackParams::OP_EXEC_WRITE_REQ_NOW; + break; + default: + writeOp = GattWriteCallbackParams::OP_INVALID; + break; + } + + GattWriteCallbackParams cbParams = { + connId, + handle, + writeOp, + offset, + len, + pValue + }; + getInstance().handleDataWrittenEvent(&cbParams); + + return ATT_SUCCESS; +} + +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; + + // bind attributes to the service + generic_access_service.service.pAttr = generic_access_service.attributes; + + attsAttr_t* current_attribute = generic_access_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGapSvcUuid; + current_attribute->maxLen = sizeof(attGapSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.device_name_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.device_name_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.device_name_declaration_value + 3, attDnChUuid, sizeof(attDnChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.device_name_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.device_name_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // device name value + ++current_attribute; + generic_access_service.device_name_length = 0; + current_attribute->pUuid = attDnChUuid; + current_attribute->maxLen = 248; + current_attribute->pLen = &generic_access_service.device_name_length; + current_attribute->pValue = NULL; + current_attribute->settings = ATTS_SET_VARIABLE_LEN; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.appearance_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.appearance_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.appearance_declaration_value + 3, attApChUuid, sizeof(attApChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.appearance_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.appearance_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // appearance value + ++current_attribute; + generic_access_service.appearance = 0; // unknown appearance + current_attribute->pUuid = attApChUuid; + current_attribute->maxLen = sizeof(generic_access_service.appearance); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = (uint8_t*) &generic_access_service.appearance; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + + // peripheral prefered connection parameters declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_access_service.ppcp_declaration_value[0] = ATT_PROP_READ; + // set value handle + memcpy(generic_access_service.ppcp_declaration_value + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_access_service.ppcp_declaration_value + 3, attPpcpChUuid, sizeof(attPpcpChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_access_service.ppcp_declaration_value; + current_attribute->maxLen = sizeof(generic_access_service.ppcp_declaration_value); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // peripheral prefered connection parameters value + ++current_attribute; + const uint8_t default_ppcp_value[] = { + 0xFF, 0xFF, // no specific min connection interval + 0xFF, 0xFF, // no specific max connection interval + 0x00, 0x00, // no slave latency + 0xFF, 0xFF // no specific connection supervision timeout + }; + memcpy(&generic_access_service.ppcp, default_ppcp_value, sizeof(default_ppcp_value)); + current_attribute->pUuid = attPpcpChUuid; + current_attribute->maxLen = sizeof(generic_access_service.ppcp); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = generic_access_service.ppcp; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + generic_access_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_access_service.service); +} + +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; + + // bind attributes to the service + generic_attribute_service.service.pAttr = generic_attribute_service.attributes; + + attsAttr_t* current_attribute = generic_attribute_service.attributes; + + // service attribute + current_attribute->pUuid = attPrimSvcUuid; + current_attribute->pValue = (uint8_t*) attGattSvcUuid; + current_attribute->maxLen = sizeof(attGattSvcUuid); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed declaration + currentHandle += 2; // note: incremented by two to get a pointer to the value handle + ++current_attribute; + + // set properties + generic_attribute_service.service_changed_declaration[0] = ATT_PROP_INDICATE; + // set value handle + memcpy(generic_attribute_service.service_changed_declaration + 1, ¤tHandle, sizeof(currentHandle)); + // set the characteristic UUID + memcpy(generic_attribute_service.service_changed_declaration + 3, attScChUuid, sizeof(attScChUuid)); + + current_attribute->pUuid = attChUuid; + current_attribute->pValue = generic_attribute_service.service_changed_declaration; + current_attribute->maxLen = sizeof(generic_attribute_service.service_changed_declaration); + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->settings = 0; + current_attribute->permissions = ATTS_PERMIT_READ; + + // service changed value + ++current_attribute; + current_attribute->pUuid = attScChUuid; + current_attribute->maxLen = 0; + current_attribute->pLen = ¤t_attribute->maxLen; + current_attribute->pValue = NULL; + current_attribute->settings = 0; + current_attribute->permissions = 0; + + // CCCD + ++current_attribute; + current_attribute->pUuid = attCliChCfgUuid; + current_attribute->pValue = (uint8_t*)&cccValues[cccCnt]; + 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++; + + generic_attribute_service.service.endHandle = currentHandle; + AttsAddGroup(&generic_attribute_service.service); + AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); +} + +void* GattServer::alloc_block(size_t block_size) { + alloc_block_t* block = (alloc_block_t*) malloc(sizeof(alloc_block_t) + block_size); + if (block == NULL) { + return NULL; + } + + if (allocated_blocks) { + block->next = allocated_blocks; + } else { + block->next = NULL; + } + + allocated_blocks = block; + + return block->data; +} + +GattServer::GattServer() : + ::GattServer(), cccSet(), cccValues(), cccHandles(), cccCnt(0), + generic_access_service(), generic_attribute_service(), + registered_service(NULL), allocated_blocks(NULL), + currentHandle(0) +{ +} + +} // namespace cordio +} // namespace vendor +} // namespace ble diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c new file mode 100644 index 00000000000..f42dff73f54 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/wsf_mbed_os_adaptation.c @@ -0,0 +1,28 @@ +/* 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. + */ + +#include "wsf_mbed_os_adaptation.h" +#include "mbed_critical.h" + +void wsf_mbed_os_critical_section_enter(void) +{ + core_util_critical_section_enter(); +} + +void wsf_mbed_os_critical_section_exit(void) +{ + core_util_critical_section_exit(); +} diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 00000000000..9a4f65e654f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, September 2015 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named “DEPENDENCIES” and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS 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. \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h new file mode 100644 index 00000000000..3ae594c3dbb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/dual_chip/hci_core_ps.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_core_ps.h + * + * \brief HCI core platform-specific interfaces for dual-chip. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_PS_H +#define HCI_CORE_PS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreResetSequence(uint8_t *pMsg); +void hciCoreNumCmplPkts(uint8_t *pMsg); +void hciCoreRecv(uint8_t msgType, uint8_t *pCoreRecvMsg); +uint8_t hciCoreVsCmdCmplRcvd(uint16_t opcode, uint8_t *pMsg, uint8_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_PS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h new file mode 100644 index 00000000000..33b5098d5bf --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_cmd.h @@ -0,0 +1,46 @@ +/*************************************************************************************************/ +/*! + * \file hci_cmd.h + * + * \brief HCI command module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CMD_H +#define HCI_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCmdSend(uint8_t *pData); +uint8_t *hciCmdAlloc(uint16_t opcode, uint16_t len); +void hciCmdInit(void); +void hciCmdTimeout(wsfMsgHdr_t *pMsg); +void hciCmdRecvCmpl(uint8_t numCmdPkts); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CMD_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h new file mode 100644 index 00000000000..74ad361b8a6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_core.h @@ -0,0 +1,129 @@ +/*************************************************************************************************/ +/*! + * \file hci_core.h + * + * \brief HCI core interfaces. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_CORE_H +#define HCI_CORE_H + +#include "hci_core_ps.h" +#include "wsf_queue.h" +#include "wsf_os.h" +#include "hci_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void(*hciResetSeq_t)(uint8_t *pMsg, uint16_t opcode); + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Per-connection structure for ACL packet accounting */ +typedef struct +{ + uint8_t *pTxAclPkt; /* Fragmenting TX ACL packet pointer */ + uint8_t *pNextTxFrag; /* Next TX ACL packet fragment */ + uint8_t *pRxAclPkt; /* RX ACL packet pointer */ + uint8_t *pNextRxFrag; /* Next RX ACL packet fragment */ + uint16_t handle; /* Connection handle */ + uint16_t txAclRemLen; /* Fragmenting TX ACL packet remaining length */ + uint16_t rxAclRemLen; /* Fragmented RX ACL packet remaining length */ + bool_t fragmenting; /* TRUE if fragmenting a TX ACL packet */ + bool_t flowDisabled; /* TRUE if data flow disabled */ + uint8_t queuedBufs; /* Queued ACL buffers on this connection */ + uint8_t outBufs; /* Outstanding ACL buffers sent to controller */ +} hciCoreConn_t; + +/* Main control block for dual-chip implementation */ +typedef struct +{ + hciCoreConn_t conn[DM_CONN_MAX]; /* Connection structures */ + uint8_t leStates[HCI_LE_STATES_LEN]; /* Controller LE supported states */ + bdAddr_t bdAddr; /* Bluetooth device address */ + wsfQueue_t aclQueue; /* HCI ACL TX queue */ + hciCoreConn_t *pConnRx; /* Connection struct for current transport RX packet */ + uint16_t maxRxAclLen; /* Maximum reassembled RX ACL packet length */ + uint16_t bufSize; /* Controller ACL data buffer size */ + uint8_t aclQueueHi; /* Disable flow when this many ACL buffers queued */ + uint8_t aclQueueLo; /* Enable flow when this many ACL buffers queued */ + uint8_t availBufs; /* Current avail ACL data buffers */ + uint8_t numBufs; /* Controller number of ACL data buffers */ + uint8_t whiteListSize; /* Controller white list size */ + uint8_t numCmdPkts; /* Controller command packed count */ + uint16_t leSupFeat; /* Controller LE supported features */ + int8_t advTxPwr; /* Controller advertising TX power */ + uint8_t resListSize; /* Controller resolving list size */ + uint16_t maxAdvDataLen; /* Controller maximum advertisement (or scan response) data length */ + uint8_t numSupAdvSets; /* Controller maximum number of advertising sets */ + uint8_t perAdvListSize; /* Controller periodic advertising list size */ + hciResetSeq_t extResetSeq; /* HCI extended reset sequence callback */ +} hciCoreCb_t; + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/* Control block */ +extern hciCoreCb_t hciCoreCb; + +/* Event mask */ +extern const uint8_t hciEventMask[HCI_EVT_MASK_LEN]; + +/* LE event mask */ +extern const uint8_t hciLeEventMask[HCI_LE_EVT_MASK_LEN]; + +/* Event mask page 2 */ +extern const uint8_t hciEventMaskPage2[HCI_EVT_MASK_LEN]; + +/* LE supported features configuration mask */ +extern uint16_t hciLeSupFeatCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciCoreInit(void); +void hciCoreResetStart(void); +void hciCoreConnOpen(uint16_t handle); +void hciCoreConnClose(uint16_t handle); +hciCoreConn_t *hciCoreConnByHandle(uint16_t handle); +void hciCoreSendAclData(hciCoreConn_t *pConn, uint8_t *pData); +void hciCoreTxReady(uint8_t bufs); +void hciCoreTxAclStart(hciCoreConn_t *pConn, uint16_t len, uint8_t *pData); +bool_t hciCoreTxAclContinue(hciCoreConn_t *pConn); +void hciCoreTxAclComplete(hciCoreConn_t *pConn, uint8_t *pData); +uint8_t *hciCoreAclReassembly(uint8_t *pData); +bool_t hciCoreTxAclDataFragmented(hciCoreConn_t *pConn); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_CORE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h new file mode 100644 index 00000000000..b0b6e562d5d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_drv.h @@ -0,0 +1,83 @@ +/*************************************************************************************************/ +/*! + * \file hci_drv.h + * + * \brief HCI driver interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2012-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DRV_H +#define HCI_DRV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn hciDrvWrite + * + * \brief Write data the driver. + * + * \param type HCI packet type + * \param len Number of bytes to write. + * \param pData Byte array to write. + * + * \return Return actual number of data bytes written. + * + * \note The type parameter allows the driver layer to prepend the data with a header on the + * same write transaction. + */ +/*************************************************************************************************/ +uint16_t hciDrvWrite(uint8_t type, uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvRead + * + * \brief Read data bytes from the driver. + * + * \param len Number of bytes to read. + * \param pData Byte array to store data. + * + * \return Return actual number of data bytes read. + */ +/*************************************************************************************************/ +uint16_t hciDrvRead(uint16_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn hciDrvReadyToSleep + * + * \brief Returns TRUE if driver allows MCU to enter low power sleep mode. + * + * \return TRUE if ready to sleep, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t hciDrvReadyToSleep(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DRV_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h new file mode 100644 index 00000000000..6e94e7f7985 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_evt.h @@ -0,0 +1,64 @@ +/*************************************************************************************************/ +/*! + * \file hci_evt.h + * + * \brief HCI event module. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_EVT_H +#define HCI_EVT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* HCI event statistics */ +typedef struct +{ + uint16_t numDiscCmplEvt; + uint16_t numEncChangeEvt; + uint16_t numReadRemoteVerInfoCmpEvt; + uint16_t numCmdCmplEvt; + uint16_t numCmdStatusEvt; + uint16_t numHwErrorEvt; + uint16_t numCmplPktsEvt; + uint16_t numDataBufOverflowEvt; + uint16_t numEncKeyRefreshCmplEvt; + uint16_t numLeMetaEvt; + uint16_t numVendorSpecEvt; + uint16_t numAuthToEvt; +} hciEvtStats_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciEvtProcessMsg(uint8_t *pEvt); +hciEvtStats_t *hciEvtGetStats(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_EVT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h new file mode 100644 index 00000000000..e91baa3ed6f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/hci/include/hci_tr.h @@ -0,0 +1,45 @@ +/*************************************************************************************************/ +/*! + * \file hci_tr.h + * + * \brief HCI transport interface. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_TR_H +#define HCI_TR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +void hciTrSendAclData(void *pContext, uint8_t *pAclData); +void hciTrSendCmd(uint8_t *pCmdData); +bool_t hciTrInit(uint8_t port, uint32_t baudRate, bool_t flowControl); +void hciTrShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_TR_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h new file mode 100644 index 00000000000..d16cbb4dd61 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/sec/include/sec_api.h @@ -0,0 +1,246 @@ +/*************************************************************************************************/ +/*! + * \file sec_api.h + * + * \brief AES and random number security service API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SEC_API_H +#define SEC_API_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! CMAC algorithm key length */ +#define SEC_CMAC_KEY_LEN 16 + +/*! CMAC algorithm result length */ +#define SEC_CMAC_HASH_LEN 16 + +/*! ECC algorithm key length */ +#define SEC_ECC_KEY_LEN 32 + +/*! Invalid AES Token */ +#define SEC_TOKEN_INVALID 0xFF + +/************************************************************************************************** + Data Types +**************************************************************************************************/ +/*! AES Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + uint8_t *pCiphertext; /*! pointer to 16 bytes of ciphertext data */ +} secMsg_t; + +/*! AES Security callback are the same as secMsg_t */ +typedef secMsg_t secAes_t; + +/*! CMAC Security callback are the same as secMsg_t */ +typedef secMsg_t secCmacMsg_t; + +/*! ECC Security public/private key pair */ +typedef struct +{ + uint8_t pubKey_x[SEC_ECC_KEY_LEN]; /*! x component of ecc public key */ + uint8_t pubKey_y[SEC_ECC_KEY_LEN]; /*! y component of ecc public key */ + uint8_t privKey[SEC_ECC_KEY_LEN]; /*! ecc private key */ +} secEccKey_t; + +/*! ECC security DH Key shared secret */ +typedef struct +{ + uint8_t secret[SEC_ECC_KEY_LEN]; /*! DH Key Shared secret */ +} secEccSharedSec_t; + + +/*! ECC Security callback parameters structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! header */ + union + { + secEccSharedSec_t sharedSecret; /*! shared secret */ + secEccKey_t key; /*! ecc public/private key pair */ + } data; +} secEccMsg_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SecInit + * + * \brief Initialize the security service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecRandInit + * + * \brief Initialize the random number service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRandInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAesInit + * + * \brief Initialize the AES service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecAesInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecCmacInit + * + * \brief Called to initialize CMAC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecCmacInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecEccInit + * + * \brief Called to initialize ECC security. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void SecEccInit(void); + +/*************************************************************************************************/ +/*! + * \fn SecAes + * + * \brief Execute an AES calculation. When the calculation completes, a WSF message will be + * sent to the specified handler. This function returns a token value that + * the client can use to match calls to this function with messages. + * + * \param pKey Pointer to 16 byte key. + * \param pPlaintext Pointer to 16 byte plaintext. + * \param handlerId WSF handler ID. + * \param param Client-defined parameter returned in message. + * \param event Event for client's WSF handler. + * + * \return Token value. + */ +/*************************************************************************************************/ +uint8_t SecAes(uint8_t *pKey, uint8_t *pPlaintext, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecAesCmac + * + * \brief Execute the CMAC algorithm. + * + * \param pKey Key used in CMAC operation. + * \param pPlaintext Data to perform CMAC operation over + * \param len Size of pPlaintext in bytes. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecCmac(const uint8_t *pKey, uint8_t *pPlaintext, uint8_t textLen, wsfHandlerId_t handlerId, + uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenKey + * + * \brief Generate an ECC key. + * + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenKey(wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecEccGenSharedSecret + * + * \brief Generate an ECC key. + * + * \param pKey ECC Key structure. + * \param handlerId WSF handler ID for client. + * \param param Optional parameter sent to client's WSF handler. + * \param event Event for client's WSF handler. + * + * \return TRUE if successful, else FALSE. + */ +/*************************************************************************************************/ +bool_t SecEccGenSharedSecret(secEccKey_t *pKey, wsfHandlerId_t handlerId, uint16_t param, uint8_t event); + +/*************************************************************************************************/ +/*! + * \fn SecRand + * + * \brief This function returns up to 16 bytes of random data to a buffer provided by the + * client. + * + * \param pRand Pointer to returned random data. + * \param randLen Length of random data. + * + * \return None. + */ +/*************************************************************************************************/ +void SecRand(uint8_t *pRand, uint8_t randLen); + +#ifdef __cplusplus +}; +#endif + +#endif /* SEC_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h new file mode 100644 index 00000000000..8cc4bc47aef --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/cfg/cfg_stack.h @@ -0,0 +1,103 @@ +/*************************************************************************************************/ +/*! + * \file cfg_stack.h + * + * \brief Stack configuration. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef CFG_STACK_H +#define CFG_STACK_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + HCI +**************************************************************************************************/ + +/*! Vendor specific targets */ +#define HCI_VS_GENERIC 0 +#define HCI_VS_EMM 1 + +/*! Vendor specific target configuration */ +#ifndef HCI_VS_TARGET +#define HCI_VS_TARGET HCI_VS_GENERIC +#endif + +/* Extra byte allocation required for LL operations (i.e. MIC) in single-chip implementation */ +#ifndef HCI_TX_DATA_TAILROOM +#define HCI_TX_DATA_TAILROOM 0 +#endif + +/************************************************************************************************** + DM +**************************************************************************************************/ + +/*! Maximum number of connections */ +#ifndef DM_CONN_MAX +#define DM_CONN_MAX 3 +#endif + +/*! Number of supported advertising sets: must be set to 1 for legacy advertising */ +#ifndef DM_NUM_ADV_SETS +#define DM_NUM_ADV_SETS 1 +#endif + +/*! Number of scanner and initiator PHYs (LE 1M, LE 2M and LE Coded): must be set to 1 for + legacy scanner and initiator */ +#ifndef DM_NUM_PHYS +#define DM_NUM_PHYS 1 +#endif + +/************************************************************************************************** + L2C +**************************************************************************************************/ + +/*! Maximum number of connection oriented channels */ +#ifndef L2C_COC_CHAN_MAX +#define L2C_COC_CHAN_MAX 8 +#endif + +/*! Maximum number of connection oriented channel registered clients */ +#ifndef L2C_COC_REG_MAX +#define L2C_COC_REG_MAX 4 +#endif + +/************************************************************************************************** + ATT +**************************************************************************************************/ + +/*! Maximum number of simultanous ATT notifications */ +#ifndef ATT_NUM_SIMUL_NTF +#define ATT_NUM_SIMUL_NTF 1 +#endif + +/************************************************************************************************** + SMP +**************************************************************************************************/ + + +#ifdef __cplusplus +}; +#endif + +#endif /* CFG_STACK_H */ 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 new file mode 100644 index 00000000000..ba81dd509da --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h @@ -0,0 +1,1111 @@ +/*************************************************************************************************/ +/*! + * \file att_api.h + * + * \brief Attribute protocol client and server API. + * + * $Date: 2017-03-03 17:46:38 -0600 (Fri, 03 Mar 2017) $ + * $Revision: 11375 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_API_H +#define ATT_API_H + +#include "wsf_timer.h" +#include "att_defs.h" +#include "att_uuid.h" +#include "dm_api.h" +#include "cfg_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! ATT server attribute settings */ +#define ATTS_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTS_SET_WRITE_CBACK 0x02 /*! Set if the group callback is executed when + this attribute is written by a client device */ +#define ATTS_SET_READ_CBACK 0x04 /*! Set if the group callback is executed when + this attribute is read by a client device */ +#define ATTS_SET_VARIABLE_LEN 0x08 /*! Set if the attribute has a variable length */ +#define ATTS_SET_ALLOW_OFFSET 0x10 /*! Set if writes are allowed with an offset */ +#define ATTS_SET_CCC 0x20 /*! Set if the attribute is a client characteristic + configuration descriptor */ +#define ATTS_SET_ALLOW_SIGNED 0x40 /*! Set if signed writes are allowed */ +#define ATTS_SET_REQ_SIGNED 0x80 /*! Set if signed writes are required if link + is not encrypted */ + +/*! ATT server attribute permissions */ +#define ATTS_PERMIT_READ 0x01 /*! Set if attribute can be read */ +#define ATTS_PERMIT_READ_AUTH 0x02 /*! Set if attribute read requires authentication */ +#define ATTS_PERMIT_READ_AUTHORIZ 0x04 /*! Set if attribute read requires authorization */ +#define ATTS_PERMIT_READ_ENC 0x08 /*! Set if attribute read requires encryption */ +#define ATTS_PERMIT_WRITE 0x10 /*! Set if attribute can be written */ +#define ATTS_PERMIT_WRITE_AUTH 0x20 /*! Set if attribute write requires authentication */ +#define ATTS_PERMIT_WRITE_AUTHORIZ 0x40 /*! Set if attribute write requires authorization */ +#define ATTS_PERMIT_WRITE_ENC 0x80 /*! Set if attribute write requires encryption */ + +/*! ATT client characteristic discovery and configuration settings */ +#define ATTC_SET_UUID_128 0x01 /*! Set if the UUID is 128 bits in length */ +#define ATTC_SET_REQUIRED 0x02 /*! Set if characteristic must be discovered */ +#define ATTC_SET_DESCRIPTOR 0x04 /*! Set if this is a characteristic descriptor */ + +/*! ATT callback events */ +#define ATT_CBACK_START 0x02 /*! ATT callback event starting value */ +enum /*! Internal note: event values match method values */ +{ + /*! ATT client callback events */ + ATTC_FIND_INFO_RSP = ATT_CBACK_START, /*! Find information response */ + ATTC_FIND_BY_TYPE_VALUE_RSP, /*! Find by type value response */ + ATTC_READ_BY_TYPE_RSP, /*! Read by type value response */ + ATTC_READ_RSP, /*! Read response */ + ATTC_READ_LONG_RSP, /*! Read long response */ + ATTC_READ_MULTIPLE_RSP, /*! Read multiple response */ + ATTC_READ_BY_GROUP_TYPE_RSP, /*! Read group type response */ + ATTC_WRITE_RSP, /*! Write response */ + ATTC_WRITE_CMD_RSP, /*! Write command response */ + ATTC_PREPARE_WRITE_RSP, /*! Prepare write response */ + ATTC_EXECUTE_WRITE_RSP, /*! Execute write response */ + ATTC_HANDLE_VALUE_NTF, /*! Handle value notification */ + ATTC_HANDLE_VALUE_IND, /*! Handle value indication */ + /*! ATT server callback events */ + ATTS_HANDLE_VALUE_CNF, /*! Handle value confirmation */ + ATTS_CCC_STATE_IND, /*! Client chracteristic configuration state change */ + /*! ATT common callback events */ + ATT_MTU_UPDATE_IND /*! Negotiated MTU value */ +}; + +/*! ATT callback events */ +#define ATT_CBACK_END ATT_MTU_UPDATE_IND /*! ATT callback event ending value */ + +/*! Base value for HCI error status values passed through ATT */ +#define ATT_HCI_ERR_BASE 0x20 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + wsfTimerTicks_t discIdleTimeout; /*! ATT server service discovery connection idle timeout in seconds */ + uint16_t mtu; /*! desired ATT MTU */ + uint8_t transTimeout; /*! transcation timeout in seconds */ + uint8_t numPrepWrites; /*! number of queued prepare writes supported by server */ +} attCfg_t; + +/*! + * Attribute server data types + */ + +/*! Attribute structure */ +typedef struct +{ + uint8_t const *pUuid; /*! Pointer to the attribute's UUID */ + uint8_t *pValue; /*! Pointer to the attribute's value */ + uint16_t *pLen; /*! Pointer to the length of the attribute's value */ + uint16_t maxLen; /*! Maximum length of attribute's value */ + uint8_t settings; /*! Attribute settings */ + uint8_t permissions; /*! Attribute permissions */ +} attsAttr_t; + +/*! Attribute group read callback */ +typedef uint8_t (*attsReadCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, attsAttr_t *pAttr); + +/*! Attribute group write callback */ +typedef uint8_t (*attsWriteCback_t)(dmConnId_t connId, uint16_t handle, uint8_t operation, + uint16_t offset, uint16_t len, uint8_t *pValue, + attsAttr_t *pAttr); + +/*! Attribute group */ +typedef struct attsGroup_tag +{ + struct attsGroup_tag *pNext; /*! For internal use only */ + attsAttr_t *pAttr; /*! Pointer to attribute list for this group */ + attsReadCback_t readCback; /*! Read callback function */ + attsWriteCback_t writeCback; /*! Write callback function */ + uint16_t startHandle; /*! The handle of the first attribute in this group */ + uint16_t endHandle; /*! The handle of the last attribute in this group */ +} attsGroup_t; + +/*! Client characteristc configuration settings */ +typedef struct +{ + uint16_t handle; /*! Client characteristc configuration descriptor handle */ + uint16_t valueRange; /*! Acceptable value range of the descriptor value */ + uint8_t secLevel; /*! Security level of characteristic value */ +} attsCccSet_t; + +/*! ATT client structure for characteristic and descriptor discovery */ +typedef struct attcDiscChar_tag +{ + uint8_t const *pUuid; /*! Pointer to UUID */ + uint8_t settings; /*! Characteristic discovery settings */ +} attcDiscChar_t; + +/*! ATT client structure for characteristic and descriptor configuration */ +typedef struct +{ + uint8_t const *pValue; /*! Pointer to default value or NULL */ + uint8_t valueLen; /*! Default value length */ + uint8_t hdlIdx; /*! Index of its handle in handle list */ +} attcDiscCfg_t; + +/*! ATT client discovery control block */ +typedef struct +{ + attcDiscChar_t **pCharList; /*! Characterisic list for discovery */ + uint16_t *pHdlList; /*! Characteristic handle list */ + attcDiscCfg_t *pCfgList; /*! Characterisic list for configuration */ + uint8_t charListLen; /*! Characteristic and handle list length */ + uint8_t cfgListLen; /*! Configuration list length */ + + /* the following are for internal use only */ + uint16_t svcStartHdl; + uint16_t svcEndHdl; + uint8_t charListIdx; + uint8_t endHdlIdx; +} attcDiscCb_t; + +/*! + * ATT callback parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status: ATT_SUCCESS or error status + * \param pValue Pointer to value data, valid if valueLen > 0 + * \param valueLen Length of value data + * \param handle Attribute handle + * \param continuing TRUE if more response packets expected + * \param mtu Negotiated MTU value + */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint8_t *pValue; /*! Value */ + uint16_t valueLen; /*! Value length */ + uint16_t handle; /*! Attribute handle */ + bool_t continuing; /*! TRUE if more response packets expected */ + uint16_t mtu; /*! Negotiated MTU value */ +} attEvt_t; + +/*! ATTS client characteristic configuration callback structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t handle; /*! CCCD handle */ + uint16_t value; /*! CCCD value */ + uint8_t idx; /*! CCCD settings index */ +} attsCccEvt_t; + +/*! ATT callback type */ +typedef void (*attCback_t)(attEvt_t *pEvt); + +/*! ATTS authorization callback type */ +typedef uint8_t (*attsAuthorCback_t)(dmConnId_t connId, uint8_t permit, uint16_t handle); + +/*! ATTS client characteristic configuration callback */ +typedef void (*attsCccCback_t)(attsCccEvt_t *pEvt); + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Configuration pointer */ +extern attCfg_t *pAttCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttRegister + * + * \brief Register a callback with ATT. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttRegister(attCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttConnRegister + * + * \brief Register a connection callback with ATT. The callback is typically used to + * manage the attribute server database. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttConnRegister(dmCback_t cback); + + +/*************************************************************************************************/ +/*! + * \fn AttGetMtu + * + * \brief Get the attribute protocol MTU of a connection. + * + * \param connId DM connection ID. + * + * \return MTU of the connection. + */ +/*************************************************************************************************/ +uint16_t AttGetMtu(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsInit + * + * \brief Initialize ATT server. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsIndInit + * + * \brief Initialize ATT server for indications/notifications. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsIndInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsSignInit + * + * \brief Initialize ATT server for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsAuthorRegister + * + * \brief Register an authorization callback with the attribute server. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAuthorRegister(attsAuthorCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsAddGroup + * + * \brief Add an attribute group to the attribute server. + * + * \param pGroup Pointer to an attribute group structure. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsAddGroup(attsGroup_t *pGroup); + +/*************************************************************************************************/ +/*! + * \fn AttsRemoveGroup + * + * \brief Remove an attribute group from the attribute server. + * + * \param startHandle Start handle of attribute group to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsRemoveGroup(uint16_t startHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsSetAttr + * + * \brief Set an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param valueLen Attribute length. + * \param pValue Attribute value. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttsSetAttr(uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsGetAttr + * + * \brief Get an attribute value in the attribute server. + * + * \param handle Attribute handle. + * \param pLen Returned attribute length pointer. + * \param pValue Returned attribute value pointer. + * + * \return ATT_SUCCESS if successful otherwise error. + * \return This function returns the attribute length in pLen and a pointer to the attribute + * value in pValue. + */ +/*************************************************************************************************/ +uint8_t AttsGetAttr(uint16_t handle, uint16_t *pLen, uint8_t **pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueInd + * + * \brief Send an attribute protocol Handle Value Indication. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueInd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtf + * + * \brief Send an attribute protocol Handle Value Notification. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtf(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueIndZeroCpy + * + * \brief Send an attribute protocol Handle Value Indication without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueIndZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsHandleValueNtfZeroCpy + * + * \brief Send an attribute protocol Handle Value Notification without copying the attribute + * value data. + * + * Note: attribute value buffer 'pValue' must be allocated with AttMsgAlloc(). + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsHandleValueNtfZeroCpy(dmConnId_t connId, uint16_t handle, uint16_t valueLen, + uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttsCccRegister + * + * \brief Register the utility service for managing client characteristic + * configuration descriptors. This function is typically called once on + * system initialization. + * + * \param setLen Length of settings array. + * \param pSet Array of CCC descriptor settings. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccRegister(uint8_t setLen, attsCccSet_t *pSet, attsCccCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn AttsCccInitTable + * + * \brief Initialize the client characteristic configuration descriptor value table for a + * connection. The table is initialized with the values from pCccTbl. If pCccTbl + * is NULL the table will be initialized to zero. + * + * This function must be called when a connection is established or when a + * device is bonded. + * + * \param connId DM connection ID. + * \param pCccTbl Pointer to the descriptor value array. The length of the array + * must equal the value of setLen passed to AttsCccRegister(). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccInitTable(dmConnId_t connId, uint16_t *pCccTbl); + +/*************************************************************************************************/ +/*! + * \fn AttsCccClearTable + * + * \brief Clear and deallocate the client characteristic configuration descriptor value + * table for a connection. This function must be called when a connection is closed. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccClearTable(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttsCccGet + * + * \brief Get the value of a client characteristic configuration descriptor by its index. + * If not found, return zero. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor. + */ +/*************************************************************************************************/ +uint16_t AttsCccGet(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsCccSet + * + * \brief Set the value of a client characteristic configuration descriptor by its index. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * \param value Value of the descriptor. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsCccSet(dmConnId_t connId, uint8_t idx, uint16_t value); + +/*************************************************************************************************/ +/*! + * \fn AttsCccEnabled + * + * \brief Check if a client characteristic configuration descriptor is enabled and if + * the characteristic's security level has been met. + * + * \param connId DM connection ID. + * \param idx Index of descriptor in CCC descriptor handle table. + * + * \return Value of the descriptor if security level is met, otherwise zero. + */ +/*************************************************************************************************/ +uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); + +/*************************************************************************************************/ +/*! + * \fn AttsSetCsrk + * + * \brief Set the peer's data signing key on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. The caller is responsible for maintaining the memory that + * contains the key. + * + * \param connId DM connection ID. + * \param pCsrk Pointer to data signing key (CSRK). + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn AttsSetSignCounter + * + * \brief Set the peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * established. ATT maintains the value of the sign counter internally and + * sets the value when a signed packet is successfully received. + * + * \param connId DM connection ID. + * \param signCounter Sign counter. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsSetSignCounter(dmConnId_t connId, uint32_t signCounter); + +/*************************************************************************************************/ +/*! + * \fn AttsGetSignCounter + * + * \brief Get the current value peer's sign counter on this connection. This function + * is typically called from the ATT connection callback when the connection is + * closed so the application can store the sign counter for use on future + * connections. + * + * \param connId DM connection ID. + * + * \return Sign counter. + */ +/*************************************************************************************************/ +uint32_t AttsGetSignCounter(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcInit + * + * \brief Initialize ATT client. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcSignInit + * + * \brief Initialize ATT client for data signing. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttcFindInfoReq + * + * \brief Initiate an attribute protocol Find Information Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindInfoReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcFindByTypeValueReq + * + * \brief Initiate an attribute protocol Find By Type Value Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuid16 16-bit UUID to find. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcFindByTypeValueReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint16_t uuid16, uint16_t valueLen, uint8_t *pValue, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByTypeReq + * + * \brief Initiate an attribute protocol Read By Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadReq + * + * \brief Initiate an attribute protocol Read Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadReq(dmConnId_t connId, uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn AttcReadLongReq + * + * \brief Initiate an attribute protocol Read Long Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Read attribute data starting at this offset. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadLongReq(dmConnId_t connId, uint16_t handle, uint16_t offset, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcReadMultipleReq + * + * \brief Initiate an attribute protocol Read Multiple Request. + * + * \param connId DM connection ID. + * \param numHandles Number of handles in attribute handle list. + * \param pHandles List of attribute handles. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadMultipleReq(dmConnId_t connId, uint8_t numHandles, uint16_t *pHandles); + +/*************************************************************************************************/ +/*! + * \fn AttcReadByGroupTypeReq + * + * \brief Initiate an attribute protocol Read By Group Type Request. + * + * \param connId DM connection ID. + * \param startHandle Attribute start handle. + * \param endHandle Attribute end handle. + * \param uuidLen Length of UUID (2 or 16). + * \param pUuid Pointer to UUID data. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcReadByGroupTypeReq(dmConnId_t connId, uint16_t startHandle, uint16_t endHandle, + uint8_t uuidLen, uint8_t *pUuid, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteReq + * + * \brief Initiate an attribute protocol Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteReq(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcWriteCmd + * + * \brief Initiate an attribute protocol Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcWriteCmd(dmConnId_t connId, uint16_t handle, uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcSignedWriteCmd + * + * \brief Initiate an attribute protocol signed Write Command. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param signCounter Value of the sign counter. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcSignedWriteCmd(dmConnId_t connId, uint16_t handle, uint32_t signCounter, + uint16_t valueLen, uint8_t *pValue); + +/*************************************************************************************************/ +/*! + * \fn AttcPrepareWriteReq + * + * \brief Initiate an attribute protocol Prepare Write Request. + * + * \param connId DM connection ID. + * \param handle Attribute handle. + * \param offset Write attribute data starting at this offset. + * \param valueLen Length of value data. + * \param pValue Pointer to value data. + * \param valueByRef TRUE if pValue data is accessed by reference rather than copied. + * \param continuing TRUE if ATTC continues sending requests until complete. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcPrepareWriteReq(dmConnId_t connId, uint16_t handle, uint16_t offset, uint16_t valueLen, + uint8_t *pValue, bool_t valueByRef, bool_t continuing); + +/*************************************************************************************************/ +/*! + * \fn AttcExecuteWriteReq + * + * \brief Initiate an attribute protocol Execute Write Request. + * + * \param connId DM connection ID. + * \param writeAll TRUE to write all queued writes, FALSE to cancel all queued writes. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcExecuteWriteReq(dmConnId_t connId, bool_t writeAll); + +/*************************************************************************************************/ +/*! + * \fn AttcCancelReq + * + * \brief Cancel an attribute protocol request in progress. + * + * \param connId DM connection ID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcCancelReq(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscService + * + * \brief This utility function discovers the given service on a peer device. Function + * AttcFindByTypeValueReq() is called to initiate the discovery procedure. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * \param uuidLen Length of service UUID (2 or 16). + * \param pUuid Pointer to service UUID. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscService(dmConnId_t connId, attcDiscCb_t *pCb, uint8_t uuidLen, uint8_t *pUuid); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscServiceCmpl + * + * \brief This utility function processes a service discovery result. It should be called + * when an ATTC_FIND_BY_TYPE_VALUE_RSP callback event is received after service + * discovery is initiated by calling AttcDiscService(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_SUCCESS if successful otherwise error. + */ +/*************************************************************************************************/ +uint8_t AttcDiscServiceCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharStart + * + * \brief This utility function starts characteristic and characteristic descriptor + * discovery for a service on a peer device. The service must have been previously + * discovered by calling AttcDiscService() and AttcDiscServiceCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcDiscCharStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscCharCmpl + * + * \brief This utility function processes a characteristic discovery result. It should be + * called when an ATTC_READ_BY_TYPE_RSP or ATTC_FIND_INFO_RSP callback event is + * received after characteristic discovery is initiated by calling AttcDiscCharStart(). + * + * \param pCb Pointer to discovery control block. + * \param pMsg ATT callback event message. + * + * \return ATT_CONTINUING if successful and the discovery procedure is continuing. + * ATT_SUCCESS if the discovery procedure completed successfully. + * Otherwise the discovery procedure failed. + */ +/*************************************************************************************************/ +uint8_t AttcDiscCharCmpl(attcDiscCb_t *pCb, attEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigStart + * + * \brief This utility function starts characteristic configuration for characteristics on a + * peer device. The characteristics must have been previously discovered by calling + * AttcDiscCharStart() and AttcDiscCharCmpl(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if nothing to configure. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigStart(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigCmpl + * + * \brief This utility function initiates the next characteristic configuration procedure. + * It should be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * after characteristic configuration is initiated by calling AttcDiscConfigStart(). + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigCmpl(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcDiscConfigResume + * + * \brief This utility function resumes the characteristic configuration procedure. It can + * be called when an ATTC_READ_RSP or ATTC_WRITE_RSP callback event is received + * with failure status to attempt the read or write procedure again. + * + * \param connId DM connection ID. + * \param pCb Pointer to discovery control block. + * + * \return ATT_CONTINUING if successful and configuration procedure is continuing. + * ATT_SUCCESS if configuration procedure completed successfully. + */ +/*************************************************************************************************/ +uint8_t AttcDiscConfigResume(dmConnId_t connId, attcDiscCb_t *pCb); + +/*************************************************************************************************/ +/*! + * \fn AttcMtuReq + * + * \brief For internal use only. + * + * \param connId DM connection ID. + * \param mtu Attribute protocol MTU. + * + * \return None. + */ +/*************************************************************************************************/ +void AttcMtuReq(dmConnId_t connId, uint16_t mtu); + +/*************************************************************************************************/ +/*! + * \fn AttsErrorTest + * + * \brief For testing purposes only. + * + * \param status ATT status + * + * \return None. + */ +/*************************************************************************************************/ +void AttsErrorTest(uint8_t status); + +/*************************************************************************************************/ +/*! + * \fn AttMsgAlloc + * + * \brief Allocate an ATT message buffer to be sent with the ATT attribute protocol + * zero-copy APIs. + * + * \param len Message length in bytes. + * \param opcode Opcode for ATT message. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *AttMsgAlloc(uint16_t len, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttMsgFree + * + * \brief Free an ATT message buffer allocated with AttMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * \param opcode Opcode for ATT message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttMsgFree(void *pMsg, uint8_t opcode); + +/*************************************************************************************************/ +/*! + * \fn AttsDynInit + * + * \brief Initialize the Dynamic ATT Service subsystem. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynInit(void); + +/*************************************************************************************************/ +/*! + * \fn AttsDynCreateGroup + * + * \brief Dynamically create an ATT Service at runtime. + * + * \param startHandle Starting attribute handle in the service + * \param endHandle Last attribute handle in the service + * + * \return Service Handle. + */ +/*************************************************************************************************/ +void *AttsDynCreateGroup(uint16_t startHandle, uint16_t endHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynDeleteGroup + * + * \brief Dynamically delete an ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynDeleteGroup(void *pSvcHandle); + +/*************************************************************************************************/ +/*! + * \fn AttsDynRegister + * + * \brief Register callback functions for a dynamic ATT Service at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynRegister(void *pSvcHandle, attsReadCback_t readCback, attsWriteCback_t writeCback); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttr + * + * \brief Dynamically add an attribute to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Initial value of attribute (copied into attribute memory) + * \param len Length of pValue in bytes + * \param maxLen Maximum length of the attribute in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttr(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, uint16_t len, + const uint16_t maxLen, uint8_t settings, uint8_t permissions); + +/*************************************************************************************************/ +/*! + * \fn AttsDynAddAttrConst + * + * \brief Dynamically add an attribute with a constant value to a dynamic ATT Services at runtime. + * + * \param pSvcHandle Service handle returned by AttsDynCreateGroup + * \param pUuid Constant UUID + * \param pValue Pointer to constant attribute memory + * \param len Length of pValue in bytes + * \param settings Attribute settings + * \param permissions Attribute permissions + * + * \return None. + */ +/*************************************************************************************************/ +void AttsDynAddAttrConst(void *pSvcHandle, const uint8_t *pUuid, const uint8_t *pValue, + const uint16_t len, uint8_t settings, uint8_t permissions); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h new file mode 100644 index 00000000000..cbb5250c17c --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_defs.h @@ -0,0 +1,225 @@ +/*************************************************************************************************/ +/*! + * \file att_defs.h + * + * \brief Attribute protocol constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_DEFS_H +#define ATT_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Attribute PDU format */ +#define ATT_HDR_LEN 1 /*! Attribute PDU header length */ +#define ATT_AUTH_SIG_LEN 12 /*! Authentication signature length */ +#define ATT_DEFAULT_MTU 23 /*! Default value of ATT_MTU */ +#define ATT_MAX_MTU 517 /*! Maximum value of ATT_MTU */ +#define ATT_DEFAULT_PAYLOAD_LEN 20 /*! Default maximum payload length for most PDUs */ + +/*! Attribute value parameters */ +#define ATT_VALUE_MAX_LEN 512 /*! Maximum attribute value length */ +#define ATT_VALUE_MAX_OFFSET 511 /*! Maximum attribute value offset */ + +/*! Transaction timeout */ +#define ATT_MAX_TRANS_TIMEOUT 30 /*! Maximum transaction timeout in seconds */ + +/*! Error codes */ +#define ATT_SUCCESS 0x00 /*! Operation successful */ +#define ATT_ERR_HANDLE 0x01 /*! Invalid handle */ +#define ATT_ERR_READ 0x02 /*! Read not permitted */ +#define ATT_ERR_WRITE 0x03 /*! Write not permitted */ +#define ATT_ERR_INVALID_PDU 0x04 /*! Invalid pdu */ +#define ATT_ERR_AUTH 0x05 /*! Insufficient authentication */ +#define ATT_ERR_NOT_SUP 0x06 /*! Request not supported */ +#define ATT_ERR_OFFSET 0x07 /*! Invalid offset */ +#define ATT_ERR_AUTHOR 0x08 /*! Insufficient authorization */ +#define ATT_ERR_QUEUE_FULL 0x09 /*! Prepare queue full */ +#define ATT_ERR_NOT_FOUND 0x0A /*! Attribute not found */ +#define ATT_ERR_NOT_LONG 0x0B /*! Attribute not long */ +#define ATT_ERR_KEY_SIZE 0x0C /*! Insufficient encryption key size */ +#define ATT_ERR_LENGTH 0x0D /*! Invalid attribute value length */ +#define ATT_ERR_UNLIKELY 0x0E /*! Other unlikely error */ +#define ATT_ERR_ENC 0x0F /*! Insufficient encryption */ +#define ATT_ERR_GROUP_TYPE 0x10 /*! Unsupported group type */ +#define ATT_ERR_RESOURCES 0x11 /*! Insufficient resources */ +#define ATT_ERR_CCCD 0xFD /*! CCCD improperly configured */ +#define ATT_ERR_IN_PROGRESS 0xFE /*! Procedure already in progress */ +#define ATT_ERR_RANGE 0xFF /*! Value out of range */ + +/*! Proprietary internal error codes */ +#define ATT_ERR_MEMORY 0x70 /*! Out of memory */ +#define ATT_ERR_TIMEOUT 0x71 /*! Transaction timeout */ +#define ATT_ERR_OVERFLOW 0x72 /*! Transaction overflow */ +#define ATT_ERR_INVALID_RSP 0x73 /*! Invalid response PDU */ +#define ATT_ERR_CANCELLED 0x74 /*! Request cancelled */ +#define ATT_ERR_UNDEFINED 0x75 /*! Other undefined error */ +#define ATT_ERR_REQ_NOT_FOUND 0x76 /*! Required characteristic not found */ +#define ATT_ERR_MTU_EXCEEDED 0x77 /*! Attribute PDU length exceeded MTU size */ +#define ATT_CONTINUING 0x78 /*! Procedure continuing */ + +/*! Application error codes */ +#define ATT_ERR_VALUE_RANGE 0x80 /*! Value out of range */ + +/*! PDU types */ +#define ATT_PDU_ERR_RSP 0x01 /*! Error response */ +#define ATT_PDU_MTU_REQ 0x02 /*! Exchange mtu request */ +#define ATT_PDU_MTU_RSP 0x03 /*! Exchange mtu response */ +#define ATT_PDU_FIND_INFO_REQ 0x04 /*! Find information request */ +#define ATT_PDU_FIND_INFO_RSP 0x05 /*! Find information response */ +#define ATT_PDU_FIND_TYPE_REQ 0x06 /*! Find by type value request */ +#define ATT_PDU_FIND_TYPE_RSP 0x07 /*! Find by type value response */ +#define ATT_PDU_READ_TYPE_REQ 0x08 /*! Read by type request */ +#define ATT_PDU_READ_TYPE_RSP 0x09 /*! Read by type response */ +#define ATT_PDU_READ_REQ 0x0A /*! Read request */ +#define ATT_PDU_READ_RSP 0x0B /*! Read response */ +#define ATT_PDU_READ_BLOB_REQ 0x0C /*! Read blob request */ +#define ATT_PDU_READ_BLOB_RSP 0x0D /*! Read blob response */ +#define ATT_PDU_READ_MULT_REQ 0x0E /*! Read multiple request */ +#define ATT_PDU_READ_MULT_RSP 0x0F /*! Read multiple response */ +#define ATT_PDU_READ_GROUP_TYPE_REQ 0x10 /*! Read by group type request */ +#define ATT_PDU_READ_GROUP_TYPE_RSP 0x11 /*! Read by group type response */ +#define ATT_PDU_WRITE_REQ 0x12 /*! Write request */ +#define ATT_PDU_WRITE_RSP 0x13 /*! Write response */ +#define ATT_PDU_WRITE_CMD 0x52 /*! Write command */ +#define ATT_PDU_SIGNED_WRITE_CMD 0xD2 /*! Signed write command */ +#define ATT_PDU_PREP_WRITE_REQ 0x16 /*! Prepare write request */ +#define ATT_PDU_PREP_WRITE_RSP 0x17 /*! Prepare write response */ +#define ATT_PDU_EXEC_WRITE_REQ 0x18 /*! Execute write request */ +#define ATT_PDU_EXEC_WRITE_RSP 0x19 /*! Execute write response */ +#define ATT_PDU_VALUE_NTF 0x1B /*! Handle value notification */ +#define ATT_PDU_VALUE_IND 0x1D /*! Handle value indication */ +#define ATT_PDU_VALUE_CNF 0x1E /*! Handle value confirmation */ +#define ATT_PDU_MAX 0x1F /*! PDU Maximum */ + +/*! Length of PDU fixed length fields */ +#define ATT_ERR_RSP_LEN 5 +#define ATT_MTU_REQ_LEN 3 +#define ATT_MTU_RSP_LEN 3 +#define ATT_FIND_INFO_REQ_LEN 5 +#define ATT_FIND_INFO_RSP_LEN 2 +#define ATT_FIND_TYPE_REQ_LEN 7 +#define ATT_FIND_TYPE_RSP_LEN 1 +#define ATT_READ_TYPE_REQ_LEN 5 +#define ATT_READ_TYPE_RSP_LEN 2 +#define ATT_READ_REQ_LEN 3 +#define ATT_READ_RSP_LEN 1 +#define ATT_READ_BLOB_REQ_LEN 5 +#define ATT_READ_BLOB_RSP_LEN 1 +#define ATT_READ_MULT_REQ_LEN 1 +#define ATT_READ_MULT_RSP_LEN 1 +#define ATT_READ_GROUP_TYPE_REQ_LEN 5 +#define ATT_READ_GROUP_TYPE_RSP_LEN 2 +#define ATT_WRITE_REQ_LEN 3 +#define ATT_WRITE_RSP_LEN 1 +#define ATT_WRITE_CMD_LEN 3 +#define ATT_SIGNED_WRITE_CMD_LEN (ATT_WRITE_CMD_LEN + ATT_AUTH_SIG_LEN) +#define ATT_PREP_WRITE_REQ_LEN 5 +#define ATT_PREP_WRITE_RSP_LEN 5 +#define ATT_EXEC_WRITE_REQ_LEN 2 +#define ATT_EXEC_WRITE_RSP_LEN 1 +#define ATT_VALUE_NTF_LEN 3 +#define ATT_VALUE_IND_LEN 3 +#define ATT_VALUE_CNF_LEN 1 + +/*! Find information response format */ +#define ATT_FIND_HANDLE_16_UUID 0x01 /*! Handle and 16 bit UUID */ +#define ATT_FIND_HANDLE_128_UUID 0x02 /*! Handle and 128 bit UUID */ + +/*! Execute write request flags */ +#define ATT_EXEC_WRITE_CANCEL 0x00 /*! Cancel all prepared writes */ +#define ATT_EXEC_WRITE_ALL 0x01 /*! Write all pending prepared writes */ + +/*! PDU masks */ +#define ATT_PDU_MASK_SERVER 0x01 /*! Server bit mask */ +#define ATT_PDU_MASK_COMMAND 0x40 /*! Command bit mask */ +#define ATT_PDU_MASK_SIGNED 0x80 /*! Auth signature bit mask */ + +/*! Handles */ +#define ATT_HANDLE_NONE 0x0000 +#define ATT_HANDLE_START 0x0001 +#define ATT_HANDLE_MAX 0xFFFF + +/*! UUID lengths */ +#define ATT_NO_UUID_LEN 0 /*! Length when no UUID is present ;-) */ +#define ATT_16_UUID_LEN 2 /*! Length in bytes of a 16 bit UUID */ +#define ATT_128_UUID_LEN 16 /*! Length in bytes of a 128 bit UUID */ + +/*! GATT characteristic properties */ +#define ATT_PROP_BROADCAST 0x01 /*! Permit broadcasts */ +#define ATT_PROP_READ 0x02 /*! Permit reads */ +#define ATT_PROP_WRITE_NO_RSP 0x04 /*! Permit writes without response */ +#define ATT_PROP_WRITE 0x08 /*! Permit writes with response */ +#define ATT_PROP_NOTIFY 0x10 /*! Permit notifications */ +#define ATT_PROP_INDICATE 0x20 /*! Permit indications */ +#define ATT_PROP_AUTHENTICATED 0x40 /*! Permit signed writes */ +#define ATT_PROP_EXTENDED 0x80 /*! More properties defined in extended properties */ + +/*! GATT characteristic extended properties */ +#define ATT_EXT_PROP_RELIABLE_WRITE 0x0001 /*! Permit reliable writes */ +#define ATT_EXT_PROP_WRITEABLE_AUX 0x0002 /*! Permit write to characteristic descriptor */ + +/*! GATT client characteristic configuration */ +#define ATT_CLIENT_CFG_NOTIFY 0x0001 /*! Notify the value */ +#define ATT_CLIENT_CFG_INDICATE 0x0002 /*! Indicate the value */ + +/*! GATT server characteristic configuration */ +#define ATT_SERVER_CFG_BROADCAST 0x0001 /*! Broadcast the value */ + +/*! GATT characteristic format */ +#define ATT_FORMAT_BOOLEAN 0x01 /*! Boolean */ +#define ATT_FORMAT_2BIT 0x02 /*! Unsigned 2 bit integer */ +#define ATT_FORMAT_NIBBLE 0x03 /*! Unsigned 4 bit integer */ +#define ATT_FORMAT_UINT8 0x04 /*! Unsigned 8 bit integer */ +#define ATT_FORMAT_UINT12 0x05 /*! Unsigned 12 bit integer */ +#define ATT_FORMAT_UINT16 0x06 /*! Unsigned 16 bit integer */ +#define ATT_FORMAT_UINT24 0x07 /*! Unsigned 24 bit integer */ +#define ATT_FORMAT_UINT32 0x08 /*! Unsigned 32 bit integer */ +#define ATT_FORMAT_UINT48 0x09 /*! Unsigned 48 bit integer */ +#define ATT_FORMAT_UINT64 0x0A /*! Unsigned 64 bit integer */ +#define ATT_FORMAT_UINT128 0x0B /*! Unsigned 128 bit integer */ +#define ATT_FORMAT_SINT8 0x0C /*! Signed 8 bit integer */ +#define ATT_FORMAT_SINT12 0x0D /*! Signed 12 bit integer */ +#define ATT_FORMAT_SINT16 0x0E /*! Signed 16 bit integer */ +#define ATT_FORMAT_SINT24 0x0F /*! Signed 24 bit integer */ +#define ATT_FORMAT_SINT32 0x10 /*! Signed 32 bit integer */ +#define ATT_FORMAT_SINT48 0x11 /*! Signed 48 bit integer */ +#define ATT_FORMAT_SINT64 0x12 /*! Signed 64 bit integer */ +#define ATT_FORMAT_SINT128 0x13 /*! Signed 128 bit integer */ +#define ATT_FORMAT_FLOAT32 0x14 /*! IEEE-754 32 bit floating point */ +#define ATT_FORMAT_FLOAT64 0x15 /*! IEEE-754 64 bit floating point */ +#define ATT_FORMAT_SFLOAT 0x16 /*! IEEE-11073 16 bit SFLOAT */ +#define ATT_FORMAT_FLOAT 0x17 /*! IEEE-11073 32 bit FLOAT */ +#define ATT_FORMAT_DUINT16 0x18 /*! IEEE-20601 format */ +#define ATT_FORMAT_UTF8 0x19 /*! UTF-8 string */ +#define ATT_FORMAT_UTF16 0x1A /*! UTF-16 string */ +#define ATT_FORMAT_STRUCT 0x1B /*! Opaque structure */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h new file mode 100644 index 00000000000..a88edbf91b6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file att_handler.h + * + * \brief Interface to ATT event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_HANDLER_H +#define ATT_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn AttHandlerInit + * + * \brief ATT handler init function called during system initialization. + * + * \param handlerID WSF handler ID for ATT. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn AttHandler + * + * \brief WSF event handler for ATT. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void AttHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h new file mode 100644 index 00000000000..177a52e0a21 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_uuid.h @@ -0,0 +1,475 @@ +/*************************************************************************************************/ +/*! + * \file att_uuid.h + * + * \brief Attribute protocol UUIDs from the Bluetooth specification. + * + * $Date: 2017-03-08 12:55:18 -0600 (Wed, 08 Mar 2017) $ + * $Revision: 11435 $ + * + * Copyright (c) 2011-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef ATT_UUID_H +#define ATT_UUID_H + +#include "att_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Service UUIDs */ +#define ATT_UUID_GAP_SERVICE 0x1800 /*! Generic Access Profile Service */ +#define ATT_UUID_GATT_SERVICE 0x1801 /*! Generic Attribute Profile Service */ +#define ATT_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /*! Immediate Alert Service */ +#define ATT_UUID_LINK_LOSS_SERVICE 0x1803 /*! Link Loss Service */ +#define ATT_UUID_TX_POWER_SERVICE 0x1804 /*! Tx Power Service */ +#define ATT_UUID_CURRENT_TIME_SERVICE 0x1805 /*! Current Time Service */ +#define ATT_UUID_REF_TIME_UPDATE_SERVICE 0x1806 /*! Reference Time Update Service */ +#define ATT_UUID_DST_CHANGE_SERVICE 0x1807 /*! Next DST Change Service */ +#define ATT_UUID_GLUCOSE_SERVICE 0x1808 /*! Glucose Service */ +#define ATT_UUID_HEALTH_THERM_SERVICE 0x1809 /*! Health Thermometer Service */ +#define ATT_UUID_DEVICE_INFO_SERVICE 0x180A /*! Device Information Service */ +#define ATT_UUID_NETWORK_AVAIL_SERVICE 0x180B /*! Network Availability Service */ +#define ATT_UUID_WATCHDOG_SERVICE 0x180C /*! Watchdog Service */ +#define ATT_UUID_HEART_RATE_SERVICE 0x180D /*! Heart Rate Service */ +#define ATT_UUID_PHONE_ALERT_SERVICE 0x180E /*! Phone Alert Status Service */ +#define ATT_UUID_BATTERY_SERVICE 0x180F /*! Battery Service */ +#define ATT_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /*! Blood Pressure Service */ +#define ATT_UUID_ALERT_NOTIF_SERVICE 0x1811 /*! Alert Notification Service */ +#define ATT_UUID_HID_SERVICE 0x1812 /*! Human Interface Device Service */ +#define ATT_UUID_SCAN_PARAM_SERVICE 0x1813 /*! Scan Parameter Service */ +#define ATT_UUID_RUNNING_SPEED_SERVICE 0x1814 /*! Running Speed Service */ +#define ATT_UUID_CYCLING_SPEED_SERVICE 0x1816 /*! Cycling Speed Service */ +#define ATT_UUID_CYCLING_POWER_SERVICE 0x1818 /*! Cycling Power Service */ +#define ATT_UUID_USER_DATA_SERVICE 0x181C /*! User Data Service */ +#define ATT_UUID_IP_SUPPORT_SERVICE 0x1820 /*! IP Support Service */ +#define ATT_UUID_PULSE_OXIMITER_SERVICE 0x1822 /*! Pulse Oximeter Service */ + +/*! GATT UUIDs */ +#define ATT_UUID_PRIMARY_SERVICE 0x2800 /*! Primary Service */ +#define ATT_UUID_SECONDARY_SERVICE 0x2801 /*! Secondary Service */ +#define ATT_UUID_INCLUDE 0x2802 /*! Include */ +#define ATT_UUID_CHARACTERISTIC 0x2803 /*! Characteristic */ + +/*! Descriptor UUIDs */ +#define ATT_UUID_CHARACTERISTIC_EXT 0x2900 /*! Characteristic Extended Properties */ +#define ATT_UUID_CHAR_USER_DESC 0x2901 /*! Characteristic User Description */ +#define ATT_UUID_CLIENT_CHAR_CONFIG 0x2902 /*! Client Characteristic Configuration */ +#define ATT_UUID_SERVER_CHAR_CONFIG 0x2903 /*! Server Characteristic Configuration */ +#define ATT_UUID_CHAR_PRES_FORMAT 0x2904 /*! Characteristic Presentation Format */ +#define ATT_UUID_AGGREGATE_FORMAT 0x2905 /*! Characteristic Aggregate Format */ +#define ATT_UUID_VALID_RANGE 0x2906 /*! Valid Range */ +#define ATT_UUID_HID_EXT_REPORT_MAPPING 0x2907 /*! HID External Report ID Mapping */ +#define ATT_UUID_HID_REPORT_ID_MAPPING 0x2908 /*! HID Report ID Mapping */ + +/*! Characteristic UUIDs */ +#define ATT_UUID_DEVICE_NAME 0x2A00 /*! Device Name */ +#define ATT_UUID_APPEARANCE 0x2A01 /*! Appearance */ +#define ATT_UUID_PERIPH_PRIVACY_FLAG 0x2A02 /*! Peripheral Privacy Flag */ +#define ATT_UUID_RECONN_ADDR 0x2A03 /*! Reconnection Address */ +#define ATT_UUID_PREF_CONN_PARAM 0x2A04 /*! Peripheral Preferred Connection Parameters */ +#define ATT_UUID_SERVICE_CHANGED 0x2A05 /*! Service Changed */ +#define ATT_UUID_ALERT_LEVEL 0x2A06 /*! Alert Level */ +#define ATT_UUID_TX_POWER_LEVEL 0x2A07 /*! Tx Power Level */ +#define ATT_UUID_DATE_TIME 0x2A08 /*! Date Time */ +#define ATT_UUID_DAY_OF_WEEK 0x2A09 /*! Day of Week */ +#define ATT_UUID_DAY_DATE_TIME 0x2A0A /*! Day Date Time */ +#define ATT_UUID_EXACT_TIME_100 0x2A0B /*! Exact Time 100 */ +#define ATT_UUID_EXACT_TIME_256 0x2A0C /*! Exact Time 256 */ +#define ATT_UUID_DST_OFFSET 0x2A0D /*! DST Offset */ +#define ATT_UUID_TIME_ZONE 0x2A0E /*! Time Zone */ +#define ATT_UUID_LOCAL_TIME_INFO 0x2A0F /*! Local Time Information */ +#define ATT_UUID_SECONDARY_TIME_ZONE 0x2A10 /*! Secondary Time Zone */ +#define ATT_UUID_TIME_WITH_DST 0x2A11 /*! Time with DST */ +#define ATT_UUID_TIME_ACCURACY 0x2A12 /*! Time Accuracy */ +#define ATT_UUID_TIME_SOURCE 0x2A13 /*! Time Source */ +#define ATT_UUID_REFERENCE_TIME_INFO 0x2A14 /*! Reference Time Information */ +#define ATT_UUID_TIME_BROADCAST 0x2A15 /*! Time Broadcast */ +#define ATT_UUID_TIME_UPDATE_CP 0x2A16 /*! Time Update Control Point */ +#define ATT_UUID_TIME_UPDATE_STATE 0x2A17 /*! Time Update State */ +#define ATT_UUID_GLUCOSE_MEAS 0x2A18 /*! Glucose Measurement */ +#define ATT_UUID_BATTERY_LEVEL 0x2A19 /*! Battery Level */ +#define ATT_UUID_BATTERY_POWER_STATE 0x2A1A /*! Battery Power State */ +#define ATT_UUID_BATTERY_LEVEL_STATE 0x2A1B /*! Battery Level State */ +#define ATT_UUID_TEMP_MEAS 0x2A1C /*! Temperature Measurement */ +#define ATT_UUID_TEMP_TYPE 0x2A1D /*! Temperature Type */ +#define ATT_UUID_INTERMEDIATE_TEMP 0x2A1E /*! Intermediate Temperature */ +#define ATT_UUID_TEMP_C 0x2A1F /*! Temperature Celsius */ +#define ATT_UUID_TEMP_F 0x2A20 /*! Temperature Fahrenheit */ +#define ATT_UUID_MEAS_INTERVAL 0x2A21 /*! Measurement Interval */ +#define ATT_UUID_HID_BOOT_KEYBOARD_IN 0x2A22 /*! HID Boot Keyboard In */ +#define ATT_UUID_SYSTEM_ID 0x2A23 /*! System ID */ +#define ATT_UUID_MODEL_NUMBER 0x2A24 /*! Model Number String */ +#define ATT_UUID_SERIAL_NUMBER 0x2A25 /*! Serial Number String */ +#define ATT_UUID_FIRMWARE_REV 0x2A26 /*! Firmware Revision String */ +#define ATT_UUID_HARDWARE_REV 0x2A27 /*! Hardware Revision String */ +#define ATT_UUID_SOFTWARE_REV 0x2A28 /*! Software Revision String */ +#define ATT_UUID_MANUFACTURER_NAME 0x2A29 /*! Manufacturer Name String */ +#define ATT_UUID_11073_CERT_DATA 0x2A2A /*! IEEE 11073-20601 Regulatory Certification Data List */ +#define ATT_UUID_CURRENT_TIME 0x2A2B /*! Current Time */ +#define ATT_UUID_ELEVATION 0x2A2C /*! Elevation */ +#define ATT_UUID_LATITUDE 0x2A2D /*! Latitude */ +#define ATT_UUID_LONGITUDE 0x2A2E /*! Longitude */ +#define ATT_UUID_POSITION_2D 0x2A2F /*! Position 2D */ +#define ATT_UUID_POSITION_3D 0x2A30 /*! Position 3D */ +#define ATT_UUID_VENDOR_ID 0x2A31 /*! Vendor ID */ +#define ATT_UUID_HID_BOOT_KEYBOARD_OUT 0x2A32 /*! HID Boot Keyboard Out */ +#define ATT_UUID_HID_BOOT_MOUSE_IN 0x2A33 /*! HID Boot Mouse In */ +#define ATT_UUID_GLUCOSE_MEAS_CONTEXT 0x2A34 /*! Glucose Measurement Context */ +#define ATT_UUID_BP_MEAS 0x2A35 /*! Blood Pressure Measurement */ +#define ATT_UUID_INTERMEDIATE_BP 0x2A36 /*! Intermediate Cuff Pressure */ +#define ATT_UUID_HR_MEAS 0x2A37 /*! Heart Rate Measurement */ +#define ATT_UUID_HR_SENSOR_LOC 0x2A38 /*! Body Sensor Location */ +#define ATT_UUID_HR_CP 0x2A39 /*! Heart Rate Control Point */ +#define ATT_UUID_REMOVABLE 0x2A3A /*! Removable */ +#define ATT_UUID_SERVICE_REQ 0x2A3B /*! Service Required */ +#define ATT_UUID_SCI_TEMP_C 0x2A3C /*! Scientific Temperature in Celsius */ +#define ATT_UUID_STRING 0x2A3D /*! String */ +#define ATT_UUID_NETWORK_AVAIL 0x2A3E /*! Network Availability */ +#define ATT_UUID_ALERT_STATUS 0x2A3F /*! Alert Status */ +#define ATT_UUID_RINGER_CP 0x2A40 /*! Ringer Control Point */ +#define ATT_UUID_RINGER_SETTING 0x2A41 /*! Ringer Setting */ +#define ATT_UUID_ALERT_CAT_ID_MASK 0x2A42 /*! Alert Category ID Bit Mask */ +#define ATT_UUID_ALERT_CAT_ID 0x2A43 /*! Alert Category ID */ +#define ATT_UUID_ALERT_NOTIF_CP 0x2A44 /*! Alert Notification Control Point */ +#define ATT_UUID_UNREAD_ALERT_STATUS 0x2A45 /*! Unread Alert Status */ +#define ATT_UUID_NEW_ALERT 0x2A46 /*! New Alert */ +#define ATT_UUID_SUP_NEW_ALERT_CAT 0x2A47 /*! Supported New Alert Category */ +#define ATT_UUID_SUP_UNREAD_ALERT_CAT 0x2A48 /*! Supported Unread Alert Category */ +#define ATT_UUID_BP_FEATURE 0x2A49 /*! Blood Pressure Feature */ +#define ATT_UUID_HID_INFORMATION 0x2A4A /*! HID Information */ +#define ATT_UUID_HID_REPORT_MAP 0x2A4B /*! HID Report Map */ +#define ATT_UUID_HID_CONTROL_POINT 0x2A4C /*! HID Control Point */ +#define ATT_UUID_HID_REPORT 0x2A4D /*! HID Report */ +#define ATT_UUID_HID_PROTOCOL_MODE 0x2A4E /*! HID Protocol Mode */ +#define ATT_UUID_SCAN_INT_WIND 0x2A4F /*! Scan Interval Window */ +#define ATT_UUID_PNP_ID 0x2A50 /*! PnP ID */ +#define ATT_UUID_GLUCOSE_FEATURE 0x2A51 /*! Glucose Feature */ +#define ATT_UUID_RACP 0x2A52 /*! Record Access Control Point */ +#define ATT_UUID_CAR 0x2AA6 /*! Central Address Resolution */ +#define ATT_UUID_RUNNING_SPEED_FEATURE 0x2A54 /*! Running Speed Feature */ +#define ATT_UUID_RUNNING_SPEED_MEASUREMENT 0x2A53 /*! Running Speed Measurement */ +#define ATT_UUID_PULSE_OX_FEATURES 0x2A60 /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_SPOT_CHECK 0x2A5E /*! Pulse Oximeter Features */ +#define ATT_UUID_PULSE_OX_CONTINUOUS 0x2A5F /*! Pulse Oximeter Features */ +#define ATT_UUID_CYCLING_POWER_FEATURE 0x2A65 /*! Cycling Power Feature */ +#define ATT_UUID_CYCLING_POWER_MEASUREMENT 0x2A63 /*! Cycling Power Measurement */ +#define ATT_UUID_CYCLING_SPEED_FEATURE 0x2A5C /*! Cycling Speed Feature */ +#define ATT_UUID_CYCLING_SPEED_MEASUREMENT 0x2A5B /*! Cycling Speed Measurement */ +#define ATT_UUID_SENSOR_LOCATION 0x2A5D /*! Sensor Location */ +#define ATT_UUID_DB_CHANGE_INCREMENT 0x2A99 /*! Database Change Increment */ +#define ATT_UUID_USER_INDEX 0x2A9A /*! User Index */ +#define ATT_UUID_USER_CONTROL_POINT 0x2A9F /*! User Control Point */ +#define ATT_UUID_RPAO 0x2AC9 /*! Resolvable Prviate Address Only */ + +/* remove when adopted */ +#define ATT_UUID_GENERIC_CTRL_SERVICE 0xF011 +#define ATT_UUID_COMMAND_ENUM 0xE010 /*! Command Enumeration */ +#define ATT_UUID_GENERIC_COMMAND_CP 0xE011 /*! Generic Command Control Point */ +#define ATT_UUID_WEIGHT_SCALE_SERVICE 0x181D /*! Weight Scale Service */ +#define ATT_UUID_WEIGHT_MEAS 0x2A9D /*! Weight Measurement */ +#define ATT_UUID_WEIGHT_SCALE_FEATURE 0x2A9E /*! Weight Scale Feature */ + +/*! Unit UUIDs */ +#define ATT_UUID_UNITLESS 0x2700 /*! unitless */ +#define ATT_UUID_LENGTH_M 0x2701 /*! length metre */ +#define ATT_UUID_MASS_KG 0x2702 /*! mass kilogram */ +#define ATT_UUID_TIME_SEC 0x2703 /*! time second */ +#define ATT_UUID_ELECTRIC_CURRENT_AMP 0x2704 /*! electric current ampere */ +#define ATT_UUID_THERMO_TEMP_K 0x2705 /*! thermodynamic temperature kelvin */ +#define ATT_UUID_AMOUNT_OF_SUBSTANCE_MOLE 0x2706 /*! amount of substance mole */ +#define ATT_UUID_LUMINOUS_INTENSITY_CAND 0x2707 /*! luminous intensity candela */ +#define ATT_UUID_AREA_SQ_M 0x2710 /*! area square metres */ +#define ATT_UUID_VOLUME_CU_M 0x2711 /*! volume cubic metres */ +#define ATT_UUID_VELOCITY_MPS 0x2712 /*! velocity metres per second */ +#define ATT_UUID_ACCELERATION_MPS_SQ 0x2713 /*! acceleration metres per second squared */ +#define ATT_UUID_WAVENUMBER_RECIPROCAL_M 0x2714 /*! wavenumber reciprocal metre */ +#define ATT_UUID_DENSITY_KG_PER_CU_M 0x2715 /*! density kilogram per cubic metre */ +#define ATT_UUID_SURFACE_DENS_KG_PER_SQ_M 0x2716 /*! surface density kilogram per square metre */ +#define ATT_UUID_SPECIFIC_VOL_CU_M_PER_KG 0x2717 /*! specific volume cubic metre per kilogram */ +#define ATT_UUID_CURRENT_DENS_AMP_PER_SQ_M 0x2718 /*! current density ampere per square metre */ +#define ATT_UUID_MAG_FIELD_STR_AMP_PER_M 0x2719 /*! magnetic field strength ampere per metre */ +#define ATT_UUID_AMOUNT_CONC_MOLE_PER_CU_M 0x271A /*! amount concentration mole per cubic metre */ +#define ATT_UUID_MASS_CONC_KG_PER_CU_M 0x271B /*! mass concentration kilogram per cubic metre */ +#define ATT_UUID_LUM_CAND_PER_SQ_M 0x271C /*! luminance candela per square metre */ +#define ATT_UUID_REFRACTIVE_INDEX 0x271D /*! refractive index */ +#define ATT_UUID_RELATIVE_PERMEABILITY 0x271E /*! relative permeability */ +#define ATT_UUID_PLANE_ANGLE_R 0x2720 /*! plane angle radian */ +#define ATT_UUID_SOLID_ANGLE_STER 0x2721 /*! solid angle steradian */ +#define ATT_UUID_FREQUENCY_HERTZ 0x2722 /*! frequency hertz */ +#define ATT_UUID_FORCE_NEWT 0x2723 /*! force newton */ +#define ATT_UUID_PRESSURE_PASCAL 0x2724 /*! pressure pascal */ +#define ATT_UUID_ENERGY_J 0x2725 /*! energy joule */ +#define ATT_UUID_POWER_W 0x2726 /*! power watt */ +#define ATT_UUID_ELECTRIC_CHG_C 0x2727 /*! electric charge coulomb */ +#define ATT_UUID_ELECTRIC_POTENTIAL_VOLT 0x2728 /*! electric potential difference volt */ +#define ATT_UUID_CAPACITANCE_F 0x2729 /*! capacitance farad */ +#define ATT_UUID_ELECTRIC_RESISTANCE_OHM 0x272A /*! electric resistance ohm */ +#define ATT_UUID_ELECTRIC_COND_SIEMENS 0x272B /*! electric conductance siemens */ +#define ATT_UUID_MAGNETIC_FLEX_WEBER 0x272C /*! magnetic flex weber */ +#define ATT_UUID_MAGNETIC_FLEX_DENS_TESLA 0x272D /*! magnetic flex density tesla */ +#define ATT_UUID_INDUCTANCE_H 0x272E /*! inductance henry */ +#define ATT_UUID_C_TEMP_DEG_C 0x272F /*! Celsius temperature degree Celsius */ +#define ATT_UUID_LUMINOUS_FLUX_LUMEN 0x2730 /*! luminous flux lumen */ +#define ATT_UUID_ILLUMINANCE_LUX 0x2731 /*! illuminance lux */ +#define ATT_UUID_RADIONUCLIDE_BECQUEREL 0x2732 /*! activity referred to a radionuclide becquerel */ +#define ATT_UUID_ABSORBED_DOSE_GRAY 0x2733 /*! absorbed dose gray */ +#define ATT_UUID_DOSE_EQUIVALENT_SIEVERT 0x2734 /*! dose equivalent sievert */ +#define ATT_UUID_CATALYTIC_ACTIVITY_KATAL 0x2735 /*! catalytic activity katal */ +#define ATT_UUID_DYNAMIC_VISC_PASCAL_SEC 0x2740 /*! dynamic viscosity pascal second */ +#define ATT_UUID_MOMENT_OF_FORCE_NEWT_M 0x2741 /*! moment of force newton metre */ +#define ATT_UUID_SURFACE_TENSION_NEWT_PER_M 0x2742 /*! surface tension newton per metre */ +#define ATT_UUID_ANG_VELOCITY_R_PER_SEC 0x2743 /*! angular velocity radian per second */ +#define ATT_UUID_ANG_ACCEL_R_PER_SEC_SQD 0x2744 /*! angular acceleration radian per second squared */ +#define ATT_UUID_HEAT_FLUX_DEN_W_PER_SQ_M 0x2745 /*! heat flux density watt per square metre */ +#define ATT_UUID_HEAT_CAP_J_PER_K 0x2746 /*! heat capacity joule per kelvin */ +#define ATT_UUID_SPEC_HEAT_CAP_J_PER_KG_K 0x2747 /*! specific heat capacity joule per kilogram kelvin */ +#define ATT_UUID_SPEC_ENERGY_J_PER_KG 0x2748 /*! specific energy joule per kilogram */ +#define ATT_UUID_THERMAL_COND_W_PER_M_K 0x2749 /*! thermal conductivity watt per metre kelvin */ +#define ATT_UUID_ENERGY_DENSITY_J_PER_CU_M 0x274A /*! energy density joule per cubic metre */ +#define ATT_UUID_ELEC_FIELD_STR_VOLT_PER_M 0x274B /*! electric field strength volt per metre */ +#define ATT_UUID_ELEC_CHG_DENS_C_PER_CU_M 0x274C /*! electric charge density coulomb per cubic metre */ +#define ATT_UUID_SURF_CHG_DENS_C_PER_SQ_M 0x274D /*! surface charge density coulomb per square metre */ +#define ATT_UUID_ELEC_FLUX_DENS_C_PER_SQ_M 0x274E /*! electric flux density coulomb per square metre */ +#define ATT_UUID_PERMITTIVITY_F_PER_M 0x274F /*! permittivity farad per metre */ +#define ATT_UUID_PERMEABILITY_H_PER_M 0x2750 /*! permeability henry per metre */ +#define ATT_UUID_MOLAR_ENERGY_J_PER_MOLE 0x2751 /*! molar energy joule per mole */ +#define ATT_UUID_MOLAR_ENTROPY_J_PER_MOLE_K 0x2752 /*! molar entropy joule per mole kelvin */ +#define ATT_UUID_EXPOSURE_C_PER_KG 0x2753 /*! exposure coulomb per kilogram */ +#define ATT_UUID_DOSE_RATE_GRAY_PER_SEC 0x2754 /*! absorbed dose rate gray per second */ +#define ATT_UUID_RT_INTENSITY_W_PER_STER 0x2755 /*! radiant intensity watt per steradian */ +#define ATT_UUID_RCE_W_PER_SQ_METER_STER 0x2756 /*! radiance watt per square meter steradian */ +#define ATT_UUID_CATALYTIC_KATAL_PER_CU_M 0x2757 /*! catalytic activity concentration katal per cubic metre */ +#define ATT_UUID_TIME_MIN 0x2760 /*! time minute */ +#define ATT_UUID_TIME_HR 0x2761 /*! time hour */ +#define ATT_UUID_TIME_DAY 0x2762 /*! time day */ +#define ATT_UUID_PLANE_ANGLE_DEG 0x2763 /*! plane angle degree */ +#define ATT_UUID_PLANE_ANGLE_MIN 0x2764 /*! plane angle minute */ +#define ATT_UUID_PLANE_ANGLE_SEC 0x2765 /*! plane angle second */ +#define ATT_UUID_AREA_HECTARE 0x2766 /*! area hectare */ +#define ATT_UUID_VOLUME_L 0x2767 /*! volume litre */ +#define ATT_UUID_MASS_TONNE 0x2768 /*! mass tonne */ +#define ATT_UUID_PRESSURE_BAR 0x2780 /*! pressure bar */ +#define ATT_UUID_PRESSURE_MM 0x2781 /*! pressure millimetre of mercury */ +#define ATT_UUID_LENGTH_ANGSTROM 0x2782 /*! length angstrom */ +#define ATT_UUID_LENGTH_NAUTICAL_MILE 0x2783 /*! length nautical mile */ +#define ATT_UUID_AREA_BARN 0x2784 /*! area barn */ +#define ATT_UUID_VELOCITY_KNOT 0x2785 /*! velocity knot */ +#define ATT_UUID_LOG_RADIO_QUANT_NEPER 0x2786 /*! logarithmic radio quantity neper */ +#define ATT_UUID_LOG_RADIO_QUANT_BEL 0x2787 /*! logarithmic radio quantity bel */ +#define ATT_UUID_LOG_RADIO_QUANT_DB 0x2788 /*! logarithmic radio quantity decibel */ +#define ATT_UUID_LENGTH_YARD 0x27A0 /*! length yard */ +#define ATT_UUID_LENGTH_PARSEC 0x27A1 /*! length parsec */ +#define ATT_UUID_LENGTH_IN 0x27A2 /*! length inch */ +#define ATT_UUID_LENGTH_FOOT 0x27A3 /*! length foot */ +#define ATT_UUID_LENGTH_MILE 0x27A4 /*! length mile */ +#define ATT_UUID_PRESSURE_POUND_PER_SQ_IN 0x27A5 /*! pressure pound-force per square inch */ +#define ATT_UUID_VELOCITY_KPH 0x27A6 /*! velocity kilometre per hour */ +#define ATT_UUID_VELOCITY_MPH 0x27A7 /*! velocity mile per hour */ +#define ATT_UUID_ANG_VELOCITY_RPM 0x27A8 /*! angular velocity revolution per minute */ +#define ATT_UUID_ENERGY_GRAM_CALORIE 0x27A9 /*! energy gram calorie */ +#define ATT_UUID_ENERGY_KG_CALORIE 0x27AA /*! energy kilogram calorie */ +#define ATT_UUID_ENERGY_KILOWATT_HR 0x27AB /*! energy kilowatt hour */ +#define ATT_UUID_THERM_TEMP_F 0x27AC /*! thermodynamic temperature degree Fahrenheit */ +#define ATT_UUID_PERCENTAGE 0x27AD /*! percentage */ +#define ATT_UUID_PER_MILLE 0x27AE /*! per mille */ +#define ATT_UUID_PERIOD_BEATS_PER_MIN 0x27AF /*! period beats per minute */ +#define ATT_UUID_ELECTRIC_CHG_AMP_HRS 0x27B0 /*! electric charge ampere hours */ +#define ATT_UUID_MASS_DENSITY_MG_PER_DL 0x27B1 /*! mass density milligram per decilitre */ +#define ATT_UUID_MASS_DENSITY_MMOLE_PER_L 0x27B2 /*! mass density millimole per litre */ +#define ATT_UUID_TIME_YEAR 0x27B3 /*! time year */ +#define ATT_UUID_TIME_MONTH 0x27B4 /*! time month */ + +/*! ARM Ltd. proprietary UUIDs */ + +/*! Base UUID: E0262760-08C2-11E1-9073-0E8AC72EXXXX */ +#define ATT_UUID_ARM_BASE 0x2E, 0xC7, 0x8A, 0x0E, 0x73, 0x90, \ + 0xE1, 0x11, 0xC2, 0x08, 0x60, 0x27, 0x26, 0xE0 + +/*! Macro for building ARM Ltd. UUIDs */ +#define ATT_UUID_ARM_BUILD(part) UINT16_TO_BYTES(part), ATT_UUID_ARM_BASE + +/*! Partial proprietary service UUIDs */ +#define ATT_UUID_P1_SERVICE_PART 0x1001 /*! Proprietary service P1 */ + +/*! Partial proprietary characteristic UUIDs */ +#define ATT_UUID_D1_DATA_PART 0x0001 /*! Proprietary data D1 */ + +/* Proprietary services */ +#define ATT_UUID_P1_SERVICE ATT_UUID_ARM_BUILD(ATT_UUID_P1_SERVICE_PART) + +/* Proprietary characteristics */ +#define ATT_UUID_D1_DATA ATT_UUID_ARM_BUILD(ATT_UUID_D1_DATA_PART) + +/************************************************************************************************** + Global Variables +**************************************************************************************************/ + +/*! Service UUIDs */ +extern const uint8_t attGapSvcUuid[ATT_16_UUID_LEN]; /*! Generic Access Profile Service */ +extern const uint8_t attGattSvcUuid[ATT_16_UUID_LEN]; /*! Generic Attribute Profile Service */ +extern const uint8_t attIasSvcUuid[ATT_16_UUID_LEN]; /*! Immediate Alert Service */ +extern const uint8_t attLlsSvcUuid[ATT_16_UUID_LEN]; /*! Link Loss Service */ +extern const uint8_t attTpsSvcUuid[ATT_16_UUID_LEN]; /*! Tx Power Service */ +extern const uint8_t attCtsSvcUuid[ATT_16_UUID_LEN]; /*! Current Time Service */ +extern const uint8_t attRtusSvcUuid[ATT_16_UUID_LEN]; /*! Reference Time Update Service */ +extern const uint8_t attNdcsSvcUuid[ATT_16_UUID_LEN]; /*! Next DST Change Service */ +extern const uint8_t attGlsSvcUuid[ATT_16_UUID_LEN]; /*! Glucose Service */ +extern const uint8_t attHtsSvcUuid[ATT_16_UUID_LEN]; /*! Health Thermometer Service */ +extern const uint8_t attDisSvcUuid[ATT_16_UUID_LEN]; /*! Device Information Service */ +extern const uint8_t attNwaSvcUuid[ATT_16_UUID_LEN]; /*! Network Availability Service */ +extern const uint8_t attWdsSvcUuid[ATT_16_UUID_LEN]; /*! Watchdog Service */ +extern const uint8_t attHrsSvcUuid[ATT_16_UUID_LEN]; /*! Heart Rate Service */ +extern const uint8_t attPassSvcUuid[ATT_16_UUID_LEN]; /*! Phone Alert Status Service */ +extern const uint8_t attBasSvcUuid[ATT_16_UUID_LEN]; /*! Battery Service */ +extern const uint8_t attBpsSvcUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Service */ +extern const uint8_t attAnsSvcUuid[ATT_16_UUID_LEN]; /*! Alert Notification Service */ +extern const uint8_t attHidSvcUuid[ATT_16_UUID_LEN]; /*! Human Interface Device Service */ +extern const uint8_t attSpsSvcUuid[ATT_16_UUID_LEN]; /*! Scan Parameter Service */ +extern const uint8_t attPlxsSvcUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Service */ +extern const uint8_t attUdsSvcUuid[ATT_16_UUID_LEN]; /*! User Data Service */ + +/*! GATT UUIDs */ +extern const uint8_t attPrimSvcUuid[ATT_16_UUID_LEN]; /*! Primary Service */ +extern const uint8_t attSecSvcUuid[ATT_16_UUID_LEN]; /*! Secondary Service */ +extern const uint8_t attIncUuid[ATT_16_UUID_LEN]; /*! Include */ +extern const uint8_t attChUuid[ATT_16_UUID_LEN]; /*! Characteristic */ + +/*! Descriptor UUIDs */ +extern const uint8_t attChExtUuid[ATT_16_UUID_LEN]; /*! Characteristic Extended Properties */ +extern const uint8_t attChUserDescUuid[ATT_16_UUID_LEN]; /*! Characteristic User Description */ +extern const uint8_t attCliChCfgUuid[ATT_16_UUID_LEN]; /*! Client Characteristic Configuration */ +extern const uint8_t attSrvChCfgUuid[ATT_16_UUID_LEN]; /*! Server Characteristic Configuration */ +extern const uint8_t attChPresFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Presentation Format */ +extern const uint8_t attAggFmtUuid[ATT_16_UUID_LEN]; /*! Characteristic Aggregate Format */ +extern const uint8_t attHidErmUuid[ATT_16_UUID_LEN]; /*! HID External Report Reference */ +extern const uint8_t attHidRimUuid[ATT_16_UUID_LEN]; /*! HID Report ID Mapping */ +extern const uint8_t attValRangeUuid[ATT_16_UUID_LEN]; /*! Valid Range */ + +/*! Characteristic UUIDs */ +extern const uint8_t attDnChUuid[ATT_16_UUID_LEN]; /*! Device Name */ +extern const uint8_t attApChUuid[ATT_16_UUID_LEN]; /*! Appearance */ +extern const uint8_t attPpfChUuid[ATT_16_UUID_LEN]; /*! Peripheral Privacy Flag */ +extern const uint8_t attRaChUuid[ATT_16_UUID_LEN]; /*! Reconnection Address */ +extern const uint8_t attPpcpChUuid[ATT_16_UUID_LEN]; /*! Peripheral Preferred Connection Parameters */ +extern const uint8_t attScChUuid[ATT_16_UUID_LEN]; /*! Service Changed */ +extern const uint8_t attAlChUuid[ATT_16_UUID_LEN]; /*! Alert Level */ +extern const uint8_t attTxpChUuid[ATT_16_UUID_LEN]; /*! Tx Power Level */ +extern const uint8_t attDtChUuid[ATT_16_UUID_LEN]; /*! Date Time */ +extern const uint8_t attDwChUuid[ATT_16_UUID_LEN]; /*! Day of Week */ +extern const uint8_t attDdtChUuid[ATT_16_UUID_LEN]; /*! Day Date Time */ +extern const uint8_t attEt100ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 100 */ +extern const uint8_t attEt256ChUuid[ATT_16_UUID_LEN]; /*! Exact Time 256 */ +extern const uint8_t attDstoChUuid[ATT_16_UUID_LEN]; /*! DST Offset */ +extern const uint8_t attTzChUuid[ATT_16_UUID_LEN]; /*! Time Zone */ +extern const uint8_t attLtiChUuid[ATT_16_UUID_LEN]; /*! Local Time Information */ +extern const uint8_t attStzChUuid[ATT_16_UUID_LEN]; /*! Secondary Time Zone */ +extern const uint8_t attTdstChUuid[ATT_16_UUID_LEN]; /*! Time with DST */ +extern const uint8_t attTaChUuid[ATT_16_UUID_LEN]; /*! Time Accuracy */ +extern const uint8_t attTsChUuid[ATT_16_UUID_LEN]; /*! Time Source */ +extern const uint8_t attRtiChUuid[ATT_16_UUID_LEN]; /*! Reference Time Information */ +extern const uint8_t attTbChUuid[ATT_16_UUID_LEN]; /*! Time Broadcast */ +extern const uint8_t attTucpChUuid[ATT_16_UUID_LEN]; /*! Time Update Control Point */ +extern const uint8_t attTusChUuid[ATT_16_UUID_LEN]; /*! Time Update State */ +extern const uint8_t attGlmChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement */ +extern const uint8_t attBlChUuid[ATT_16_UUID_LEN]; /*! Battery Level */ +extern const uint8_t attBpsChUuid[ATT_16_UUID_LEN]; /*! Battery Power State */ +extern const uint8_t attBlsChUuid[ATT_16_UUID_LEN]; /*! Battery Level State */ +extern const uint8_t attTmChUuid[ATT_16_UUID_LEN]; /*! Temperature Measurement */ +extern const uint8_t attTtChUuid[ATT_16_UUID_LEN]; /*! Temperature Type */ +extern const uint8_t attItChUuid[ATT_16_UUID_LEN]; /*! Intermediate Temperature */ +extern const uint8_t attTcelChUuid[ATT_16_UUID_LEN]; /*! Temperature Celsius */ +extern const uint8_t attTfahChUuid[ATT_16_UUID_LEN]; /*! Temperature Fahrenheit */ +extern const uint8_t attSidChUuid[ATT_16_UUID_LEN]; /*! System ID */ +extern const uint8_t attMnsChUuid[ATT_16_UUID_LEN]; /*! Model Number String */ +extern const uint8_t attSnsChUuid[ATT_16_UUID_LEN]; /*! Serial Number String */ +extern const uint8_t attFrsChUuid[ATT_16_UUID_LEN]; /*! Firmware Revision String */ +extern const uint8_t attHrsChUuid[ATT_16_UUID_LEN]; /*! Hardware Revision String */ +extern const uint8_t attSrsChUuid[ATT_16_UUID_LEN]; /*! Software Revision String */ +extern const uint8_t attMfnsChUuid[ATT_16_UUID_LEN]; /*! Manufacturer Name String */ +extern const uint8_t attIeeeChUuid[ATT_16_UUID_LEN]; /*! IEEE 11073-20601 Regulatory Certification Data List */ +extern const uint8_t attCtChUuid[ATT_16_UUID_LEN]; /*! Current Time */ +extern const uint8_t attElChUuid[ATT_16_UUID_LEN]; /*! Elevation */ +extern const uint8_t attLatChUuid[ATT_16_UUID_LEN]; /*! Latitude */ +extern const uint8_t attLongChUuid[ATT_16_UUID_LEN]; /*! Longitude */ +extern const uint8_t attP2dChUuid[ATT_16_UUID_LEN]; /*! Position 2D */ +extern const uint8_t attP3dChUuid[ATT_16_UUID_LEN]; /*! Position 3D */ +extern const uint8_t attVidChUuid[ATT_16_UUID_LEN]; /*! Vendor ID */ +extern const uint8_t attGlmcChUuid[ATT_16_UUID_LEN]; /*! Glucose Measurement Context */ +extern const uint8_t attBpmChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Measurement */ +extern const uint8_t attIcpChUuid[ATT_16_UUID_LEN]; /*! Intermediate Cuff Pressure */ +extern const uint8_t attHrmChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Measurement */ +extern const uint8_t attBslChUuid[ATT_16_UUID_LEN]; /*! Body Sensor Location */ +extern const uint8_t attHrcpChUuid[ATT_16_UUID_LEN]; /*! Heart Rate Control Point */ +extern const uint8_t attRemChUuid[ATT_16_UUID_LEN]; /*! Removable */ +extern const uint8_t attSrChUuid[ATT_16_UUID_LEN]; /*! Service Required */ +extern const uint8_t attStcChUuid[ATT_16_UUID_LEN]; /*! Scientific Temperature in Celsius */ +extern const uint8_t attStrChUuid[ATT_16_UUID_LEN]; /*! String */ +extern const uint8_t attNwaChUuid[ATT_16_UUID_LEN]; /*! Network Availability */ +extern const uint8_t attAsChUuid[ATT_16_UUID_LEN]; /*! Alert Status */ +extern const uint8_t attRcpChUuid[ATT_16_UUID_LEN]; /*! Ringer Control Point */ +extern const uint8_t attRsChUuid[ATT_16_UUID_LEN]; /*! Ringer Setting */ +extern const uint8_t attAcbmChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID Bit Mask */ +extern const uint8_t attAcChUuid[ATT_16_UUID_LEN]; /*! Alert Category ID */ +extern const uint8_t attAncpChUuid[ATT_16_UUID_LEN]; /*! Alert Notification Control Point */ +extern const uint8_t attUasChUuid[ATT_16_UUID_LEN]; /*! Unread Alert Status */ +extern const uint8_t attNaChUuid[ATT_16_UUID_LEN]; /*! New Alert */ +extern const uint8_t attSnacChUuid[ATT_16_UUID_LEN]; /*! Supported New Alert Category */ +extern const uint8_t attSuacChUuid[ATT_16_UUID_LEN]; /*! Supported Unread Alert Category */ +extern const uint8_t attBpfChUuid[ATT_16_UUID_LEN]; /*! Blood Pressure Feature */ +extern const uint8_t attHidBmiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidBkoChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidiChUuid[ATT_16_UUID_LEN]; /*! HID Information */ +extern const uint8_t attHidRmChUuid[ATT_16_UUID_LEN]; /*! Report Map */ +extern const uint8_t attHidcpChUuid[ATT_16_UUID_LEN]; /*! HID Control Point */ +extern const uint8_t attHidRepChUuid[ATT_16_UUID_LEN]; /*! Report */ +extern const uint8_t attHidPmChUuid[ATT_16_UUID_LEN]; /*! Protocol Mode */ +extern const uint8_t attSiwChUuid[ATT_16_UUID_LEN]; /*! Scan Interval Window */ +extern const uint8_t attPnpChUuid[ATT_16_UUID_LEN]; /*! PnP ID */ +extern const uint8_t attGlfChUuid[ATT_16_UUID_LEN]; /*! Glucose Feature */ +extern const uint8_t attRacpChUuid[ATT_16_UUID_LEN]; /*! Record Access Control Point */ +extern const uint8_t attCarChUuid[ATT_16_UUID_LEN]; /*! Central Address Resolution */ +extern const uint8_t attRsfChUuid[ATT_16_UUID_LEN]; /*! Running Speed Features */ +extern const uint8_t attRsmChUuid[ATT_16_UUID_LEN]; /*! Running Speed Measurement */ +extern const uint8_t attCpfChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Features */ +extern const uint8_t attCpmChUuid[ATT_16_UUID_LEN]; /*! Cycling Power Measurement */ +extern const uint8_t attCsfChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Features */ +extern const uint8_t attCsmChUuid[ATT_16_UUID_LEN]; /*! Cycling Speed Measurement */ +extern const uint8_t attSlChUuid[ATT_16_UUID_LEN]; /*! Sensor Location */ +extern const uint8_t attPlxfChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Features */ +extern const uint8_t attPlxscmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Spot Check Measurement */ +extern const uint8_t attPlxcmChUuid[ATT_16_UUID_LEN]; /*! Pulse Oximeter Continuous Measurement */ +extern const uint8_t attRpaoChUuid[ATT_16_UUID_LEN]; /*! Resolvable Private Address Only */ +extern const uint8_t attDbciChUuid[ATT_16_UUID_LEN]; /*! Database Change Increment */ +extern const uint8_t attUiChUuid[ATT_16_UUID_LEN]; /*! User Index */ +extern const uint8_t attUcpChUuid[ATT_16_UUID_LEN]; /*! User Control Point */ + +/* remove when adopted */ +extern const uint8_t attWssSvcUuid[ATT_16_UUID_LEN]; /*! Weight scale service */ +extern const uint8_t attWmChUuid[ATT_16_UUID_LEN]; /*! Weight measurement */ +extern const uint8_t attWsfChUuid[ATT_16_UUID_LEN]; /*! Weight scale feature */ + +#ifdef __cplusplus +}; +#endif + +#endif /* ATT_UUID_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h new file mode 100644 index 00000000000..ad01975349d --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_api.h @@ -0,0 +1,2423 @@ +/*************************************************************************************************/ +/*! + * \file dm_api.h + * + * \brief Device Manager subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2016-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_API_H +#define DM_API_H + +#include "hci_api.h" +#include "cfg_stack.h" +#include "smp_defs.h" +#include "sec_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Device role */ +#define DM_ROLE_MASTER HCI_ROLE_MASTER /*! Role is master */ +#define DM_ROLE_SLAVE HCI_ROLE_SLAVE /*! Role is slave */ + +/*! The GAP discovery mode */ +#define DM_DISC_MODE_NONE 0 /*! GAP non-discoverable */ +#define DM_DISC_MODE_LIMITED 1 /*! GAP limited discoverable mode */ +#define DM_DISC_MODE_GENERAL 2 /*! GAP general discoverable mode */ + +/*! The type of connectable or discoverable of advertising */ +#define DM_ADV_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_ADV_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_ADV_NONCONN_UNDIRECT 3 /*! Non-connectable and non-scannable undirected advertising */ +#define DM_ADV_CONN_DIRECT_LO_DUTY 4 /*! Connectable directed low duty cycle advertising */ + +/*! The type of extended advertising -- only applicable to AE */ +#define DM_EXT_ADV_CONN_UNDIRECT 5 /*! Connectable undirected advertising */ +#define DM_EXT_ADV_NONCONN_DIRECT 6 /*! Non-connectable and non-scannable directed advertising */ +#define DM_EXT_ADV_SCAN_DIRECT 7 /*! Scannable directed advertising */ +#define DM_ADV_NONE 255 /*! For internal use only */ + +/*! The type of advertising report */ +#define DM_RPT_CONN_UNDIRECT 0 /*! Connectable and scannable undirected advertising */ +#define DM_RPT_CONN_DIRECT 1 /*! Connectable directed advertising */ +#define DM_RPT_SCAN_UNDIRECT 2 /*! Scannable undirected advertising */ +#define DM_RPT_NONCONN_UNDIRECT 3 /*! Non-connectable undirected advertising */ +#define DM_RPT_SCAN_RESPONSE 4 /*! Scan response */ + +/*! Whether data is located in the advertising data or the scan response data */ +#define DM_DATA_LOC_ADV 0 /*! Locate data in the advertising data */ +#define DM_DATA_LOC_SCAN 1 /*! Locate data in the scan response data */ + +/*! The scan type */ +#define DM_SCAN_TYPE_PASSIVE 0 /*! Passive scan */ +#define DM_SCAN_TYPE_ACTIVE 1 /*! Active scan */ + +/*! Advertising channel map */ +#define DM_ADV_CHAN_37 HCI_ADV_CHAN_37 /*! Advertising channel 37 */ +#define DM_ADV_CHAN_38 HCI_ADV_CHAN_38 /*! Advertising channel 38 */ +#define DM_ADV_CHAN_39 HCI_ADV_CHAN_39 /*! Advertising channel 39 */ +#define DM_ADV_CHAN_ALL (HCI_ADV_CHAN_37 | HCI_ADV_CHAN_38 | HCI_ADV_CHAN_39) + +/*! The client ID parameter to function DmConnRegister() */ +#define DM_CLIENT_ID_ATT 0 /*! Identifier for attribute protocol, for internal use only */ +#define DM_CLIENT_ID_SMP 1 /*! Identifier for security manager protocol, for internal use only */ +#define DM_CLIENT_ID_DM 2 /*! Identifier for device manager, for internal use only */ +#define DM_CLIENT_ID_APP 3 /*! Identifier for the application */ +#define DM_CLIENT_ID_L2C 4 /*! Identifier for L2CAP */ +#define DM_CLIENT_ID_MAX 5 /*! For internal use only */ + +/*! Unknown connection ID or other error */ +#define DM_CONN_ID_NONE 0 + +/*! The address type */ +#define DM_ADDR_PUBLIC 0x00 /*! Public device address */ +#define DM_ADDR_RANDOM 0x01 /*! Random device address */ +#define DM_ADDR_PUBLIC_IDENTITY 0x02 /*! Public identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_IDENTITY 0x03 /*! Random (static) identity address (corresponds to resolved private address) */ +#define DM_ADDR_RANDOM_UNRESOLVED 0xFE /*! Random device address (Controller unable to resolve) */ +#define DM_ADDR_NONE 0xFF /*! No address provided (anonymous) */ + +/*! Advertising data types */ +#define DM_ADV_TYPE_FLAGS 0x01 /*! Flag bits */ +#define DM_ADV_TYPE_16_UUID_PART 0x02 /*! Partial list of 16 bit UUIDs */ +#define DM_ADV_TYPE_16_UUID 0x03 /*! Complete list of 16 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID_PART 0x04 /*! Partial list of 32 bit UUIDs */ +#define DM_ADV_TYPE_32_UUID 0x05 /*! Complete list of 32 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID_PART 0x06 /*! Partial list of 128 bit UUIDs */ +#define DM_ADV_TYPE_128_UUID 0x07 /*! Complete list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SHORT_NAME 0x08 /*! Shortened local name */ +#define DM_ADV_TYPE_LOCAL_NAME 0x09 /*! Complete local name */ +#define DM_ADV_TYPE_TX_POWER 0x0A /*! TX power level */ +#define DM_ADV_TYPE_SM_TK_VALUE 0x10 /*! Security manager TK value */ +#define DM_ADV_TYPE_SM_OOB_FLAGS 0x11 /*! Security manager OOB flags */ +#define DM_ADV_TYPE_CONN_INTERVAL 0x12 /*! Slave preferred connection interval */ +#define DM_ADV_TYPE_SIGNED_DATA 0x13 /*! Signed data */ +#define DM_ADV_TYPE_16_SOLICIT 0x14 /*! Service soliticiation list of 16 bit UUIDs */ +#define DM_ADV_TYPE_128_SOLICIT 0x15 /*! Service soliticiation list of 128 bit UUIDs */ +#define DM_ADV_TYPE_SERVICE_DATA 0x16 /*! Service data - 16-bit UUID */ +#define DM_ADV_TYPE_PUBLIC_TARGET 0x17 /*! Public target address */ +#define DM_ADV_TYPE_RANDOM_TARGET 0x18 /*! Random target address */ +#define DM_ADV_TYPE_APPEARANCE 0x19 /*! Device appearance */ +#define DM_ADV_TYPE_ADV_INTERVAL 0x1A /*! Advertising interval */ +#define DM_ADV_TYPE_BD_ADDR 0x1B /*! LE Bluetooth device address */ +#define DM_ADV_TYPE_ROLE 0x1C /*! LE role */ +#define DM_ADV_TYPE_32_SOLICIT 0x1F /*! Service soliticiation list of 32 bit UUIDs */ +#define DM_ADV_TYPE_SVC_DATA_32 0x20 /*! Service data - 32-bit UUID */ +#define DM_ADV_TYPE_SVC_DATA_128 0x21 /*! Service data - 128-bit UUID */ +#define DM_ADV_TYPE_LESC_CONFIRM 0x22 /*! LE Secure Connections confirm value */ +#define DM_ADV_TYPE_LESC_RANDOM 0x23 /*! LE Secure Connections random value */ +#define DM_ADV_TYPE_URI 0x24 /*! URI */ +#define DM_ADV_TYPE_MANUFACTURER 0xFF /*! Manufacturer specific data */ + +/*! Bit mask for flags advertising data type */ +#define DM_FLAG_LE_LIMITED_DISC 0x01 /*! Limited discoverable flag */ +#define DM_FLAG_LE_GENERAL_DISC 0x02 /*! General discoverable flag */ +#define DM_FLAG_LE_BREDR_NOT_SUP 0x04 /*! BR/EDR not supported flag */ + +/*! Advertising data element indexes */ +#define DM_AD_LEN_IDX 0 /*! Advertising data element len */ +#define DM_AD_TYPE_IDX 1 /*! Advertising data element type */ +#define DM_AD_DATA_IDX 2 /*! Advertising data element data */ + +/*! Advertising URI Scheme */ +#define DM_URI_SCHEME_HTTP 0x16 /*! URI HTTP Scheme */ +#define DM_URI_SCHEME_HTTPS 0x17 /*! URI HTTPS Scheme */ + +/*! Timeouts defined by the GAP specification; in units of milliseconds */ +#define DM_GAP_LIM_ADV_TIMEOUT 180000 /*! Maximum advertising duration in limited discoverable mode */ +#define DM_GAP_GEN_DISC_SCAN_MIN 10240 /*! Minimum scan duration for general discovery */ +#define DM_GAP_LIM_DISC_SCAN_MIN 10240 /*! Minimum scan duration for limited discovery */ +#define DM_GAP_CONN_PARAM_TIMEOUT 30000 /*! Connection parameter update timeout */ +#define DM_GAP_SCAN_FAST_PERIOD 30720 /*! Minimum time to perform scanning when user initiated */ +#define DM_GAP_ADV_FAST_PERIOD 30000 /*! Minimum time to perform advertising when user initiated */ + +/*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE 1M PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_FAST_INT_MIN 48 /*! Minimum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_INT_MAX 96 /*! Maximum scan interval when user initiated */ +#define DM_GAP_SCAN_FAST_WINDOW 48 /*! Scan window when user initiated */ +#define DM_GAP_SCAN_SLOW_INT_1 2048 /*! Scan interval 1 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_1 18 /*! Scan window 1 when background scanning */ +#define DM_GAP_SCAN_SLOW_INT_2 4096 /*! Scan interval 2 when background scannning */ +#define DM_GAP_SCAN_SLOW_WINDOW_2 36 /*! Scan window 2 when background scanning */ +#define DM_GAP_ADV_FAST_INT_MIN_1 48 /*! Minimum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_1 96 /*! Maximum advertising interval 1 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MIN_2 160 /*! Minimum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_FAST_INT_MAX_2 240 /*! Maximum advertising interval 2 when user initiated */ +#define DM_GAP_ADV_SLOW_INT_MIN 1600 /*! Minimum advertising interval when background advertising */ +#define DM_GAP_ADV_SLOW_INT_MAX 1920 /*! Maximum advertising interval when background advertising */ + + /*! + * Advertising, scanning, and connection parameters defined in the GAP specification for the LE Coded PHY. + * In units of 625 microseconds. + */ +#define DM_GAP_SCAN_CODED_FAST_INT_MIN 144 /*! Minimum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_INT_MAX 288 /*! Maximum scan interval when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_FAST_WINDOW 144 /*! Scan window when user initiated on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_1 6144 /*! Scan interval 1 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_1 54 /*! Scan window 1 when background scanning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_INT_2 12288 /*! Scan interval 2 when background scannning on LE Coded PHY */ +#define DM_GAP_SCAN_CODED_SLOW_WINDOW_2 108 /*! Scan window 2 when background scanning on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_1 144 /*! Minimum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_1 288 /*! Maximum advertising interval 1 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MIN_2 480 /*! Minimum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_FAST_INT_MAX_2 720 /*! Maximum advertising interval 2 when user initiated on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MIN 4800 /*! Minimum advertising interval when background advertising on LE Coded PHY */ +#define DM_GAP_ADV_CODED_SLOW_INT_MAX 5760 /*! Maximum advertising interval when background advertising on LE Coded PHY */ + +/*! GAP connection establishment latency */ +#define DM_GAP_CONN_EST_LATENCY 0 + +/*! GAP connection intervals in 1.25ms units */ +#define DM_GAP_INITIAL_CONN_INT_MIN 24 /*! Minimum initial connection interval */ +#define DM_GAP_INITIAL_CONN_INT_MAX 40 /*! Maximum initial onnection interval */ + +/*! GAP connection establishment minimum and maximum connection event lengths */ +#define DM_GAP_CONN_EST_MIN_CE_LEN 0 +#define DM_GAP_CONN_EST_MAX_CE_LEN 0 + +/*! GAP peripheral privacy flag characteristic values */ +#define DM_GAP_PRIV_DISABLED 0 +#define DM_GAP_PRIV_ENABLED 1 + +/*! Connection establishment supervision timeout default, in 10ms units */ +#define DM_DEFAULT_EST_SUP_TIMEOUT 2000 + +/*! Pairing authentication/security properties bit mask */ +#define DM_AUTH_BOND_FLAG SMP_AUTH_BOND_FLAG /*! Bonding requested */ +#define DM_AUTH_MITM_FLAG SMP_AUTH_MITM_FLAG /*! MITM (authenticated pairing) requested */ +#define DM_AUTH_SC_FLAG SMP_AUTH_SC_FLAG /*! LE Secure Connections requested */ +#define DM_AUTH_KP_FLAG SMP_AUTH_KP_FLAG /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define DM_KEY_DIST_LTK SMP_KEY_DIST_ENC /*! Distribute LTK used for encryption */ +#define DM_KEY_DIST_IRK SMP_KEY_DIST_ID /*! Distribute IRK used for privacy */ +#define DM_KEY_DIST_CSRK SMP_KEY_DIST_SIGN /*! Distribute CSRK used for signed data */ + +/*! Key type used in DM_SEC_KEY_IND */ +#define DM_KEY_LOCAL_LTK 0x01 /*! LTK generated locally for this device */ +#define DM_KEY_PEER_LTK 0x02 /*! LTK received from peer device */ +#define DM_KEY_IRK 0x04 /*! IRK and identity info of peer device */ +#define DM_KEY_CSRK 0x08 /*! CSRK of peer device */ + +/*! Base value for HCI error status values for DM_SEC_PAIR_CMPL_IND */ +#define DM_SEC_HCI_ERR_BASE 0x20 + +#define DM_SEC_LEVEL_NONE 0 /*! Connection has no security */ +#define DM_SEC_LEVEL_ENC 1 /*! Connection is encrypted with unauthenticated key */ +#define DM_SEC_LEVEL_ENC_AUTH 2 /*! Connection is encrypted with authenticated key */ +#define DM_SEC_LEVEL_ENC_LESC 3 /*! Connection is encrypted with LE Secure Connections */ + +/*! Random address types */ +#define DM_RAND_ADDR_STATIC 0xC0 /*! Static address */ +#define DM_RAND_ADDR_RESOLV 0x40 /*! Resolvable private address */ +#define DM_RAND_ADDR_NONRESOLV 0x00 /*! Non-resolvable private address */ + +/*! Privacy modes */ +#define DM_PRIV_MODE_NETWORK 0x00 /*! Network privacy mode (default) */ +#define DM_PRIV_MODE_DEVICE 0x01 /*! Device privacy mode */ + +/*! Get the type of random address */ +#define DM_RAND_ADDR_GET(addr) ((addr)[5] & 0xC0) + +/*! Set the type of random address */ +#define DM_RAND_ADDR_SET(addr, type) {(addr)[5] = ((addr)[5] & 0x3F) | (type);} + +/*! Check for Resolvable Random Address */ +#define DM_RAND_ADDR_RPA(addr, type) (((type) == DM_ADDR_RANDOM) && \ + (DM_RAND_ADDR_GET((addr)) == DM_RAND_ADDR_RESOLV)) + +/*! Connection busy/idle state */ +#define DM_CONN_IDLE 0 /*! Connection is idle */ +#define DM_CONN_BUSY 1 /*! Connection is busy */ + +/*! Connection busy/idle state bitmask */ +#define DM_IDLE_SMP_PAIR 0x0001 /*! SMP pairing in progress */ +#define DM_IDLE_DM_ENC 0x0002 /*! DM Encryption setup in progress */ +#define DM_IDLE_ATTS_DISC 0x0004 /*! ATTS service discovery in progress */ +#define DM_IDLE_APP_DISC 0x0008 /*! App framework service discovery in progress */ +#define DM_IDLE_USER_1 0x0010 /*! For use by user application */ +#define DM_IDLE_USER_2 0x0020 /*! For use by user application */ +#define DM_IDLE_USER_3 0x0040 /*! For use by user application */ +#define DM_IDLE_USER_4 0x0080 /*! For use by user application */ + +/*! Filter policy modes */ +#define DM_FILT_POLICY_MODE_ADV 0 /*! Advertising filter policy mode */ +#define DM_FILT_POLICY_MODE_SCAN 1 /*! Scanning filter policy mode */ +#define DM_FILT_POLICY_MODE_INIT 2 /*! Initiator filter policy mode */ + +/*! Proprietary internal error codes */ +#define DM_ERR_SMP_RX_PDU_LEN_EXCEEDED 0x01 /*! LESC key length exceeded maximum RX PDU length */ +#define DM_ERR_ATT_RX_PDU_LEN_EXCEEDED 0x02 /*! Configured ATT MTU exceeded maximum RX PDU length */ +#define DM_ERR_L2C_RX_PDU_LEN_EXCEEDED 0x03 /*! Registered COC MPS exceeded maximum RX PDU length */ + +/*! Advertising handle */ +#define DM_ADV_HANDLE_DEFAULT 0 /*! Default advertising handle for legacy advertising */ + +/*! DM callback events */ +#define DM_CBACK_START 0x20 /*! DM callback event starting value */ +enum +{ + DM_RESET_CMPL_IND = DM_CBACK_START, /*! Reset complete */ + DM_ADV_START_IND, /*! Advertising started */ + DM_ADV_STOP_IND, /*! Advertising stopped */ + DM_ADV_NEW_ADDR_IND, /*! New resolvable address has been generated */ + DM_SCAN_START_IND, /*! Scanning started */ + DM_SCAN_STOP_IND, /*! Scanning stopped */ + DM_SCAN_REPORT_IND, /*! Scan data received from peer device */ + DM_CONN_OPEN_IND, /*! Connection opened */ + DM_CONN_CLOSE_IND, /*! Connection closed */ + DM_CONN_UPDATE_IND, /*! Connection update complete */ + DM_SEC_PAIR_CMPL_IND, /*! Pairing completed successfully */ + DM_SEC_PAIR_FAIL_IND, /*! Pairing failed or other security failure */ + DM_SEC_ENCRYPT_IND, /*! Connection encrypted */ + DM_SEC_ENCRYPT_FAIL_IND, /*! Encryption failed */ + DM_SEC_AUTH_REQ_IND, /*! PIN or OOB data requested for pairing */ + DM_SEC_KEY_IND, /*! Security key indication */ + DM_SEC_LTK_REQ_IND, /*! LTK requested for encyption */ + DM_SEC_PAIR_IND, /*! Incoming pairing request from master */ + DM_SEC_SLAVE_REQ_IND, /*! Incoming security request from slave */ + DM_SEC_CALC_OOB_IND, /*! Result of OOB Confirm Calculation Generation */ + DM_SEC_ECC_KEY_IND, /*! Result of ECC Key Generation */ + DM_SEC_COMPARE_IND, /*! Result of Just Works/Numeric Comparison Compare Value Calculation */ + DM_SEC_KEYPRESS_IND, /*! Keypress indication from peer in passkey security */ + DM_PRIV_RESOLVED_ADDR_IND, /*! Private address resolved */ + DM_CONN_READ_RSSI_IND, /*! Connection RSSI read */ + DM_PRIV_ADD_DEV_TO_RES_LIST_IND, /*! Device added to resolving list */ + DM_PRIV_REM_DEV_FROM_RES_LIST_IND, /*! Device removed from resolving list */ + DM_PRIV_CLEAR_RES_LIST_IND, /*! Resolving list cleared */ + DM_PRIV_READ_PEER_RES_ADDR_IND, /*! Peer resolving address read */ + DM_PRIV_READ_LOCAL_RES_ADDR_IND, /*! Local resolving address read */ + DM_PRIV_SET_ADDR_RES_ENABLE_IND, /*! Address resolving enable set */ + DM_REM_CONN_PARAM_REQ_IND, /*! Remote connection parameter requested */ + DM_CONN_DATA_LEN_CHANGE_IND, /*! Data length changed */ + DM_CONN_WRITE_AUTH_TO_IND, /*! Write authenticated payload complete */ + DM_CONN_AUTH_TO_EXPIRED_IND, /*! Authenticated payload timeout expired */ + DM_PHY_READ_IND, /*! Read PHY */ + DM_PHY_SET_DEF_IND, /*! Set default PHY */ + DM_PHY_UPDATE_IND, /*! PHY update */ + DM_ADV_SET_START_IND, /*! Advertising set(s) started */ + DM_ADV_SET_STOP_IND, /*! Advertising set(s) stopped */ + DM_SCAN_REQ_RCVD_IND, /*! Scan request received */ + DM_EXT_SCAN_START_IND, /*! Extended scanning started */ + DM_EXT_SCAN_STOP_IND, /*! Extended scanning stopped */ + DM_EXT_SCAN_REPORT_IND, /*! Extended scan data received from peer device */ + DM_PER_ADV_SET_START_IND, /*! Periodic advertising set started */ + DM_PER_ADV_SET_STOP_IND, /*! Periodic advertising set stopped */ + DM_PER_ADV_SYNC_EST_IND, /*! Periodic advertising sync established */ + DM_PER_ADV_SYNC_LOST_IND, /*! Periodic advertising sync lost */ + DM_PER_ADV_REPORT_IND, /*! Periodic advertising data received from peer device */ + DM_REMOTE_FEATURES_IND, /*! Remote features from peer device */ + DM_ERROR_IND, /*! General error */ + DM_VENDOR_SPEC_IND, /*! Vendor specific event */ +}; + +#define DM_CBACK_END DM_VENDOR_SPEC_IND /*! DM callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection identifier */ +typedef uint8_t dmConnId_t; + +/*! Configuration structure */ +typedef struct +{ + uint8_t dummy; +} dmCfg_t; + +/*! LTK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + uint8_t rand[SMP_RAND8_LEN]; + uint16_t ediv; +} dmSecLtk_t; + +/*! IRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; + bdAddr_t bdAddr; + uint8_t addrType; +} dmSecIrk_t; + +/*! CSRK data type */ +typedef struct +{ + uint8_t key[SMP_KEY_LEN]; +} dmSecCsrk_t; + +/*! union of key types */ +typedef union +{ + dmSecLtk_t ltk; + dmSecIrk_t irk; + dmSecCsrk_t csrk; +} dmSecKey_t; + +/*! Data type for DM_SEC_PAIR_CMPL_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecPairCmplIndEvt_t; + +/*! Data type for DM_SEC_ENCRYPT_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t usingLtk; /*! TRUE if connection encrypted with LTK */ +} dmSecEncryptIndEvt_t; + +/*! Data type for DM_SEC_AUTH_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bool_t oob; /*! Out-of-band data requested */ + bool_t display; /*! TRUE if pin is to be displayed */ +} dmSecAuthReqIndEvt_t; + +/*! Data type for DM_SEC_PAIR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ + bool_t oob; /*! Out-of-band pairing data present or not present */ + uint8_t iKeyDist; /*! Initiator key distribution flags */ + uint8_t rKeyDist; /*! Responder key distribution flags */ +} dmSecPairIndEvt_t; + +/*! Data type for DM_SEC_SLAVE_REQ_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t auth; /*! Authentication and bonding flags */ +} dmSecSlaveIndEvt_t; + +/*! Data type for DM_SEC_KEY_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + dmSecKey_t keyData; /*! Key data */ + uint8_t type; /*! Key type */ + uint8_t secLevel; /*! Security level of pairing when key was exchanged */ + uint8_t encKeyLen; /*! Length of encryption key used when data was transferred */ +} dmSecKeyIndEvt_t; + +/*! Data type for DM_SEC_COMPARE_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Confirm value */ +} dmSecCnfIndEvt_t; + +/*! Data type for DM_SEC_KEYPRESS_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t notificationType; /*! Type of keypress notification */ +} dmSecKeypressIndEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t confirm[SMP_CONFIRM_LEN]; /*! Local confirm value */ + uint8_t random[SMP_RAND_LEN]; /*! Local random value */ +} dmSecOobCalcIndEvt_t; + +/*! Data type for DM_ADV_NEW_ADDR_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + bdAddr_t addr; /*! New resolvable private address */ + bool_t firstTime; /*! TRUE when address is generated for the first time */ +} dmAdvNewAddrIndEvt_t; + +/* Data structure for DM_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t numSets; /*! Number of advertising sets */ + uint8_t advHandle[DM_NUM_ADV_SETS];/*! Advertising handle array */ +} dmAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_START_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStartEvt_t; + +/* Data structure for DM_PER_ADV_SET_STOP_IND */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header */ + uint8_t advHandle; /*! Advertising handle */ +} dmPerAdvSetStopEvt_t; + +/*! Union of DM callback event data types */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Common header */ + /*! common header used by DM_RESET_CMPL_IND */ + /*! common header used by DM_ADV_START_IND */ + /*! common header used by DM_ADV_STOP_IND */ + dmAdvNewAddrIndEvt_t advNewAddr; /*! DM_ADV_NEW_ADDR_IND */ + /*! common header used by DM_SCAN_START_IND */ + /*! common header used by DM_SCAN_STOP_IND */ + hciLeAdvReportEvt_t scanReport; /*! DM_SCAN_REPORT_IND */ + hciLeConnCmplEvt_t connOpen; /*! DM_CONN_OPEN_IND */ + hciDisconnectCmplEvt_t connClose; /*! DM_CONN_CLOSE_IND */ + hciLeConnUpdateCmplEvt_t connUpdate; /*! DM_CONN_UPDATE_IND */ + dmSecPairCmplIndEvt_t pairCmpl; /*! DM_SEC_PAIR_CMPL_IND */ + /*! common header used by DM_SEC_PAIR_FAIL_IND */ + dmSecEncryptIndEvt_t encryptInd; /*! DM_SEC_ENCRYPT_IND */ + /*! common header used by DM_SEC_ENCRYPT_FAIL_IND */ + dmSecAuthReqIndEvt_t authReq; /*! DM_SEC_AUTH_REQ_IND */ + dmSecKeyIndEvt_t keyInd; /*! DM_SEC_KEY_IND */ + hciLeLtkReqEvt_t ltkReqInd; /*! DM_SEC_LTK_REQ_IND */ + dmSecPairIndEvt_t pairInd; /*! DM_SEC_PAIR_IND */ + dmSecSlaveIndEvt_t slaveInd; /*! DM_SEC_SLAVE_REQ_IND */ + dmSecOobCalcIndEvt_t oobCalcInd; /*! DM_SEC_CALC_OOB_IND */ + secEccMsg_t eccMsg; /*! DM_SEC_ECC_KEY_IND */ + dmSecCnfIndEvt_t cnfInd; /*! DM_SEC_COMPARE_IND */ + dmSecKeypressIndEvt_t keypressInd; /*! DM_SEC_KEYPRESS_IND */ + /*! common header used by DM_PRIV_RESOLVED_ADDR_IND */ + hciReadRssiCmdCmplEvt_t readRssi; /*! DM_CONN_READ_RSSI_IND */ + hciLeAddDevToResListCmdCmplEvt_t addDevToResList; /*! DM_PRIV_ADD_DEV_TO_RES_LIST_IND */ + hciLeRemDevFromResListCmdCmplEvt_t remDevFromResList;/*! DM_PRIV_REM_DEV_FROM_RES_LIST_IND */ + hciLeClearResListCmdCmplEvt_t clearResList; /*! DM_PRIV_CLEAR_RES_LIST_IND */ + hciLeReadPeerResAddrCmdCmplEvt_t readPeerResAddr; /*! DM_PRIV_READ_PEER_RES_ADDR_IND */ + hciLeReadLocalResAddrCmdCmplEvt_t readLocalResAddr; /*! DM_PRIV_READ_LOCAL_RES_ADDR_IND */ + hciLeSetAddrResEnableCmdCmplEvt_t setAddrResEnable; /*! DM_PRIV_SET_ADDR_RES_ENABLE_IND */ + hciLeRemConnParamReqEvt_t remConnParamReq; /*! DM_REM_CONN_PARAM_REQ_IND */ + hciLeDataLenChangeEvt_t dataLenChange; /*! DM_CONN_DATA_LEN_CHANGE_IND */ + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthTo; /*! DM_CONN_WRITE_AUTH_TO_IND */ + hciAuthPayloadToExpiredEvt_t authToExpired; /*! DM_CONN_AUTH_TO_EXPIRED_IND */ + hciLeReadPhyCmdCmplEvt_t readPhy; /*! DM_PHY_READ_IND */ + hciLeSetDefPhyCmdCmplEvt_t setDefPhy; /*! DM_PHY_SET_DEF_IND */ + hciLePhyUpdateEvt_t phyUpdate; /*! DM_PHY_UPDATE_IND */ + dmAdvSetStartEvt_t advSetStart; /*! DM_ADV_SET_START_IND */ + hciLeAdvSetTermEvt_t advSetStop; /*! DM_ADV_SET_STOP_IND */ + hciLeScanReqRcvdEvt_t scanReqRcvd; /*! DM_SCAN_REQ_RCVD_IND */ + /*! common header used by DM_EXT_SCAN_START_IND */ + /*! common header used by DM_EXT_SCAN_STOP_IND */ + hciLeExtAdvReportEvt_t extScanReport; /*! DM_EXT_SCAN_REPORT_IND */ + dmPerAdvSetStartEvt_t perAdvSetStart; /*! DM_PER_ADV_SET_START_IND */ + dmPerAdvSetStopEvt_t perAdvSetStop; /*! DM_PER_ADV_SET_STOP_IND */ + hciLePerAdvSyncEstEvt_t perAdvSyncEst; /*! DM_PER_ADV_SYNC_EST_IND */ + hciLePerAdvSyncLostEvt_t perAdvSyncLost; /*! DM_PER_ADV_SYNC_LOST_IND */ + hciLePerAdvReportEvt_t perAdvReport; /*! DM_PER_ADV_REPORT_IND */ + hciLeReadRemoteFeatCmplEvt_t readRemoteFeat; /*! DM_REMOTE_FEATURES_IND */ + /*! common header used by DM_ERROR_IND */ + hciVendorSpecEvt_t vendorSpec; /*! DM_VENDOR_SPEC_IND */ +} dmEvt_t; + +/*! Data type for DmSecSetOob */ +typedef struct +{ + uint8_t localRandom[SMP_RAND_LEN]; /*! Random value of the local device */ + uint8_t localConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the local device */ + uint8_t peerRandom[SMP_RAND_LEN]; /*! Random value of the peer device */ + uint8_t peerConfirm[SMP_CONFIRM_LEN]; /*! Confirm value of the peer device */ +} dmSecLescOobCfg_t; + +/*! Callback type */ +typedef void (*dmCback_t)(dmEvt_t *pDmEvt); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmRegister + * + * \brief Register a callback with DM for scan and advertising events. + * + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRegister(dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmFindAdType + * + * \brief Find an advertising data element in the given advertising or scan response data. + * + * \param adType Advertising data element type to find. + * \param dataLen Data length. + * \param pData Pointer to advertising or scan response data. + * + * \return Pointer to the advertising data element byte array or NULL if not found. + */ +/*************************************************************************************************/ +uint8_t *DmFindAdType(uint8_t adType, uint16_t dataLen, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvInit + * + * \brief Initialize DM legacy advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtAdvInit + * + * \brief Initialize DM extended advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtAdvInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeLeg + * + * \brief Whether DM advertising is in legacy mode. + * + * \return TRUE if DM advertising is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvModeExt + * + * \brief Whether DM advertising is in extended mode. + * + * \return TRUE if DM advertising is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvConfig + * + * \brief Set the advertising parameters using the given advertising type, and peer address. + * + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param peerAddrType Peer address type. + * \param pPeerAddr Peer address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvConfig(uint8_t advHandle, uint8_t advType, uint8_t peerAddrType, uint8_t *pPeerAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetData + * + * \brief Set the advertising or scan response data to the given data. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param location Data location. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetData(uint8_t advHandle, uint8_t op, uint8_t location, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStart + * + * \brief Start advertising using the given advertising set and duration. + * + * \param numSets Number of advertising sets to enable. + * \param advHandle Advertising handle array. + * \param duration Advertising duration (in milliseconds) array. + * \param maxEaEvents Maximum number of extended advertising events array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStart(uint8_t numSets, uint8_t *pAdvHandles, uint16_t *pDuration, uint8_t *pMaxEaEvents); + +/*************************************************************************************************/ +/*! + * \fn DmAdvStop + * + * \brief Stop advertising for the given advertising set. If the number of sets is set to 0 + * then all advertising sets are disabled. + * + * \param numSets Number of advertising sets to disable. + * \param pAdvHandles Advertising handles array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvStop(uint8_t numSets, uint8_t *pAdvHandles); + +/*************************************************************************************************/ +/*! + * \fn DmAdvRemoveAdvSet + * + * \brief Remove an advertising set. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvRemoveAdvSet(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvClearAdvSets + * + * \brief Clear advertising sets. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvClearAdvSets(void); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvConfig + * + * \brief Set the advertising parameters for periodic advertising. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvConfig(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetData + * + * \brief Set the advertising data to the given data for periodic advertising. + * + * \param advHandle Advertising handle. + * \param op Data operation. + * \param len Length of the data. Maximum length is 236 bytes. + * \param pData Pointer to the data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetData(uint8_t advHandle, uint8_t op, uint8_t len, uint8_t *pData); + +/*************************************************************************************************/ +/*! +* \fn DmPerAdvStart + * + * \brief Start periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStart(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvStop + * + * \brief Stop periodic advertising for the advertising set specified by the advertising handle. + * + * \param advHandle Advertising handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvStop(uint8_t advHandle); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetChannelMap + * + * \brief Include or exclude certain channels from the advertising channel map. + * + * \param advHandle Advertising handle. + * \param channelMap Advertising channel map. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetChannelMap(uint8_t advHandle, uint8_t channelMap); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAddrType + * + * \brief Set the local address type used while advertising. This function can be used to + * configure advertising to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetAdValue + * + * \brief Set the value of an advertising data element in the given advertising or + * scan response data. If the element already exists in the data then it is replaced + * with the new value. If the element does not exist in the data it is appended + * to it, space permitting. + * + * \param adType Advertising data element type. + * \param len Length of the value. Maximum length is 29 bytes. + * \param pValue Pointer to the value. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetAdValue(uint8_t adType, uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, + uint8_t *pAdvData, uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetName + * + * \brief Set the device name in the given advertising or scan response data. If the + * name can only fit in the data if it is shortened, the name is shortened + * and the AD type is changed to DM_ADV_TYPE_SHORT_NAME. + * + * \param len Length of the name. Maximum length is 29 bytes. + * \param pValue Pointer to the name in UTF-8 format. + * \param pAdvDataLen Advertising or scan response data length. The new length is returned + * in this parameter. + * \param pAdvData Pointer to advertising or scan response data. + * \param advDataBufLen Length of the advertising or scan response data buffer maintained by + * Application. + * + * \return TRUE if the element was successfully added to the data, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmAdvSetName(uint8_t len, uint8_t *pValue, uint16_t *pAdvDataLen, uint8_t *pAdvData, + uint16_t advDataBufLen); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetRandAddr + * + * \brief Set the random device address for a given advertising set. + * + * \param advHandle Advertising handle. + * \param pAddr Random device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetRandAddr(uint8_t advHandle, const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvUseLegacyPdu + * + * \brief Set whether or not to use legacy advertising PDUs with extended advertising. + * + * \param advHandle Advertising handle. + * \param useLegacyPdu Whether to use legacy advertising PDUs (default value is TRUE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvUseLegacyPdu(uint8_t advHandle, bool_t useLegacyPdu); + +/*************************************************************************************************/ +/*! + * \fn DmAdvOmitAdvAddr + * + * \brief Set whether or not to omit advertiser�s address from all PDUs (anonymous advertising). + * + * \param advHandle Advertising handle. + * \param omitAdvAddr Whether to omit advertiser�s address from all PDUs (default value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvOmitAdvAddr(uint8_t advHandle, bool_t omitAdvAddr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * \param advTxPwr Advertising tx power (127 = no preference). + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr, int8_t advTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetPhyParam + * + * \brief Set extended advertising PHY parameters. + * + * \param advHandle Advertising handle. + * \param priAdvPhy Primary advertising Phy. + * \param secAdvMaxSkip Maximum advertising events Controller can skip before sending AUX_ADV_IND + * on secondary advertising channel (0 = AUX_ADV_IND will be sent prior to + * next advertising event). + * \param secAdvPhy Secondary advertising Phy. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetPhyParam(uint8_t advHandle, uint8_t priAdvPhy, uint8_t secAdvMaxSkip, uint8_t secAdvPhy); + +/*************************************************************************************************/ +/*! + * \fn DmAdvScanReqNotifEnable + * + * \brief Set scan request notification enable. + * + * \param advHandle Advertising handle. + * \param scanReqNotifEna Scan request notification enable. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvScanReqNotifEnable(uint8_t advHandle, bool_t scanReqNotifEna); + +/*************************************************************************************************/ +/*! + * \fn DmAdvSetfragPref + * + * \brief Set fragment preference for advertising data. + * + * \param advHandle Advertising handle. + * \param fragPref Fragment preference. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvSetFragPref(uint8_t advHandle, uint8_t fragPref); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvSetInterval + * + * \brief Set the minimum and maximum advertising intervals for periodic advertising. + * + * \param advHandle Advertising handle. + * \param intervalMin Minimum advertising interval. + * \param intervalMax Maximum advertising interval. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax); + +/*************************************************************************************************/ +/*! + * \fn DmPerAdvIncTxPwr + * + * \brief Set whether or not to include TxPower in extended header of advertising PDU for + * periodic advertising. + * + * \param advHandle Advertising handle. + * \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default + * value is FALSE). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPerAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivInit + * + * \brief Initialize private advertising. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStart + * + * \brief Start using a private resolvable address. + * + * \param changeInterval Interval between automatic address changes, in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStart(uint16_t changeInterval); + +/*************************************************************************************************/ +/*! + * \fn DmAdvPrivStop + * + * \brief Stop using a private resolvable address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAdvPrivStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanInit + * + * \brief Initialize DM legacy scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtScanInit + * + * \brief Initialize DM extended scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtScanInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeLeg + * + * \brief Whether DM scanning is in legacy mode. + * + * \return TRUE if DM scanning is in legacy mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeLeg(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanModeExt + * + * \brief Whether DM scanning is in extended mode. + * + * \return TRUE if DM scanning is in extended mode. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmScanModeExt(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanStart + * + * \brief Start scanning on the given PHYs. + * + * \param scanPhys Scanner PHYs. + * \param mode Discoverability mode. + * \param pScanType Scan type array. + * \param filterDup Filter duplicates. Set to TRUE to filter duplicate responses received + * from the same device. Set to FALSE to receive all responses. + * \param duration The scan duration, in milliseconds. If set to zero or both duration and + * period set to non-zero, scanning will continue until DmScanStop() is called. + * \param period The scan period, in 1.28 sec units (only applicable to AE). If set to zero, + * periodic scanning is disabled. + * + * \return None. + */ + /*************************************************************************************************/ +void DmScanStart(uint8_t scanPhys, uint8_t mode, const uint8_t *pScanType, bool_t filterDup, + uint16_t duration, uint16_t period); + +/*************************************************************************************************/ +/*! + * \fn DmScanStop + * + * \brief Stop scanning. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanStop(void); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStart + * + * \brief Synchronize with periodic advertising from the given advertisier, and start receiving + * periodic advertising packets. + * + * \param filterPolicy Filter policy. + * \param advSid Advertising SID. + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param skip Number of periodic advertising packets that can be skipped after + * successful receive. + * \param syncTimeout Synchronization timeout. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStart(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, const uint8_t *pAdvAddr, + uint16_t skip, uint16_t syncTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmSyncStop + * + * \brief Stop reception of the periodic advertising identified by the given sync handle. + * + * \param syncHandle Sync handle. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncStop(uint16_t syncHandle); + +/*************************************************************************************************/ +/*! + * \fn DmSyncCancel + * + * \brief Cancel creation of a sync while it's pending. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSyncCancel(void); + +/*************************************************************************************************/ +/*! + * \fn DmAddDeviceToPerAdvList + * + * \brief Add device to periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmAddDeviceToPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmRemoveDeviceFromPerAdvList + * + * \brief DM remove device from periodic advertiser list. + * + * \param advAddrType Advertiser address type. + * \param pAdvAddr Advertiser address. + * \param advSid Advertising SID. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoveDeviceFromPerAdvList(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); + +/*************************************************************************************************/ +/*! + * \fn DmClearPerAdvList + * + * \brief DM clear periodic advertiser list. + * + * \return None. + */ +/*************************************************************************************************/ +void DmClearPerAdvList(void); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetInterval + * + * \brief Set the scan interval and window for the specified PHYs. + * + * \param scanPhys Scanning PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetInterval(uint8_t scanPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmScanSetAddrType + * + * \brief Set the local address type used while scanning. This function can be used to + * configure scanning to use a random address. + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmScanSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnInit + * + * \brief Initialize DM connection manager. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnMasterInit + * + * \brief Initialize DM connection manager for operation as legacy master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnMasterInit + * + * \brief Initialize DM connection manager for operation as extended master. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnSlaveInit + * + * \brief Initialize DM connection manager for operation as legacy slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSlaveInit + * + * \brief Initialize DM connection manager for operation as extended slave. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmConnRegister + * + * \brief Register with the DM connection manager. + * + * \param clientId The client identifier. + * \param cback Client callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnRegister(uint8_t clientId, dmCback_t cback); + +/*************************************************************************************************/ +/*! + * \fn DmConnOpen + * + * \brief Open a connection to a peer device with the given address. + * + * \param clientId The client identifier. + * \param initPhys Initiator PHYs. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnOpen(uint8_t clientId, uint8_t initPhys, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnClose + * + * \brief Close the connection with the give connection identifier. + * + * \param clientId The client identifier. + * \param connId Connection identifier. + * \param reason Reason connection is being closed. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnClose(uint8_t clientId, dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnAccept + * + * \brief Accept a connection from the given peer device by initiating directed advertising. + * + * \param clientId The client identifier. + * \param advHandle Advertising handle. + * \param advType Advertising type. + * \param duration Advertising duration (in ms). + * \param maxEaEvents Maximum number of extended advertising events. + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return Connection identifier. + */ +/*************************************************************************************************/ +dmConnId_t DmConnAccept(uint8_t clientId, uint8_t advHandle, uint8_t advType, uint16_t duration, + uint8_t maxEaEvents, uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmConnUpdate + * + * \brief Update the connection parameters of an open connection + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnUpdate(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetScanInterval + * + * \brief Set the scan interval and window for connections to be created with DmConnOpen(). + * + * \param scanInterval The scan interval. + * \param scanWindow The scan window. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetScanInterval(uint16_t scanInterval, uint16_t scanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmExtConnSetScanInterval + * + * \brief Set the scan interval and window for extended connections to be created with + * DmConnOpen(). + * + * \param initPhy Initiator PHYs. + * \param pScanInterval Scan interval array. + * \param pScanWindow Scan window array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetScanInterval(uint8_t initPhys, uint16_t *pScanInterval, uint16_t *pScanWindow); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetConnSpec + * + * \brief Set the connection spec parameters for connections to be created with DmConnOpen(). + * + * \param pConnSpec Connection spec parameters. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetConnSpec(hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetExtConnSpec + * + * \brief Set the extended connection spec parameters for extended connections to be created + * with DmConnOpen(). + * + * \param initPhys The initiator PHYs. + * \param pConnSpec Connection spec parameters array. + * + * \return None. + */ +/*************************************************************************************************/ +void DmExtConnSetConnSpec(uint8_t initPhys, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetAddrType + * + * \brief Set the local address type used for connections created with DmConnOpen(). + * + * \param addrType Address type. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetIdle + * + * \brief Configure a bit in the connection idle state mask as busy or idle. + * + * \param connId Connection identifier. + * \param idleMask Bit in the idle state mask to configure. + * \param idle DM_CONN_BUSY or DM_CONN_IDLE. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetIdle(dmConnId_t connId, uint16_t idleMask, uint8_t idle); + +/*************************************************************************************************/ +/*! + * \fn DmConnCheckIdle + * + * \brief Check if a connection is idle. + * + * \param connId Connection identifier. + * + * \return Zero if connection is idle, nonzero if busy. + */ +/*************************************************************************************************/ +uint16_t DmConnCheckIdle(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnReadRssi + * + * \brief Read RSSI of a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnReadRssi(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqReply + * + * \brief Reply to the HCI remote connection parameter request event. This command is used to + * indicate that the Host has accepted the remote device�s request to change connection + * parameters. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqReply(dmConnId_t connId, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmRemoteConnParamReqNegReply + * + * \brief Negative reply to the HCI remote connection parameter request event. This command + * is used to indicate that the Host has rejected the remote device�s request to change + * connection parameters. + * + * \param connId Connection identifier. + * \param reason Reason for rejection. + * + * \return None. + */ +/*************************************************************************************************/ +void DmRemoteConnParamReqNegReply(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmConnSetDataLen + * + * \brief Set data length for a given connection. + * + * \param connId Connection identifier. + * \param txOctets Maximum number of payload octets for a Data PDU. + * \param txTime Maximum number of microseconds for a Data PDU. + * + * \return None. + */ +/*************************************************************************************************/ +void DmConnSetDataLen(dmConnId_t connId, uint16_t txOctets, uint16_t txTime); + +/*************************************************************************************************/ +/*! + * \fn DmWriteAuthPayloadTimeout + * + * \brief Set authenticated payload timeout for a given connection. + * + * \param connId Connection identifier. + * \param timeout Timeout period in units of 10ms + * + * \return None. + */ +/*************************************************************************************************/ +void DmWriteAuthPayloadTimeout(dmConnId_t connId, uint16_t timeout); + +/*************************************************************************************************/ +/*! + * \fn DmReadPhy + * + * \brief Read the current transmitter PHY and receiver PHY for a given connection. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadPhy(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSetDefaultPhy + * + * \brief Set the preferred values for the transmitter PHY and receiver PHY for all subsequent + * connections. + * + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetDefaultPhy(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); + +/*************************************************************************************************/ +/*! + * \fn DmSetPhy + * + * \brief Set the PHY preferences for a given connection. + * + * \param connId Connection identifier. + * \param allPhys All PHYs preferences. + * \param txPhys Preferred transmitter PHYs. + * \param rxPhys Preferred receiver PHYs. + * \param phyOptions PHY options. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSetPhy(dmConnId_t connId, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); + +/*************************************************************************************************/ +/*! + * \fn DmDevReset + * + * \brief Reset the device. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevReset(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevRole + * + * \brief Return the device role indicating master or slave. + * + * \return Device role. + */ +/*************************************************************************************************/ +uint8_t DmDevRole(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetRandAddr + * + * \brief Set the random address to be used by the local device. + * + * \param pAddr Random address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevSetRandAddr(uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListAdd + * + * \brief Add a peer device to the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListAdd(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListRemove + * + * \brief Remove a peer device from the white list. Note that this function cannot be called + * while advertising, scanning, or connecting with white list filtering active. + * + * \param addrType Address type. + * \param pAddr Peer device address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListRemove(uint8_t addrType, uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn DmDevWhiteListClear + * + * \brief Clear the white list. Note that this function cannot be called while + * advertising, scanning, or connecting with white list filtering active. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevWhiteListClear(void); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetFilterPolicy + * + * \brief Set the Advertising, Scanning or Initiator filter policy. + * + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetFilterPolicy(uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevSetExtFilterPolicy + * + * \brief Set the Advertising filter policy for the given advertising, Scanning or Initiator + * filter policy. + * + * \param advHandle Advertising handle. + * \param mode Policy mode. + * \param policy Filter policy. + * + * \return TRUE if the filter policy was successfully set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmDevSetExtFilterPolicy(uint8_t advHandle, uint8_t mode, uint8_t policy); + +/*************************************************************************************************/ +/*! + * \fn DmDevVsInit + * + * \brief Vendor-specific controller initialization function. + * + * \param param Vendor-specific parameter. + * + * \return None. + */ +/*************************************************************************************************/ +void DmDevVsInit(uint8_t param); + +/*************************************************************************************************/ +/*! + * \fn DmSecInit + * + * \brief Initialize DM security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecLescInit + * + * \brief Initialize DM LE Secure Connections security. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLescInit(void); + +/*************************************************************************************************/ +/*! +* \fn DmPhyInit +* +* \brief Initialize DM PHY. +* +* \return None. +*/ +/*************************************************************************************************/ +void DmPhyInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairReq + * + * \brief This function is called by a master device to initiate pairing. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairReq(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecPairRsp + * + * \brief This function is called by a slave device to proceed with pairing after a + * DM_SEC_PAIR_IND event is received. + * + * \param connId DM connection ID. + * \param oob Out-of-band pairing data present or not present. + * \param auth Authentication and bonding flags. + * \param iKeyDist Initiator key distribution flags. + * \param rKeyDist Responder key distribution flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecPairRsp(dmConnId_t connId, bool_t oob, uint8_t auth, uint8_t iKeyDist, uint8_t rKeyDist); + +/*************************************************************************************************/ +/*! + * \fn DmSecCancelReq + * + * \brief This function is called to cancel the pairing process. + * + * \param connId DM connection ID. + * \param reason Failure reason. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCancelReq(dmConnId_t connId, uint8_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmSecAuthRsp + * + * \brief This function is called in response to a DM_SEC_AUTH_REQ_IND event to provide + * PIN or OOB data during pairing. + * + * \param connId DM connection ID. + * \param authDataLen Length of PIN or OOB data. + * \param pAuthData pointer to PIN or OOB data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecAuthRsp(dmConnId_t connId, uint8_t authDataLen, uint8_t *pAuthData); + +/*************************************************************************************************/ +/*! + * \fn DmSecSlaveReq + * + * \brief This function is called by a slave device to request that the master initiates + * pairing or link encryption. + * + * \param connId DM connection ID. + * \param auth Authentication flags. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSlaveReq(dmConnId_t connId, uint8_t auth); + +/*************************************************************************************************/ +/*! + * \fn DmSecEncryptReq + * + * \brief This function is called by a master device to initiate link encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when LTK was exchanged. + * \param pLtk Pointer to LTK parameter structure. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecEncryptReq(dmConnId_t connId, uint8_t secLevel, dmSecLtk_t *pLtk); + +/*************************************************************************************************/ +/*! + * \fn DmSecLtkRsp + * + * \brief This function is called by a slave in response to a DM_SEC_LTK_REQ_IND event + * to provide the long term key used for encryption. + * + * \param connId DM connection ID. + * \param keyFound TRUE if key found. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to the key, if found. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecLtkRsp(dmConnId_t connId, bool_t keyFound, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalCsrk + * + * \brief This function sets the local CSRK used by the device. + * + * \param pCsrk Pointer to CSRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalCsrk(uint8_t *pCsrk); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetLocalIrk + * + * \brief This function sets the local IRK used by the device. + * + * \param pCsrk Pointer to IRK. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalIrk(uint8_t *pIrk); + +/*************************************************************************************************/ +/*! + * \fn DmPrivInit + * + * \brief Initialize DM privacy module. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivInit(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivResolveAddr + * + * \brief Resolve a private resolvable address. When complete the client's callback function + * is called with a DM_PRIV_RESOLVED_ADDR_IND event. The client must wait to receive + * this event before executing this function again. + * + * \param pAddr Peer device address. + * \param pIrk The peer's identity resolving key. + * \param param Client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivResolveAddr(uint8_t *pAddr, uint8_t *pIrk, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivAddDevToResList + * + * \brief Add device to resolving list. When complete the client's callback function + * is called with a DM_PRIV_ADD_DEV_TO_RES_LIST_IND event. The client must wait + * to receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: If the local or peer IRK associated with the peer Identity Address is all + * zeros then the LL will use or accept the local or peer Identity Address. + * + * Note: 'enableLlPriv' should be set to TRUE when the last device is being added + * to resolving list to enable address resolution in LL. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param pPeerIrk The peer's identity resolving key. + * \param pLocalIrk The local identity resolving key. + * \param enableLlPriv Set to TRUE to enable address resolution in LL. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivAddDevToResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t *pPeerIrk, + uint8_t *pLocalIrk, bool_t enableLlPriv, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivRemDevFromResList + * + * \brief Remove device from resolving list. When complete the client's callback function + * is called with a DM_PRIV_REM_DEV_FROM_RES_LIST_IND event. The client must wait to + * receive this event before executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param param client-defined parameter returned with callback event. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivRemDevFromResList(uint8_t addrType, const uint8_t *pIdentityAddr, uint16_t param); + +/*************************************************************************************************/ +/*! + * \fn DmPrivClearResList + * + * \brief Clear resolving list. When complete the client's callback function is called with a + * DM_PRIV_CLEAR_RES_LIST_IND event. The client must wait to receive this event before + * executing this function again. + * + * Note: This command cannot be used when address translation is enabled in the LL and: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * Note: Address resolution in LL will be disabled when resolving list's cleared + * successfully. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivClearResList(void); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadPeerResolvableAddr + * + * \brief HCI read peer resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_PEER_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivReadLocalResolvableAddr + * + * \brief Read local resolvable address command. When complete the client's callback + * function is called with a DM_PRIV_READ_LOCAL_RES_ADDR_IND event. The client must + * wait to receive this event before executing this function again. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetAddrResEnable + * + * \brief Enable or disable address resolution in LL. When complete the client's callback + * function is called with a DM_PRIV_SET_ADDR_RES_ENABLE_IND event. The client must + * wait to receive this event before executing this function again. + * + * Note: This command can be used at any time except when: + * - Advertising is enabled + * - Scanning is enabled + * - Create connection command is outstanding + * + * \param enable Set to TRUE to enable address resolution or FALSE to disable it. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetAddrResEnable(bool_t enable); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetResolvablePrivateAddrTimeout + * + * \brief Set resolvable private address timeout command. + * + * \param rpaTimeout Timeout measured in seconds. + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); + +/*************************************************************************************************/ +/*! + * \fn DmPrivSetPrivacyMode + * + * \brief Set privacy mode for a given entry in the resolving list. + * + * \param addrType Peer identity address type. + * \param pIdentityAddr Peer identity address. + * \param mode Privacy mode (by default, network privacy mode is used). + * + * \return None. + */ +/*************************************************************************************************/ +void DmPrivSetPrivacyMode(uint8_t addrType, const uint8_t *pIdentityAddr, uint8_t mode); + +/*************************************************************************************************/ +/*! + * \fn DmLlPrivEnabled + * + * \brief Whether LL Privacy is enabled. + * + * \return TRUE if LL Privacy is enabled. FALSE, otherwise. + */ +/*************************************************************************************************/ +bool_t DmLlPrivEnabled(void); + +/*************************************************************************************************/ +/*! + * \fn DmLlAddrType + * + * \brief Map an address type to a type used by LL. + * + * \param addrType Address type used by Host. + * + * \return Address type used by LL. + */ +/*************************************************************************************************/ +uint8_t DmLlAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmHostAddrType + * + * \brief Map an address type to a type used by Host. + * + * \param addrType Address type used by LL. + * + * \return Address type used by Host. + */ +/*************************************************************************************************/ +uint8_t DmHostAddrType(uint8_t addrType); + +/*************************************************************************************************/ +/*! + * \fn DmSizeOfEvt + * + * \brief Return size of a DM callback event. + * + * \param pDmEvt DM callback event. + * + * \return Size of DM callback event. + */ +/*************************************************************************************************/ +uint16_t DmSizeOfEvt(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateCnf + * + * \brief For internal use only. L2C calls this function to send the result of an L2CAP + * connection update response to DM. + * + * \param handle Connection handle. + * \param reason Connection update response reason code. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateCnf(uint16_t handle, uint16_t reason); + +/*************************************************************************************************/ +/*! + * \fn DmL2cConnUpdateInd + * + * \brief For internal use only. L2C calls this function when it receives a connection update + * request from a peer device. + * + * \param identifier Identifier value. + * \param handle Connection handle. + * \param pConnSpec Connection spec parameters. + * \return None. + */ +/*************************************************************************************************/ +void DmL2cConnUpdateInd(uint8_t identifier, uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn DmConnIdByHandle + * + * \brief For internal use only. Find the connection ID with matching handle. + * + * \param handle Handle to find. + * + * \return Connection ID or DM_CONN_ID_NONE if error. + */ +/*************************************************************************************************/ +dmConnId_t DmConnIdByHandle(uint16_t handle); + +/*************************************************************************************************/ +/*! + * \fn DmConnInUse + * + * \brief For internal use only. Return TRUE if the connection is in use. + * + * \param connId Connection ID. + * + * \return TRUE if the connection is in use, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t DmConnInUse(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddrType + * + * \brief For internal use only. Return the peer address type. + * + * \param connId Connection ID. + * + * \return Peer address type. + */ +/*************************************************************************************************/ +uint8_t DmConnPeerAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnPeerAddr + * + * \brief For internal use only. Return the peer device address. + * + * \param connId Connection ID. + * + * \return Pointer to peer device address. + */ +/*************************************************************************************************/ +uint8_t *DmConnPeerAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddrType + * + * \brief For internal use only. Return the local address type. + * + * \param connId Connection ID. + * + * \return Local address type. + */ +/*************************************************************************************************/ +uint8_t DmConnLocalAddrType(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnLocalAddr + * + * \brief For internal use only. Return the local address. + * + * \param connId Connection ID. + * + * \return Pointer to local address. + */ +/*************************************************************************************************/ +uint8_t *DmConnLocalAddr(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnPeerRpa +* +* \brief For internal use only. Return the peer resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to peer RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnPeerRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! +* \fn DmConnLocalRpa +* +* \brief For internal use only. Return the local resolvable private address (RPA). +* +* \param connId Connection ID. +* +* \return Pointer to local RPA. +*/ +/*************************************************************************************************/ +uint8_t *DmConnLocalRpa(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmConnSecLevel + * + * \brief For internal use only. Return the security level of the connection. + * + * \param connId Connection ID. + * + * \return Security level of the connection. + */ +/*************************************************************************************************/ +uint8_t DmConnSecLevel(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSmpEncryptReq + * + * \brief For internal use only. This function is called by SMP to request encryption. + * + * \param connId DM connection ID. + * \param secLevel Security level of pairing when key was exchanged. + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpEncryptReq(dmConnId_t connId, uint8_t secLevel, uint8_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSmpCbackExec + * + * \brief For internal use only. Execute DM callback from SMP procedures. + * + * \param pDmEvt Pointer to callback event data. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSmpCbackExec(dmEvt_t *pDmEvt); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalCsrk + * + * \brief For internal use only. This function gets the local CSRK used by the device. + * + * \return Pointer to CSRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalCsrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetLocalIrk + * + * \brief For internal use only. This function gets the local IRK used by the device. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalIrk(void); + +/*************************************************************************************************/ +/*! + * \fn DmReadRemoteFeatures + * + * \brief For internal use only. Read the features of the remote device. + * + * \param connId Connection identifier. + * \param pConnSpec Connection specification. + * + * \return None. + */ +/*************************************************************************************************/ +void DmReadRemoteFeatures(dmConnId_t connId); + +/*************************************************************************************************/ +/*! + * \fn DmSecGenerateEccKeyReq + * + * \brief This function generates an ECC key for use with LESC security. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecGenerateEccKeyReq(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetEccKey + * + * \brief This function sets the ECC key for use with LESC security. + * + * \param pKey Pointer to key. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetEccKey(secEccKey_t *pKey); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetEccKey + * + * \brief This function gets the local ECC key for use with LESC security. + * + * \return Pointer to local ECC key. + */ +/*************************************************************************************************/ +secEccKey_t *DmSecGetEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetDebugEccKey + * + * \brief This function sets the ECC key for use with LESC security to standard debug keys values. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetDebugEccKey(void); + +/*************************************************************************************************/ +/*! + * \fn DmSecSetOob + * + * \brief This function configures the DM to use OOB pairing for the given connection. + * The pRand and pConfirm contain the Random and Confirm values exchanged via + * out of band methods. + * + * \param connId ID of the connection + * \param pConfig Pointer to OOB configuration. + * + * \return Pointer to IRK. + */ +/*************************************************************************************************/ +void DmSecSetOob(dmConnId_t connId, dmSecLescOobCfg_t *pConfig); + +/*************************************************************************************************/ +/*! + * \fn DmSecCalcOobReq + * + * \brief This function calculates the local random and confirm values used in LESC OOB pairing. + * The operation's result is posted as a DM_SEC_CALC_OOB_IND event to the application's DM + * callback handler. The local rand and confirm values are exchanged with the peer via + * out-of-band (OOB) methods and passed into the DmSecSetOob after DM_CONN_OPEN_IND. + * + * \param pRand Random value used in calculation. + * \param pPubKeyX X component of the local public key. + * + * \return none. + */ +/*************************************************************************************************/ +void DmSecCalcOobReq(uint8_t *pRand, uint8_t *pPubKeyX); + +/*************************************************************************************************/ +/*! + * \fn DmSecCompareRsp + * + * \brief This function is called by the application in response to a DM_SEC_COMPARE_IND event. + * The valid parameter indicates if the compare value of the DM_SEC_COMPARE_IND was valid. + * + * \param connId ID of the connection + * \param valid TRUE if compare value was valid + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecCompareRsp(dmConnId_t connId, bool_t valid); + +/*************************************************************************************************/ +/*! + * \fn DmSecGetCompareValue + * + * \brief This function returns the 6-digit compare value for the specified 128-bit confirm value. + * + * \param pConfirm Pointer to 128-bit comfirm value. + * + * \return Six-digit compare value. + */ +/*************************************************************************************************/ +uint32_t DmSecGetCompareValue(uint8_t *pConfirm); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h new file mode 100644 index 00000000000..650ecb06461 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/dm_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file dm_handler.h + * + * \brief Interface to DM event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef DM_HANDLER_H +#define DM_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn DmHandlerInit + * + * \brief DM handler init function called during system initialization. + * + * \param handlerID WSF handler ID for DM. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn DmHandler + * + * \brief WSF event handler for DM. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void DmHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* DM_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h new file mode 100644 index 00000000000..30ea3c099bd --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_api.h @@ -0,0 +1,837 @@ +/*************************************************************************************************/ +/*! + * \file hci_api.h + * + * \brief HCI subsystem API. + * + * $Date: 2017-02-09 11:58:21 -0600 (Thu, 09 Feb 2017) $ + * $Revision: 11135 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_API_H +#define HCI_API_H + +#include "wsf_types.h" +#include "hci_defs.h" +#include "wsf_os.h" +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Internal event values for the HCI event and sec callbacks */ +#define HCI_RESET_SEQ_CMPL_CBACK_EVT 0 /*! Reset sequence complete */ +#define HCI_LE_CONN_CMPL_CBACK_EVT 1 /*! LE connection complete */ +#define HCI_LE_ENHANCED_CONN_CMPL_CBACK_EVT 2 /*! LE enhanced connection complete */ +#define HCI_DISCONNECT_CMPL_CBACK_EVT 3 /*! LE disconnect complete */ +#define HCI_LE_CONN_UPDATE_CMPL_CBACK_EVT 4 /*! LE connection update complete */ +#define HCI_LE_CREATE_CONN_CANCEL_CMD_CMPL_CBACK_EVT 5 /*! LE create connection cancel command complete */ +#define HCI_LE_ADV_REPORT_CBACK_EVT 6 /*! LE advertising report */ +#define HCI_READ_RSSI_CMD_CMPL_CBACK_EVT 7 /*! Read RSSI command complete */ +#define HCI_LE_READ_CHAN_MAP_CMD_CMPL_CBACK_EVT 8 /*! LE Read channel map command complete */ +#define HCI_READ_TX_PWR_LVL_CMD_CMPL_CBACK_EVT 9 /*! Read transmit power level command complete */ +#define HCI_READ_REMOTE_VER_INFO_CMPL_CBACK_EVT 10 /*! Read remote version information complete */ +#define HCI_LE_READ_REMOTE_FEAT_CMPL_CBACK_EVT 11 /*! LE read remote features complete */ +#define HCI_LE_LTK_REQ_REPL_CMD_CMPL_CBACK_EVT 12 /*! LE LTK request reply command complete */ +#define HCI_LE_LTK_REQ_NEG_REPL_CMD_CMPL_CBACK_EVT 13 /*! LE LTK request negative reply command complete */ +#define HCI_ENC_KEY_REFRESH_CMPL_CBACK_EVT 14 /*! Encryption key refresh complete */ +#define HCI_ENC_CHANGE_CBACK_EVT 15 /*! Encryption change */ +#define HCI_LE_LTK_REQ_CBACK_EVT 16 /*! LE LTK request */ +#define HCI_VENDOR_SPEC_CMD_STATUS_CBACK_EVT 17 /*! Vendor specific command status */ +#define HCI_VENDOR_SPEC_CMD_CMPL_CBACK_EVT 18 /*! Vendor specific command complete */ +#define HCI_VENDOR_SPEC_CBACK_EVT 19 /*! Vendor specific */ +#define HCI_HW_ERROR_CBACK_EVT 20 /*! Hardware error */ +#define HCI_LE_ADD_DEV_TO_RES_LIST_CMD_CMPL_CBACK_EVT 21 /*! LE add device to resolving list command complete */ +#define HCI_LE_REM_DEV_FROM_RES_LIST_CMD_CMPL_CBACK_EVT 22 /*! LE remove device from resolving command complete */ +#define HCI_LE_CLEAR_RES_LIST_CMD_CMPL_CBACK_EVT 23 /*! LE clear resolving list command complete */ +#define HCI_LE_READ_PEER_RES_ADDR_CMD_CMPL_CBACK_EVT 24 /*! LE read peer resolving address command complete */ +#define HCI_LE_READ_LOCAL_RES_ADDR_CMD_CMPL_CBACK_EVT 25 /*! LE read local resolving address command complete */ +#define HCI_LE_SET_ADDR_RES_ENABLE_CMD_CMPL_CBACK_EVT 26 /*! LE set address resolving enable command complete */ +#define HCI_LE_ENCRYPT_CMD_CMPL_CBACK_EVT 27 /*! LE encrypt command complete */ +#define HCI_LE_RAND_CMD_CMPL_CBACK_EVT 28 /*! LE rand command complete */ +#define HCI_LE_REM_CONN_PARAM_REP_CMD_CMPL_CBACK_EVT 29 /*! LE remote connection parameter request reply complete */ +#define HCI_LE_REM_CONN_PARAM_NEG_REP_CMD_CMPL_CBACK_EVT 30 /*! LE remote connection parameter request negative reply complete */ +#define HCI_LE_READ_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 31 /*! LE read suggested default data length command complete */ +#define HCI_LE_WRITE_DEF_DATA_LEN_CMD_CMPL_CBACK_EVT 32 /*! LE write suggested default data length command complete */ +#define HCI_LE_SET_DATA_LEN_CMD_CMPL_CBACK_EVT 33 /*! LE set data length command complete */ +#define HCI_LE_READ_MAX_DATA_LEN_CMD_CMPL_CBACK_EVT 34 /*! LE read maximum data length command complete */ +#define HCI_LE_REM_CONN_PARAM_REQ_CBACK_EVT 35 /*! LE remote connection parameter request */ +#define HCI_LE_DATA_LEN_CHANGE_CBACK_EVT 36 /*! LE data length change */ +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_CBACK_EVT 37 /*! LE read local P-256 public key */ +#define HCI_LE_GENERATE_DHKEY_CMPL_CBACK_EVT 38 /*! LE generate DHKey complete */ +#define HCI_WRITE_AUTH_PAYLOAD_TO_CMD_CMPL_CBACK_EVT 39 /*! Write authenticated payload timeout command complete */ +#define HCI_AUTH_PAYLOAD_TO_EXPIRED_CBACK_EVT 40 /*! Authenticated payload timeout expired event */ +#define HCI_LE_READ_PHY_CMD_CMPL_CBACK_EVT 41 /*! LE read phy command complete */ +#define HCI_LE_SET_DEF_PHY_CMD_CMPL_CBACK_EVT 42 /*! LE set default phy command complete */ +#define HCI_LE_PHY_UPDATE_CMPL_CBACK_EVT 43 /*! LE phy update complete */ +#define HCI_LE_EXT_ADV_REPORT_CBACK_EVT 44 /*! LE extended advertising report */ +#define HCI_LE_SCAN_TIMEOUT_CBACK_EVT 45 /*! LE scan timeout event */ +#define HCI_LE_ADV_SET_TERM_CBACK_EVT 46 /*! LE advertising set terminated event */ +#define HCI_LE_SCAN_REQ_RCVD_CBACK_EVT 47 /*! LE scan request received event */ +#define HCI_LE_PER_ADV_SYNC_EST_CBACK_EVT 48 /*! LE periodic advertising sync established event */ +#define HCI_LE_PER_ADV_REPORT_CBACK_EVT 49 /*! LE periodic advertising report event */ +#define HCI_LE_PER_ADV_SYNC_LOST_CBACK_EVT 50 /*! LE periodic advertising synch lost event */ +#define HCI_LE_CH_SEL_ALGO_CBACK_EVT 51 /*! LE channel selection algorithm event */ +#define HCI_LE_SCAN_ENABLE_CMPL_CBACK_EVT 52 /*! LE scan enable complete event */ +#define HCI_LE_ADV_ENABLE_CMPL_CBACK_EVT 53 /*! LE advertise enable complete event */ +#define HCI_LE_EXT_SCAN_ENABLE_CMPL_CBACK_EVT 54 /*! LE extended scan enable complete event */ +#define HCI_LE_EXT_ADV_ENABLE_CMPL_CBACK_EVT 55 /*! LE extended advertise enable complete event */ +#define HCI_LE_PER_ADV_ENABLE_CMPL_CBACK_EVT 56 /*! LE periodic advertise enable complete event */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection specification type */ +typedef struct +{ + uint16_t connIntervalMin; /*!< Minimum connection interval. */ + uint16_t connIntervalMax; /*!< Maximum connection interval. */ + uint16_t connLatency; /*!< Connection latency. */ + uint16_t supTimeout; /*!< Supervision timeout. */ + uint16_t minCeLen; /*!< Minimum CE length. */ + uint16_t maxCeLen; /*!< Maximum CE length. */ +} hciConnSpec_t; + +/*! Initiating parameters */ +typedef struct +{ + uint8_t filterPolicy; /*!< Scan filter policy. */ + uint8_t ownAddrType; /*!< Address type used by this device. */ + uint8_t peerAddrType; /*!< Address type used for peer device. */ + const uint8_t *pPeerAddr; /*!< Address of peer device. */ + uint8_t initPhys; /*!< Initiating PHYs. */ +} hciExtInitParam_t; + +/*! Initiating scan parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ +} hciExtInitScanParam_t; + +/*! Extended advertising parameters */ +typedef struct +{ + uint16_t advEventProp; /*! Advertising Event Properties. */ + uint32_t priAdvInterMin; /*! Primary Advertising Interval Minimum. */ + uint32_t priAdvInterMax; /*! Primary Advertising Interval Maximum. */ + uint8_t priAdvChanMap; /*! Primary Advertising Channel Map. */ + uint8_t ownAddrType; /*! Own Address Type. */ + uint8_t peerAddrType; /*! Peer Address Type. */ + uint8_t *pPeerAddr; /*! Peer Address. */ + uint8_t advFiltPolicy; /*! Advertising Filter Policy. */ + int8_t advTxPwr; /*! Advertising Tx Power. */ + uint8_t priAdvPhy; /*! Primary Advertising PHY. */ + uint8_t secAdvMaxSkip; /*! Secondary Advertising Maximum Skip. */ + uint8_t secAdvPhy; /*! Secondary Advertising PHY. */ + uint8_t advSetId; /*! Advertising set ID. */ + uint8_t scanReqNotifEna; /*! Scan Request Notification Enable. */ +} hciExtAdvParam_t; + +/*! Extended advertising enable parameters */ +typedef struct +{ + uint8_t advHandle; /*! Advertising handle. */ + uint16_t duration; /*! Advertising duration in 10 ms units. */ + uint8_t maxEaEvents; /*! Maximum number of extended advertising events. */ +} hciExtAdvEnableParam_t; + +/*! Extended scanning parameters */ +typedef struct +{ + uint16_t scanInterval; /*! Scan interval. */ + uint16_t scanWindow; /*! Scan window. */ + uint8_t scanType; /*! Scan type. */ +} hciExtScanParam_t; + +/*! LE connection complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t role; + uint8_t addrType; + bdAddr_t peerAddr; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; + uint8_t clockAccuracy; + + /* enhanced fields */ + bdAddr_t localRpa; + bdAddr_t peerRpa; +} hciLeConnCmplEvt_t; + +/*! Disconnect complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t reason; +} hciDisconnectCmplEvt_t; + +/*! LE connection update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint16_t connInterval; + uint16_t connLatency; + uint16_t supTimeout; +} hciLeConnUpdateCmplEvt_t; + +/*! LE create connection cancel command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeCreateConnCancelCmdCmplEvt_t; + +/*! LE advertising report event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t *pData; + uint8_t len; + int8_t rssi; + uint8_t eventType; + uint8_t addrType; + bdAddr_t addr; + + /* direct fields */ + uint8_t directAddrType; + bdAddr_t directAddr; +} hciLeAdvReportEvt_t; + +/*! LE extended advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t eventType; /*!< Event type. */ + uint8_t addrType; /*!< Address type. */ + bdAddr_t addr; /*!< Address. */ + uint8_t priPhy; /*!< Primary PHY. */ + uint8_t secPhy; /*!< Secondary PHY. */ + uint8_t advSid; /*!< Advertising SID. */ + int8_t txPower; /*!< Tx Power. */ + int8_t rssi; /*!< RSSI. */ + int16_t perAdvInter; /*!< Periodic advertising interval. */ + uint8_t directAddrType; /*!< Directed address type. */ + bdAddr_t directAddr; /*!< Directed address. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLeExtAdvReportEvt_t; + +/*! LE scan timeout */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ +} hciLeScanTimeoutEvt_t; + +/*! LE advertising set terminated */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t numComplEvts; /*!< Number of completed extended advertising events. */ +} hciLeAdvSetTermEvt_t; + +/*! LE scan request received */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t advHandle; /*!< Advertising handle. */ + uint8_t scanAddrType; /*!< Scanner address type. */ + bdAddr_t scanAddr; /*!< Scanner address. */ +} hciLeScanReqRcvdEvt_t; + +/*! LE periodic advertising sync established */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint8_t status; /*!< Status. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t advSid; /*!< Advertising SID. */ + uint8_t advAddrType; /*!< Advertiser address type. */ + bdAddr_t advAddr; /*!< Advertiser address. */ + uint8_t advPhy; /*!< Advertiser PHY. */ + uint16_t perAdvInterval; /*!< Periodic advertising interval. */ + uint8_t clockAccuracy; /*!< Advertiser clock accuracy. */ +} hciLePerAdvSyncEstEvt_t; + +/*! LE periodic advertising report */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ + uint8_t txPower; /*!< Tx power. */ + uint8_t rssi; /*!< RSSI. */ + uint8_t unused; /*!< Intended to be used in a future feature. */ + uint8_t status; /*!< Data status. */ + uint8_t len; /*!< Data buffer length. */ + uint8_t *pData; /*!< Data buffer. */ +} hciLePerAdvReportEvt_t; + +/*! LE periodic advertising synch lost */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t syncHandle; /*!< Sync handle. */ +} hciLePerAdvSyncLostEvt_t; + +/*! LE channel selection algorithm */ +typedef struct +{ + wsfMsgHdr_t hdr; /*!< Event header. */ + uint16_t handle; /*!< Connection handle. */ + uint8_t chSelAlgo; /*!< Channel selection algorithm */ +} hciLeChSelAlgoEvt_t; + +/*! Read RSSI command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + int8_t rssi; +} hciReadRssiCmdCmplEvt_t; + +/*! LE Read channel map command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t chanMap[HCI_CHAN_MAP_LEN]; +} hciReadChanMapCmdCmplEvt_t; + +/*! Read transmit power level command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t handle; + int8_t pwrLvl; +} hciReadTxPwrLvlCmdCmplEvt_t; + +/*! Read remote version information complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t version; + uint16_t mfrName; + uint16_t subversion; +} hciReadRemoteVerInfoCmplEvt_t; + +/*! LE read remote features complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t features[HCI_FEAT_LEN]; +} hciLeReadRemoteFeatCmplEvt_t; + +/*! LE LTK request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqReplCmdCmplEvt_t; + +/*! LE LTK request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeLtkReqNegReplCmdCmplEvt_t; + +/*! Encryption key refresh complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciEncKeyRefreshCmpl_t; + +/*! Encryption change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t enabled; +} hciEncChangeEvt_t; + +/*! LE LTK request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint8_t randNum[HCI_RAND_LEN]; + uint16_t encDiversifier; +} hciLeLtkReqEvt_t; + +/*! Vendor specific command status event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; +} hciVendorSpecCmdStatusEvt_t; + +/*! Vendor specific command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t opcode; + uint8_t param[1]; +} hciVendorSpecCmdCmplEvt_t; + +/*! Vendor specific event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t param[1]; +} hciVendorSpecEvt_t; + +/*! Hardware error event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t code; +} hciHwErrorEvt_t; + +/*! LE encrypt command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t data[HCI_ENCRYPT_DATA_LEN]; +} hciLeEncryptCmdCmplEvt_t; + +/*! LE rand command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t randNum[HCI_RAND_LEN]; +} hciLeRandCmdCmplEvt_t; + +/*! LE remote connection parameter request reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamRepEvt_t; + +/*! LE remote connection parameter request negative reply command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeRemConnParamNegRepEvt_t; + +/*! LE read suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t suggestedMaxTxOctets; + uint16_t suggestedMaxTxTime; +} hciLeReadDefDataLenEvt_t; + +/*! LE write suggested default data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeWriteDefDataLenEvt_t; + +/*! LE set data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciLeSetDataLenEvt_t; + +/*! LE read maximum data len command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t supportedMaxTxOctets; + uint16_t supportedMaxTxTime; + uint16_t supportedMaxRxOctets; + uint16_t supportedMaxRxTime; +} hciLeReadMaxDataLenEvt_t; + +/*! LE remote connetion parameter request event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t intervalMin; + uint16_t intervalMax; + uint16_t latency; + uint16_t timeout; +} hciLeRemConnParamReqEvt_t; + +/*! LE data length change event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; + uint16_t maxTxOctets; + uint16_t maxTxTime; + uint16_t maxRxOctets; + uint16_t maxRxTime; +} hciLeDataLenChangeEvt_t; + +/*! LE local p256 ecc key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_P256_KEY_LEN]; +} hciLeP256CmplEvt_t; + +/*! LE generate DH key command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t key[HCI_DH_KEY_LEN]; +} hciLeGenDhKeyEvt_t; + +/*! LE read peer resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t peerRpa[BDA_ADDR_LEN]; +} hciLeReadPeerResAddrCmdCmplEvt_t; + +/*! LE read local resolving address command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint8_t localRpa[BDA_ADDR_LEN]; +} hciLeReadLocalResAddrCmdCmplEvt_t; + +/*! LE set address resolving enable command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetAddrResEnableCmdCmplEvt_t; + +/*! LE add device to resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeAddDevToResListCmdCmplEvt_t; + +/*! LE remove device from resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeRemDevFromResListCmdCmplEvt_t; + +/*! LE clear resolving list command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeClearResListCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; +} hciWriteAuthPayloadToCmdCmplEvt_t; + +typedef struct +{ + wsfMsgHdr_t hdr; + uint16_t handle; +} hciAuthPayloadToExpiredEvt_t; + +/*! LE read PHY command complete event */ + typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLeReadPhyCmdCmplEvt_t; + +/*! LE set default PHY command complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; +} hciLeSetDefPhyCmdCmplEvt_t; + +/*! LE PHY update complete event */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t status; + uint16_t handle; + uint8_t txPhy; + uint8_t rxPhy; +} hciLePhyUpdateEvt_t; + +/*! Union of all event types */ +typedef union +{ + wsfMsgHdr_t hdr; + wsfMsgHdr_t resetSeqCmpl; + hciLeConnCmplEvt_t leConnCmpl; + hciDisconnectCmplEvt_t disconnectCmpl; + hciLeConnUpdateCmplEvt_t leConnUpdateCmpl; + hciLeCreateConnCancelCmdCmplEvt_t leCreateConnCancelCmdCmpl; + hciLeAdvReportEvt_t leAdvReport; + hciReadRssiCmdCmplEvt_t readRssiCmdCmpl; + hciReadChanMapCmdCmplEvt_t readChanMapCmdCmpl; + hciReadTxPwrLvlCmdCmplEvt_t readTxPwrLvlCmdCmpl; + hciReadRemoteVerInfoCmplEvt_t readRemoteVerInfoCmpl; + hciLeReadRemoteFeatCmplEvt_t leReadRemoteFeatCmpl; + hciLeLtkReqReplCmdCmplEvt_t leLtkReqReplCmdCmpl; + hciLeLtkReqNegReplCmdCmplEvt_t leLtkReqNegReplCmdCmpl; + hciEncKeyRefreshCmpl_t encKeyRefreshCmpl; + hciEncChangeEvt_t encChange; + hciLeLtkReqEvt_t leLtkReq; + hciVendorSpecCmdStatusEvt_t vendorSpecCmdStatus; + hciVendorSpecCmdCmplEvt_t vendorSpecCmdCmpl; + hciVendorSpecEvt_t vendorSpec; + hciHwErrorEvt_t hwError; + hciLeEncryptCmdCmplEvt_t leEncryptCmdCmpl; + hciLeRandCmdCmplEvt_t leRandCmdCmpl; + hciLeReadPeerResAddrCmdCmplEvt_t leReadPeerResAddrCmdCmpl; + hciLeReadLocalResAddrCmdCmplEvt_t leReadLocalResAddrCmdCmpl; + hciLeSetAddrResEnableCmdCmplEvt_t leSetAddrResEnableCmdCmpl; + hciLeAddDevToResListCmdCmplEvt_t leAddDevToResListCmdCmpl; + hciLeRemDevFromResListCmdCmplEvt_t leRemDevFromResListCmdCmpl; + hciLeClearResListCmdCmplEvt_t leClearResListCmdCmpl; + hciLeRemConnParamRepEvt_t leRemConnParamRepCmdCmpl; + hciLeRemConnParamNegRepEvt_t leRemConnParamNegRepCmdCmpl; + hciLeReadDefDataLenEvt_t leReadDefDataLenCmdCmpl; + hciLeWriteDefDataLenEvt_t leWriteDefDataLenCmdCmpl; + hciLeSetDataLenEvt_t leSetDataLenCmdCmpl; + hciLeReadMaxDataLenEvt_t leReadMaxDataLenCmdCmpl; + hciLeRemConnParamReqEvt_t leRemConnParamReq; + hciLeDataLenChangeEvt_t leDataLenChange; + hciLeP256CmplEvt_t leP256; + hciLeGenDhKeyEvt_t leGenDHKey; + hciWriteAuthPayloadToCmdCmplEvt_t writeAuthPayloadToCmdCmpl; + hciAuthPayloadToExpiredEvt_t authPayloadToExpired; + hciLeReadPhyCmdCmplEvt_t leReadPhyCmdCmpl; + hciLeSetDefPhyCmdCmplEvt_t leSetDefPhyCmdCmpl; + hciLePhyUpdateEvt_t lePhyUpdate; + hciLeExtAdvReportEvt_t leExtAdvReport; + hciLeScanTimeoutEvt_t leScanTimeout; + hciLeAdvSetTermEvt_t leAdvSetTerm; + hciLeScanReqRcvdEvt_t leScanReqRcvd; + hciLePerAdvSyncEstEvt_t lePerAdvSyncEst; + hciLePerAdvReportEvt_t lePerAdvReport; + hciLePerAdvSyncLostEvt_t lePerAdvSyncLost; + hciLeChSelAlgoEvt_t leChSelAlgo; +} hciEvt_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +typedef void (*hciEvtCback_t)(hciEvt_t *pEvent); +typedef void (*hciSecCback_t)(hciEvt_t *pEvent); +typedef void (*hciAclCback_t)(uint8_t *pData); +typedef void (*hciFlowCback_t)(uint16_t handle, bool_t flowDisabled); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*! Initialization, registration, and reset */ +void HciEvtRegister(hciEvtCback_t evtCback); +void HciSecRegister(hciSecCback_t secCback); +void HciAclRegister(hciAclCback_t aclCback, hciFlowCback_t flowCback); +void HciResetSequence(void); +void HciVsInit(uint8_t param); +void HciCoreInit(void); +void HciCoreHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); +void HciSetMaxRxAclLen(uint16_t len); +void HciSetAclQueueWatermarks(uint8_t queueHi, uint8_t queueLo); +void HciSetLeSupFeat(uint16_t feat, bool_t flag); + +/*! Optimization interface */ +uint8_t *HciGetBdAddr(void); +uint8_t HciGetWhiteListSize(void); +int8_t HciGetAdvTxPwr(void); +uint16_t HciGetBufSize(void); +uint8_t HciGetNumBufs(void); +uint8_t *HciGetSupStates(void); +uint16_t HciGetLeSupFeat(void); +uint16_t HciGetMaxRxAclLen(void); +uint8_t HciGetResolvingListSize(void); +bool_t HciLlPrivacySupported(void); +uint16_t HciGetMaxAdvDataLen(void); +uint8_t HciGetNumSupAdvSets(void); +bool_t HciLeAdvExtSupported(void); +uint8_t HciGetPerAdvListSize(void); + +/*! ACL data interface */ +void HciSendAclData(uint8_t *pAclData); + +/*! Command interface */ +void HciDisconnectCmd(uint16_t handle, uint8_t reason); +void HciLeAddDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeClearWhiteListCmd(void); +void HciLeConnUpdateCmd(uint16_t handle, hciConnSpec_t *pConnSpec); +void HciLeCreateConnCmd(uint16_t scanInterval, uint16_t scanWindow, uint8_t filterPolicy, + uint8_t peerAddrType, uint8_t *pPeerAddr, uint8_t ownAddrType, + hciConnSpec_t *pConnSpec); +void HciLeCreateConnCancelCmd(void); +void HciLeEncryptCmd(uint8_t *pKey, uint8_t *pData); +void HciLeLtkReqNegReplCmd(uint16_t handle); +void HciLeLtkReqReplCmd(uint16_t handle, uint8_t *pKey); +void HciLeRandCmd(void); +void HciLeReadAdvTXPowerCmd(void); +void HciLeReadBufSizeCmd(void); +void HciLeReadChanMapCmd(uint16_t handle); +void HciLeReadLocalSupFeatCmd(void); +void HciLeReadRemoteFeatCmd(uint16_t handle); +void HciLeReadSupStatesCmd(void); +void HciLeReadWhiteListSizeCmd(void); +void HciLeRemoveDevWhiteListCmd(uint8_t addrType, uint8_t *pAddr); +void HciLeSetAdvEnableCmd(uint8_t enable); +void HciLeSetAdvDataCmd(uint8_t len, uint8_t *pData); +void HciLeSetAdvParamCmd(uint16_t advIntervalMin, uint16_t advIntervalMax, uint8_t advType, + uint8_t ownAddrType, uint8_t peerAddrType, uint8_t *pPeerAddr, + uint8_t advChanMap, uint8_t advFiltPolicy); +void HciLeSetEventMaskCmd(uint8_t *pLeEventMask); +void HciLeSetHostChanClassCmd(uint8_t *pChanMap); +void HciLeSetRandAddrCmd(uint8_t *pAddr); +void HciLeSetScanEnableCmd(uint8_t enable, uint8_t filterDup); +void HciLeSetScanParamCmd(uint8_t scanType, uint16_t scanInterval, uint16_t scanWindow, + uint8_t ownAddrType, uint8_t scanFiltPolicy); +void HciLeSetScanRespDataCmd(uint8_t len, uint8_t *pData); +void HciLeStartEncryptionCmd(uint16_t handle, uint8_t *pRand, uint16_t diversifier, uint8_t *pKey); +void HciReadBdAddrCmd(void); +void HciReadBufSizeCmd(void); +void HciReadLocalSupFeatCmd(void); +void HciReadLocalVerInfoCmd(void); +void HciReadRemoteVerInfoCmd(uint16_t handle); +void HciReadRssiCmd(uint16_t handle); +void HciReadTxPwrLvlCmd(uint16_t handle, uint8_t type); +void HciResetCmd(void); +void HciSetEventMaskCmd(uint8_t *pEventMask); +void HciSetEventMaskPage2Cmd(uint8_t *pEventMask); +void HciReadAuthPayloadTimeout(uint16_t handle); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); +void HciLeAddDeviceToResolvingListCmd(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr, + const uint8_t *pPeerIrk, const uint8_t *pLocalIrk); +void HciLeRemoveDeviceFromResolvingList(uint8_t peerAddrType, const uint8_t *pPeerIdentityAddr); +void HciLeClearResolvingList(void); +void HciLeReadResolvingListSize(void); +void HciLeReadPeerResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeReadLocalResolvableAddr(uint8_t addrType, const uint8_t *pIdentityAddr); +void HciLeSetAddrResolutionEnable(uint8_t enable); +void HciLeSetResolvablePrivateAddrTimeout(uint16_t rpaTimeout); +void HciLeSetPrivacyModeCmd(uint8_t addrType, uint8_t *pAddr, uint8_t mode); +void HciLeReadPhyCmd(uint16_t handle); +void HciLeSetDefaultPhyCmd(uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys); +void HciLeSetPhyCmd(uint16_t handle, uint8_t allPhys, uint8_t txPhys, uint8_t rxPhys, uint16_t phyOptions); +void HciVendorSpecificCmd(uint16_t opcode, uint8_t len, uint8_t *pData); + +void HciLeRemoteConnParamReqReply(uint16_t handle, uint16_t intervalMin, uint16_t intervalMax, uint16_t latency, + uint16_t timeout, uint16_t minCeLen, uint16_t maxCeLen); +void HciLeRemoteConnParamReqNegReply(uint16_t handle, uint8_t reason); +void HciLeSetDataLen(uint16_t handle, uint16_t txOctets, uint16_t txTime); +void HciLeReadDefDataLen(void); +void HciLeWriteDefDataLen(uint16_t suggestedMaxTxOctets, uint16_t suggestedMaxTxTime); +void HciLeReadLocalP256PubKey(void); +void HciLeGenerateDHKey(uint8_t *pPubKeyX, uint8_t *pPubKeyY); +void HciLeReadMaxDataLen(void); +void HciWriteAuthPayloadTimeout(uint16_t handle, uint16_t timeout); + +/* AE slave interface */ +void HciLeSetAdvSetRandAddrCmd(uint8_t advHandle, const uint8_t *pAddr); +void HciLeSetExtAdvParamCmd(uint8_t advHandle, hciExtAdvParam_t *pExtAdvParam); +void HciLeSetExtAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtScanRespDataCmd(uint8_t advHandle, uint8_t op, uint8_t fragPref, uint8_t len, + const uint8_t *pData); +void HciLeSetExtAdvEnableCmd(uint8_t enable, uint8_t numSets, hciExtAdvEnableParam_t *pEnableParam); +void HciLeReadMaxAdvDataLen(void); +void HciLeReadNumSupAdvSets(void); +void HciLeRemoveAdvSet(uint8_t advHandle); +void HciLeClearAdvSets(void); +void HciLeSetPerAdvParamCmd(uint8_t advHandle, uint16_t advIntervalMin, uint16_t advIntervalMax, + uint16_t advProps); +void HciLeSetPerAdvDataCmd(uint8_t advHandle, uint8_t op, uint8_t len, const uint8_t *pData); +void HciLeSetPerAdvEnableCmd(uint8_t enable, uint8_t advHandle); + +/* AE master interface */ +void HciLeSetExtScanParamCmd(uint8_t ownAddrType, uint8_t scanFiltPolicy, uint8_t scanPhys, + hciExtScanParam_t *pScanParam); +void HciLeExtScanEnableCmd(uint8_t enable, uint8_t filterDup, uint16_t duration, uint16_t period); +void HciLeExtCreateConnCmd(hciExtInitParam_t *pInitParam, hciExtInitScanParam_t *pScanParam, + hciConnSpec_t *pConnSpec); +void HciLePerAdvCreateSyncCmd(uint8_t filterPolicy, uint8_t advSid, uint8_t advAddrType, + const uint8_t *pAdvAddr, uint16_t skip, uint16_t syncTimeout, uint8_t unused); +void HciLePerAdvCreateSyncCancelCmd(void); +void HciLePerAdvTerminateSyncCmd(uint16_t syncHandle); +void HciLeAddDeviceToPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeRemoveDeviceFromPerAdvListCmd(uint8_t advAddrType, const uint8_t *pAdvAddr, uint8_t advSid); +void HciLeClearPerAdvListCmd(void); +void HciLeReadPerAdvListSizeCmd(void); + +/* AE common interface */ +void HciVsAeInit(uint8_t param); +void HciLeReadTxPower(void); +void HciLeReadRfPathComp(void); +void HciLeWriteRfPathComp(int16_t txPathComp, int16_t rxPathComp); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h new file mode 100644 index 00000000000..4b7f6bad624 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/hci_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file hci_handler.h + * + * \brief Interface to HCI event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_HANDLER_H +#define HCI_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn HciHandlerInit + * + * \brief HCI handler init function called during system initialization. + * + * \param handlerID WSF handler ID for HCI. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn HciHandler + * + * \brief WSF event handler for HCI. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void HciHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h new file mode 100644 index 00000000000..006791edfae --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_api.h @@ -0,0 +1,431 @@ +/*************************************************************************************************/ +/*! + * \file l2c_api.h + * + * \brief L2CAP subsystem API. + * + * $Date: 2017-03-21 16:36:53 -0500 (Tue, 21 Mar 2017) $ + * $Revision: 11626 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_API_H +#define L2C_API_H + +#include "dm_api.h" +#include "l2c_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Control callback message events */ +#define L2C_CTRL_FLOW_ENABLE_IND 0 /*! Data flow enabled */ +#define L2C_CTRL_FLOW_DISABLE_IND 1 /*! Data flow disabled */ + +/*! Invalid channel registration ID for connection oriented channels */ +#define L2C_COC_REG_ID_NONE 0 + +/*! Invalid channel ID for connection oriented channels */ +#define L2C_COC_CID_NONE 0 + +/*! Connection oriented channel initiator/acceptor role */ +#define L2C_COC_ROLE_NONE 0x00 /*! No role (unallocated) */ +#define L2C_COC_ROLE_INITIATOR 0x01 /*! Channel initiator */ +#define L2C_COC_ROLE_ACCEPTOR 0x02 /*! Channel acceptor */ + +/*! Connection oriented channel data confirm status values */ +#define L2C_COC_DATA_SUCCESS 0 /*! Data request successful */ +#define L2C_COC_DATA_ERR_MEMORY 1 /*! Out of memory */ +#define L2C_COC_DATA_ERR_OVERFLOW 2 /*! Transaction overflow */ + +/*! Connection oriented channel callback events */ +#define L2C_COC_CBACK_START 0x70 /*! L2C callback event starting value */ +enum +{ + L2C_COC_CONNECT_IND = L2C_COC_CBACK_START, /*! Channel connect indication */ + L2C_COC_DISCONNECT_IND, /*! Channel disconnect indication */ + L2C_COC_DATA_IND, /*! Received data indication */ + L2C_COC_DATA_CNF /*! Transmit data confirm */ +}; + +#define L2C_COC_CBACK_CBACK_END L2C_COC_DATA_CNF /*! L2C callback event ending value */ + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Connection oriented channel registration ID */ +typedef uint16_t l2cCocRegId_t; + +/*! Connection oriented channel registration structure */ +typedef struct +{ + uint16_t psm; /*! Protocol service multiplexer */ + uint16_t mps; /*! Maximum receive PDU fragment size */ + uint16_t mtu; /*! Maximum receive data packet size */ + uint16_t credits; /*! Data packet receive credits for this channel */ + bool_t authoriz; /*! TRUE if authorization is required */ + uint8_t secLevel; /*! Channel minimum security level requirements */ + uint8_t role; /*! Channel initiator/acceptor role */ +} l2cCocReg_t; + +/* Connection oriented channel connect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t peerMtu; /*! Data packet MTU peer can receive */ + uint16_t psm; /*! Connected PSM */ +} l2cCocConnectInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint16_t result; /*! Connection failure result code */ +} l2cCocDisconnectInd_t; + +/* Connection oriented channel data indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ + uint8_t *pData; /*! Pointer to packet data */ + uint16_t dataLen; /*! packet data length */ +} l2cCocDataInd_t; + +/* Connection oriented channel disconnect indication structure */ +typedef struct +{ + wsfMsgHdr_t hdr; /*! Header structure */ + uint16_t cid; /*! Local channel ID */ +} l2cCocDataCnf_t; + +/*! + * Connection oriented channel event structure + * + * Connection oriented channel callback header parameters: + * + * \param hdr.event Callback event + * \param hdr.param DM connection ID + * \param hdr.status Event status (L2C_COC_DATA_CNF only) + */ +typedef union +{ + wsfMsgHdr_t hdr; /*! Header structure */ + l2cCocConnectInd_t connectInd; /*! Channel connect indication */ + l2cCocDisconnectInd_t disconnectInd; /*! Channel disconnect indication */ + l2cCocDataInd_t dataInd; /*! Received data indication */ + l2cCocDataCnf_t dataCnf; /*! Transmit data confirm */ +} l2cCocEvt_t; + +/*! Configurable parameters */ +typedef struct +{ + uint16_t reqTimeout; /*! Request timeout in seconds */ +} l2cCfg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern l2cCfg_t *pL2cCfg; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn l2cDataCback_t + * + * \brief This callback function sends a received L2CAP packet to the client. + * + * \param handle The connection handle. + * \param len The length of the L2CAP payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cDataCback_t)(uint16_t handle, uint16_t len, uint8_t *pPacket); + +/*************************************************************************************************/ +/*! + * \fn l2cCtrlCback_t + * + * \brief This callback function sends control messages to the client. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCtrlCback_t)(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocCback_t + * + * \brief This callback function sends data and other events to connection oriented + * channels clients. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*l2cCocCback_t)(l2cCocEvt_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn l2cCocAuthorCback_t + * + * \brief This callback function is used for authoriztion of connection oriented channels. + * + * \param connId DM connection ID. + * \param regId The registration instance requiring authorization. + * \param psm The PSM of the registration instance. + * + * \return L2C_CONN_SUCCESS if authorization is successful, any other value for failure. + */ +/*************************************************************************************************/ +typedef uint16_t (*l2cCocAuthorCback_t)(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cInit + * + * \brief Initialize L2C subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cMasterInit + * + * \brief Initialize L2C for operation as a Bluetooth LE master. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cMasterInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveInit + * + * \brief Initialize L2C for operation as a Bluetooth LE slave. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cRegister + * + * \brief called by the L2C client, such as ATT or SMP, to register for the given CID. + * + * \param cid channel identifier. + * \param dataCback Callback function for L2CAP data received for this CID. + * \param ctrlCback Callback function for control events for this CID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cRegister(uint16_t cid, l2cDataCback_t dataCback, l2cCtrlCback_t ctrlCback); + +/*************************************************************************************************/ +/*! + * \fn L2cDataReq + * + * \brief Send an L2CAP data packet on the given CID. + * + * \param cid The channel identifier. + * \param handle The connection handle. The client receives this handle from DM. + * \param len The length of the payload data in pPacket. + * \param pPacket A buffer containing the packet. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDataReq(uint16_t cid, uint16_t handle, uint16_t len, uint8_t *pL2cPacket); + +/*************************************************************************************************/ +/*! + * \fn L2cCocInit + * + * \brief Initialize L2C connection oriented channel subsystem. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocInit(void); + +/*************************************************************************************************/ +/*! + * \fn L2cCocRegister + * + * \brief Register to use a connection oriented channel, as either a channel acceptor, + * initiator, or both. If registering as channel acceptor then the PSM is specified. + * After registering a connection can be established by the client using this + * registration instance. + * + * \param cback Client callback function. + * \param pReg Registration parameter structure. + * + * \return Registration instance ID or L2C_COC_REG_ID_NONE if registration failed. + */ +/*************************************************************************************************/ +l2cCocRegId_t L2cCocRegister(l2cCocCback_t cback, l2cCocReg_t *pReg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDeregister + * + * \brief Deregister and deallocate a connection oriented channel registration instance. + * This function should only be called if there are no active channels using this + * registration instance. + * + * \param regId Registration instance ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDeregister(l2cCocRegId_t regId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocConnectReq + * + * \brief Initiate a connection to the given peer PSM. + * + * \param connId DM connection ID. + * \param regId The associated registration instance. + * \param psm Peer PSM. + * + * \return Local CID or L2C_COC_CID_NONE none if failure. + */ +/*************************************************************************************************/ +uint16_t L2cCocConnectReq(dmConnId_t connId, l2cCocRegId_t regId, uint16_t psm); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDisconnectReq + * + * \brief Disconnect the channel for the given CID. + * + * \param cid Channel ID. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDisconnectReq(uint16_t cid); + +/*************************************************************************************************/ +/*! + * \fn L2cCocDataReq + * + * \brief Send an L2CAP data packet on the given connection oriented CID. + * + * \param cid The local channel identifier. + * \param len The length of the payload data in pPacket. + * \param pPacket Packet payload data. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocDataReq(uint16_t cid, uint16_t len, uint8_t *pPayload); + +/*************************************************************************************************/ +/*! + * \fn L2cCocErrorTest + * + * \brief For testing purposes only. + * + * \param result Result code + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocErrorTest(uint16_t result); + +/*************************************************************************************************/ +/*! + * \fn L2cCocCreditSendTest + * + * \brief For testing purposes only. + * + * \param cid The local channel identifier. + * \param credits Credits to send. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocCreditSendTest(uint16_t cid, uint16_t credits); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateReq + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update request. + * + * \param handle The connection handle. + * \param pConnSpec Pointer to the connection specification structure. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateReq(uint16_t handle, hciConnSpec_t *pConnSpec); + +/*************************************************************************************************/ +/*! + * \fn L2cDmConnUpdateRsp + * + * \brief For internal use only. This function is called by DM to send an L2CAP + * connection update response. + * + * \param identifier Identifier value previously passed from L2C to DM. + * \param handle The connection handle. + * \param result Connection update response result. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cDmConnUpdateRsp(uint8_t identifier, uint16_t handle, uint16_t result); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h new file mode 100644 index 00000000000..7754abb7f67 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_defs.h @@ -0,0 +1,118 @@ +/*************************************************************************************************/ +/*! + * \file l2c_defs.h + * + * \brief L2CAP constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_DEFS_H +#define L2C_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Packet definitions */ +#define L2C_HDR_LEN 4 /*! L2CAP packet header length */ +#define L2C_MIN_MTU 23 /*! Minimum packet payload MTU for LE */ +#define L2C_SIG_HDR_LEN 4 /*! L2CAP signaling command header length */ +#define L2C_LE_SDU_HDR_LEN 2 /*! L2CAP LE SDU data header length */ + +/*! Start of L2CAP payload in an HCI ACL packet buffer */ +#define L2C_PAYLOAD_START (HCI_ACL_HDR_LEN + L2C_HDR_LEN) + +/*! L2CAP signaling packet base length, including HCI header */ +#define L2C_SIG_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_SIG_HDR_LEN) + +/*! L2CAP LE SDU packet base length, including HCI header */ +#define L2C_LE_SDU_PKT_BASE_LEN (HCI_ACL_HDR_LEN + L2C_HDR_LEN + L2C_LE_SDU_HDR_LEN) + +/*! Signaling packet parameter lengths */ +#define L2C_SIG_CONN_UPDATE_REQ_LEN 8 +#define L2C_SIG_CONN_UPDATE_RSP_LEN 2 +#define L2C_SIG_CMD_REJ_LEN 2 +#define L2C_SIG_DISCONN_REQ_LEN 4 +#define L2C_SIG_DISCONN_RSP_LEN 4 +#define L2C_SIG_LE_CONN_REQ_LEN 10 +#define L2C_SIG_LE_CONN_RSP_LEN 10 +#define L2C_SIG_FLOW_CTRL_CREDIT_LEN 4 + +/*! Connection identifiers */ +#define L2C_CID_ATT 0x0004 /*! CID for attribute protocol */ +#define L2C_CID_LE_SIGNALING 0x0005 /*! CID for LE signaling */ +#define L2C_CID_SMP 0x0006 /*! CID for security manager protocol */ + +/*! Signaling codes */ +#define L2C_SIG_CMD_REJ 0x01 /*! Comand reject */ +#define L2C_SIG_DISCONNECT_REQ 0x06 /*! Disconnect request */ +#define L2C_SIG_DISCONNECT_RSP 0x07 /*! Disconnect response */ +#define L2C_SIG_CONN_UPDATE_REQ 0x12 /*! Connection parameter update request */ +#define L2C_SIG_CONN_UPDATE_RSP 0x13 /*! Connection parameter update response */ +#define L2C_SIG_LE_CONNECT_REQ 0x14 /*! LE credit based connection request */ +#define L2C_SIG_LE_CONNECT_RSP 0x15 /*! LE credit based connection response */ +#define L2C_SIG_FLOW_CTRL_CREDIT 0x16 /*! LE flow control credit */ + +/*! Signaling response code flag */ +#define L2C_SIG_RSP_FLAG 0x01 + +/*! Command reject reason codes */ +#define L2C_REJ_NOT_UNDERSTOOD 0x0000 /*! Command not understood */ +#define L2C_REJ_MTU_EXCEEDED 0x0001 /*! Signaling MTU exceeded */ +#define L2C_REJ_INVALID_CID 0x0002 /*! Invalid CID in request */ + +/*! Connection parameter update result */ +#define L2C_CONN_PARAM_ACCEPTED 0x0000 /*! Connection parameters accepted */ +#define L2C_CONN_PARAM_REJECTED 0x0001 /*! Connection parameters rejected */ + +/*! LE connection result */ +#define L2C_CONN_SUCCESS 0x0000 /*! Connection successful */ +#define L2C_CONN_NONE 0x0001 /*! No connection result value available */ +#define L2C_CONN_FAIL_PSM 0x0002 /*! Connection refused LE_PSM not supported */ +#define L2C_CONN_FAIL_RES 0x0004 /*! Connection refused no resources available */ +#define L2C_CONN_FAIL_AUTH 0x0005 /*! Connection refused insufficient authentication */ +#define L2C_CONN_FAIL_AUTHORIZ 0x0006 /*! Connection refused insufficient authorization */ +#define L2C_CONN_FAIL_KEY_SIZE 0x0007 /*! Connection refused insufficient encryption key size */ +#define L2C_CONN_FAIL_ENC 0x0008 /*! Connection Refused insufficient encryption */ +#define L2C_CONN_FAIL_INVALID_SCID 0x0009 /*! Connection refused invalid source CID */ +#define L2C_CONN_FAIL_ALLOCATED_SCID 0x000A /*! Connection refused source CID already allocated */ +#define L2C_CONN_FAIL_UNACCEPT_PARAM 0x000B /*! Connection refused unacceptable parameters */ + +/*! LE connection result proprietary codes */ +#define L2C_CONN_FAIL_TIMEOUT 0xF000 /*! Request timeout */ + +/*! Signaling parameter value ranges */ +#define L2C_PSM_MIN 0x0001 +#define L2C_PSM_MAX 0x00FF +#define L2C_CID_DYN_MIN 0x0040 +#define L2C_CID_DYN_MAX 0x007F +#define L2C_MTU_MIN 0x0017 +#define L2C_MPS_MIN 0x0017 +#define L2C_MPS_MAX 0xFFFD +#define L2C_CREDITS_MAX 0xFFFF + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h new file mode 100644 index 00000000000..5b8fde42eee --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/l2c_handler.h @@ -0,0 +1,96 @@ +/*************************************************************************************************/ +/*! + * \file l2c_handler.h + * + * \brief L2CAP handler interface. + * + * $Date $ + * $Revision $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef L2C_HANDLER_H +#define L2C_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandlerInit + * + * \brief Event handler initialization function for L2C when operating as a slave. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cSlaveHandler + * + * \brief The WSF event handler for L2C when operating as a slave. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cSlaveHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandlerInit + * + * \brief Event handler initialization function for L2C with connection oriented channels. + * + * \param handlerId ID for this event handler. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandlerInit(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn L2cCocHandler + * + * \brief The WSF event handler for L2C with connection oriented channels. + * + * \param event Event mask. + * \param pMsg Pointer to message. + * + * \return None. + */ +/*************************************************************************************************/ +void L2cCocHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* L2C_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h new file mode 100644 index 00000000000..f1624f1c4df --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_api.h @@ -0,0 +1,242 @@ +/*************************************************************************************************/ +/*! + * \file smp_api.h + * + * \brief SMP subsystem API. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_API_H +#define SMP_API_H + +#include "wsf_os.h" +#include "smp_defs.h" +#include "dm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Event handler messages for SMP state machines */ +enum +{ + SMP_MSG_API_PAIR_REQ = 1, /*! API pairing request */ + SMP_MSG_API_PAIR_RSP, /*! API pairing response */ + SMP_MSG_API_CANCEL_REQ, /*! API cancel request */ + SMP_MSG_API_AUTH_RSP, /*! API pin response */ + SMP_MSG_API_SECURITY_REQ, /*! API security request */ + SMP_MSG_CMD_PKT, /*! SMP command packet received */ + SMP_MSG_CMD_PAIRING_FAILED, /*! SMP pairing failed packet received */ + SMP_MSG_DM_ENCRYPT_CMPL, /*! Link encrypted */ + SMP_MSG_DM_ENCRYPT_FAILED, /*! Link encryption failed */ + SMP_MSG_DM_CONN_CLOSE, /*! Connection closed */ + SMP_MSG_WSF_AES_CMPL, /*! AES calculation complete */ + SMP_MSG_INT_SEND_NEXT_KEY, /*! Send next key to be distributed */ + SMP_MSG_INT_MAX_ATTEMPTS, /*! Maximum pairing attempts reached */ + SMP_MSG_INT_PAIRING_CMPL, /*! Pairing complete */ + SMP_MSG_INT_TIMEOUT, /*! Pairing protocol timeout */ + SMP_MSG_INT_LESC, /*! Pair with Secure Connections */ + SMP_MSG_INT_LEGACY, /*! Pair with Legacy Security */ + SMP_MSG_INT_JW_NC, /*! LESC Just-Works/Numeric Comparison pairing */ + SMP_MSG_INT_PASSKEY, /*! LESC Passkey pairing */ + SMP_MSG_INT_OOB, /*! LESC Out-of-Band Pairing */ + SMP_MSG_API_USER_CONFIRM, /*! User confirms valid numeric comparison */ + SMP_MSG_API_USER_KEYPRESS, /*! User keypress in passkey pairing */ + SMP_MSG_API_KEYPRESS_CMPL, /*! User keypress complete in passkey pairing */ + SMP_MSG_WSF_ECC_CMPL, /*! WSF ECC operation complete */ + SMP_MSG_INT_PK_NEXT, /*! Continue to next passkey bit */ + SMP_MSG_INT_PK_CMPL, /*! Passkey operation complete */ + SMP_MSG_WSF_CMAC_CMPL, /*! WSF CMAC operation complete */ + SMP_MSG_DH_CHECK_FAILURE, /*! WSF CMAC operation complete */ + SMP_MSG_EARLY_CNF, /*! An early Confirm from the initiator in passkey pairing */ + SMP_NUM_MSGS +}; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Configurable parameters */ +typedef struct +{ + uint16_t attemptTimeout; /*! 'Repeated attempts' timeout in msec */ + uint8_t ioCap; /*! I/O Capability */ + uint8_t minKeyLen; /*! Minimum encryption key length */ + uint8_t maxKeyLen; /*! Maximum encryption key length */ + uint8_t maxAttempts; /*! Attempts to trigger 'repeated attempts' timeout */ + uint8_t auth; /*! Device authentication requirements */ +} smpCfg_t; + +/*! Data type for SMP_MSG_API_PAIR_REQ and SMP_MSG_API_PAIR_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t oob; + uint8_t auth; + uint8_t iKeyDist; + uint8_t rKeyDist; +} smpDmPair_t; + +/*! Data type for SMP_MSG_API_AUTH_RSP */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t authData[SMP_OOB_LEN]; + uint8_t authDataLen; +} smpDmAuthRsp_t; + +/*! Data type for SMP_MSG_API_USER_KEYPRESS */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t keypress; +} smpDmKeypress_t; + +/*! Data type for SMP_MSG_API_SECURITY_REQ */ +typedef struct +{ + wsfMsgHdr_t hdr; + uint8_t auth; +} smpDmSecurityReq_t; + +/*! Union SMP DM message data types */ +typedef union +{ + wsfMsgHdr_t hdr; + smpDmPair_t pair; + smpDmAuthRsp_t authRsp; + smpDmSecurityReq_t securityReq; + smpDmKeypress_t keypress; +} smpDmMsg_t; + +/************************************************************************************************** + Global Variables; +**************************************************************************************************/ + +/*! Configuration pointer */ +extern smpCfg_t *pSmpCfg; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpiInit + * + * \brief Initialize SMP initiator role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprInit + * + * \brief Initialize SMP responder role. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpiScInit + * + * \brief Initialize SMP initiator role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpiScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmprScInit + * + * \brief Initialize SMP responder role utilizing BTLE Secure Connections. + * + * \return None. + */ +/*************************************************************************************************/ +void SmprScInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpNonInit + * + * \brief Use this SMP init function when SMP is not supported. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpNonInit(void); + +/*************************************************************************************************/ +/*! + * \fn SmpDmMsgSend + * + * \brief This function is called by DM to send a message to SMP. + * + * \param pMsg Pointer to message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmMsgSend(smpDmMsg_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmEncryptInd + * + * \brief This function is called by DM to notify SMP of encrypted link status. + * + * \param pMsg Pointer to HCI message structure. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpDmEncryptInd(wsfMsgHdr_t *pMsg); + +/*************************************************************************************************/ +/*! + * \fn SmpDmGetStk + * + * \brief Return the STK for the given connection. + * + * \param connId Connection identifier. + * \param pSecLevel Returns the security level of pairing when STK was created. + * + * \return Pointer to STK or NULL if not available. + */ +/*************************************************************************************************/ +uint8_t *SmpDmGetStk(dmConnId_t connId, uint8_t *pSecLevel); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_API_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h new file mode 100644 index 00000000000..317b84802cb --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_defs.h @@ -0,0 +1,155 @@ +/*************************************************************************************************/ +/*! + * \file smp_defs.h + * + * \brief Security manager constants and definitions from the Bluetooth specification. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_DEFS_H +#define SMP_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! PDU format */ +#define SMP_HDR_LEN 1 /*! Attribute PDU header length */ + +/*! Protocol timeout */ +#define SMP_TIMEOUT 30 /*! Protocol timeout in seconds */ + +/*! Encryption key size */ +#define SMP_KEY_SIZE_MAX 16 /*! Maximum encryption key size */ +#define SMP_KEY_SIZE_MIN 7 /*! Minimum encryption key size */ + +/*! OOB and PIN data lengths in bytes */ +#define SMP_OOB_LEN 16 +#define SMP_PIN_LEN 3 + +/*! Error codes */ +#define SMP_ERR_PASSKEY_ENTRY 0x01 /*! User input of passkey failed */ +#define SMP_ERR_OOB 0x02 /*! OOB data is not available */ +#define SMP_ERR_AUTH_REQ 0x03 /*! Authentication requirements cannot be met */ +#define SMP_ERR_CONFIRM_VALUE 0x04 /*! Confirm value does not match */ +#define SMP_ERR_PAIRING_NOT_SUP 0x05 /*! Pairing is not supported by the device */ +#define SMP_ERR_ENC_KEY_SIZE 0x06 /*! Insufficient encryption key size */ +#define SMP_ERR_COMMAND_NOT_SUP 0x07 /*! Command not supported */ +#define SMP_ERR_UNSPECIFIED 0x08 /*! Unspecified reason */ +#define SMP_ERR_ATTEMPTS 0x09 /*! Repeated attempts */ +#define SMP_ERR_INVALID_PARAM 0x0A /*! Invalid parameter or command length */ +#define SMP_ERR_DH_KEY_CHECK 0x0B /*! DH Key check did not match */ +#define SMP_ERR_NUMERIC_COMPARISON 0x0C /*! Numeric comparison did not match */ +#define SMP_ERR_BR_EDR_IN_PROGRESS 0x0D /*! BR/EDR in progress */ +#define SMP_ERR_CROSS_TRANSPORT 0x0E /*! BR/EDR Cross transport key generation not allowed */ + +/*! Proprietary internal error codes */ +#define SMP_ERR_MEMORY 0xE0 /*! Out of memory */ +#define SMP_ERR_TIMEOUT 0xE1 /*! Transaction timeout */ + +/*! Command codes */ +#define SMP_CMD_PAIR_REQ 0x01 /*! Pairing Request */ +#define SMP_CMD_PAIR_RSP 0x02 /*! Pairing Response */ +#define SMP_CMD_PAIR_CNF 0x03 /*! Pairing Confirm */ +#define SMP_CMD_PAIR_RAND 0x04 /*! Pairing Random */ +#define SMP_CMD_PAIR_FAIL 0x05 /*! Pairing Failed */ +#define SMP_CMD_ENC_INFO 0x06 /*! Encryption Information */ +#define SMP_CMD_MASTER_ID 0x07 /*! Master Identification */ +#define SMP_CMD_ID_INFO 0x08 /*! Identity Information */ +#define SMP_CMD_ID_ADDR_INFO 0x09 /*! Identity Address Information */ +#define SMP_CMD_SIGN_INFO 0x0A /*! Signing Information */ +#define SMP_CMD_SECURITY_REQ 0x0B /*! Security Request */ +#define SMP_CMD_PUBLIC_KEY 0x0C /*! Public Key */ +#define SMP_CMD_DHKEY_CHECK 0x0D /*! DH Key Check */ +#define SMP_CMD_KEYPRESS 0x0E /*! User Key Press */ +#define SMP_CMD_MAX 0x0F /*! Command code maximum */ + +/*! Command packet lengths */ +#define SMP_PAIR_REQ_LEN 7 +#define SMP_PAIR_RSP_LEN 7 +#define SMP_PAIR_CNF_LEN 17 +#define SMP_PAIR_RAND_LEN 17 +#define SMP_PAIR_FAIL_LEN 2 +#define SMP_ENC_INFO_LEN 17 +#define SMP_MASTER_ID_LEN 11 +#define SMP_ID_INFO_LEN 17 +#define SMP_ID_ADDR_INFO_LEN 8 +#define SMP_SIGN_INFO_LEN 17 +#define SMP_SECURITY_REQ_LEN 2 +#define SMP_PUB_KEY_MSG_LEN (1 + 2*SMP_PUB_KEY_LEN) +#define SMP_DHKEY_CHECK_MSG_LEN (1 + SMP_DHKEY_CHECK_LEN) +#define SMP_KEYPRESS_MSG_LEN 2 + +/*! I/O capabilities */ +#define SMP_IO_DISP_ONLY 0x00 /*! DisplayOnly */ +#define SMP_IO_DISP_YES_NO 0x01 /*! DisplayYesNo */ +#define SMP_IO_KEY_ONLY 0x02 /*! KeyboardOnly */ +#define SMP_IO_NO_IN_NO_OUT 0x03 /*! NoInputNoOutput */ +#define SMP_IO_KEY_DISP 0x04 /*! KeyboardDisplay */ + +/*! OOB data present */ +#define SMP_OOB_DATA_NONE 0x00 +#define SMP_OOB_DATA_PRESENT 0x01 + +/*! Authentication/security properties bit mask */ +#define SMP_AUTH_BOND_MASK 0x03 /*! Mask for bonding bits */ +#define SMP_AUTH_BOND_FLAG 0x01 /*! Bonding requested */ +#define SMP_AUTH_MITM_FLAG 0x04 /*! MITM (authenticated pairing) requested */ +#define SMP_AUTH_SC_FLAG 0x08 /*! LE Secure Connections requested */ +#define SMP_AUTH_KP_FLAG 0x10 /*! Keypress notifications requested */ + +/*! Key distribution bit mask */ +#define SMP_KEY_DIST_ENC 0x01 /*! Distribute LTK */ +#define SMP_KEY_DIST_ID 0x02 /*! Distribute IRK */ +#define SMP_KEY_DIST_SIGN 0x04 /*! Distribute CSRK */ +#define SMP_KEY_DIST_MASK (SMP_KEY_DIST_ENC | SMP_KEY_DIST_ID | SMP_KEY_DIST_SIGN) + +/*! LESC Passkey keypress types */ +#define SMP_PASSKEY_ENTRY_STARTED 0x00 /*! Passkey entry started keypress type */ +#define SMP_PASSKEY_DIGIT_ENTERED 0x01 /*! Passkey digit entered keypress type */ +#define SMP_PASSKEY_DIGIT_ERASED 0x02 /*! Passkey digit erased keypress type */ +#define SMP_PASSKEY_CLEARED 0x03 /*! Passkey cleared keypress type */ +#define SMP_PASSKEY_ENTRY_COMPLETED 0x04 /*! Passkey entry complete keypress type */ + +/*! Various parameter lengths */ +#define SMP_RAND_LEN 16 +#define SMP_CONFIRM_LEN 16 +#define SMP_KEY_LEN 16 +#define SMP_RAND8_LEN 8 +#define SMP_PRIVATE_KEY_LEN 32 +#define SMP_PUB_KEY_LEN 32 +#define SMP_DHKEY_LEN 32 +#define SMP_DHKEY_CHECK_LEN 16 + +/* CMAC Input Lengths */ +#define SMP_F4_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + 1) +#define SMP_G2_TEXT_LEN (SMP_PUB_KEY_LEN * 2 + SMP_RAND_LEN) +#define SMP_F5_TKEY_TEXT_LEN (SMP_DHKEY_LEN) +#define SMP_F5_TEXT_LEN (9 + 2*BDA_ADDR_LEN + 2*SMP_RAND_LEN) +#define SMP_F6_TEXT_LEN (2*BDA_ADDR_LEN + 3*SMP_RAND_LEN + 5) + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h new file mode 100644 index 00000000000..b324afba3f4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/smp_handler.h @@ -0,0 +1,70 @@ +/*************************************************************************************************/ +/*! + * \file smp_handler.h + * + * \brief Interface to SMP event handler. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2010-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef SMP_HANDLER_H +#define SMP_HANDLER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn SmpHandlerInit + * + * \brief SMP handler init function called during system initialization. + * + * \param handlerID WSF handler ID for SMP. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandlerInit(wsfHandlerId_t handlerId); + + +/*************************************************************************************************/ +/*! + * \fn SmpHandler + * + * \brief WSF event handler for SMP. + * + * \param event WSF event mask. + * \param pMsg WSF message. + * + * \return None. + */ +/*************************************************************************************************/ +void SmpHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +#ifdef __cplusplus +}; +#endif + +#endif /* SMP_HANDLER_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h new file mode 100644 index 00000000000..4acda1153e6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/hci_defs.h @@ -0,0 +1,891 @@ +/*************************************************************************************************/ +/*! + * \file hci_defs.h + * + * \brief HCI constants and definitions from the Bluetooth specification. + * + * $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $ + * $Revision: 11460 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef HCI_DEFS_H +#define HCI_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Packet definitions */ +#define HCI_CMD_HDR_LEN 3 /*!< Command packet header length */ +#define HCI_ACL_HDR_LEN 4 /*!< ACL packet header length */ +#define HCI_EVT_HDR_LEN 2 /*!< Event packet header length */ +#define HCI_EVT_PARAM_MAX_LEN 255 /*!< Maximum length of event packet parameters */ +#define HCI_ACL_DEFAULT_LEN 27 /*!< Default maximum ACL packet length */ +#define HCI_PB_FLAG_MASK 0x3000 /*!< ACL packet boundary flag mask */ +#define HCI_PB_START_H2C 0x0000 /*!< Packet boundary flag, start, host-to-controller */ +#define HCI_PB_CONTINUE 0x1000 /*!< Packet boundary flag, continue */ +#define HCI_PB_START_C2H 0x2000 /*!< Packet boundary flag, start, controller-to-host */ +#define HCI_HANDLE_MASK 0x0FFF /*!< Mask for handle bits in ACL packet */ +#define HCI_HANDLE_NONE 0xFFFF /*!< Value for invalid handle */ + +/* Packet types */ +#define HCI_CMD_TYPE 1 /*!< HCI command packet */ +#define HCI_ACL_TYPE 2 /*!< HCI ACL data packet */ +#define HCI_EVT_TYPE 4 /*!< HCI event packet */ + +/* Error codes */ +#define HCI_SUCCESS 0x00 /*!< Success */ +#define HCI_ERR_UNKNOWN_CMD 0x01 /*!< Unknown HCI command */ +#define HCI_ERR_UNKNOWN_HANDLE 0x02 /*!< Unknown connection identifier */ +#define HCI_ERR_HARDWARE_FAILURE 0x03 /*!< Hardware failure */ +#define HCI_ERR_PAGE_TIMEOUT 0x04 /*!< Page timeout */ +#define HCI_ERR_AUTH_FAILURE 0x05 /*!< Authentication failure */ +#define HCI_ERR_KEY_MISSING 0x06 /*!< PIN or key missing */ +#define HCI_ERR_MEMORY_EXCEEDED 0x07 /*!< Memory capacity exceeded */ +#define HCI_ERR_CONN_TIMEOUT 0x08 /*!< Connection timeout */ +#define HCI_ERR_CONN_LIMIT 0x09 /*!< Connection limit exceeded */ +#define HCI_ERR_SYNCH_CONN_LIMIT 0x0A /*!< Synchronous connection limit exceeded */ +#define HCI_ERR_ACL_CONN_EXISTS 0x0B /*!< ACL connection already exists */ +#define HCI_ERR_CMD_DISALLOWED 0x0C /*!< Command disallowed */ +#define HCI_ERR_REJ_RESOURCES 0x0D /*!< Connection rejected limited resources */ +#define HCI_ERR_REJ_SECURITY 0x0E /*!< Connection rejected security reasons */ +#define HCI_ERR_REJ_BD_ADDR 0x0F /*!< Connection rejected unacceptable BD_ADDR */ +#define HCI_ERR_ACCEPT_TIMEOUT 0x10 /*!< Connection accept timeout exceeded */ +#define HCI_ERR_UNSUP_FEAT 0x11 /*!< Unsupported feature or parameter value */ +#define HCI_ERR_INVALID_PARAM 0x12 /*!< Invalid HCI command parameters */ +#define HCI_ERR_REMOTE_TERMINATED 0x13 /*!< Remote user terminated connection */ +#define HCI_ERR_REMOTE_RESOURCES 0x14 /*!< Remote device low resources */ +#define HCI_ERR_REMOTE_POWER_OFF 0x15 /*!< Remote device power off */ +#define HCI_ERR_LOCAL_TERMINATED 0x16 /*!< Connection terminated by local host */ +#define HCI_ERR_REPEATED_ATTEMPTS 0x17 /*!< Repeated attempts */ +#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18 /*!< Pairing not allowed */ +#define HCI_ERR_UNKNOWN_LMP_PDU 0x19 /*!< Unknown LMP PDU */ +#define HCI_ERR_UNSUP_REMOTE_FEAT 0x1A /*!< Unsupported remote feature */ +#define HCI_ERR_SCO_OFFSET 0x1B /*!< SCO offset rejected */ +#define HCI_ERR_SCO_INTERVAL 0x1C /*!< SCO interval rejected */ +#define HCI_ERR_SCO_MODE 0x1D /*!< SCO air mode rejected */ +#define HCI_ERR_LMP_PARAM 0x1E /*!< Invalid LMP parameters */ +#define HCI_ERR_UNSPECIFIED 0x1F /*!< Unspecified error */ +#define HCI_ERR_UNSUP_LMP_PARAM 0x20 /*!< Unsupported LMP parameter value */ +#define HCI_ERR_ROLE_CHANGE 0x21 /*!< Role change not allowed */ +#define HCI_ERR_LL_RESP_TIMEOUT 0x22 /*!< LL response timeout */ +#define HCI_ERR_LMP_COLLISION 0x23 /*!< LMP error transaction collision */ +#define HCI_ERR_LMP_PDU 0x24 /*!< LMP pdu not allowed */ +#define HCI_ERR_ENCRYPT_MODE 0x25 /*!< Encryption mode not acceptable */ +#define HCI_ERR_LINK_KEY 0x26 /*!< Link key can not be changed */ +#define HCI_ERR_UNSUP_QOS 0x27 /*!< Requested qos not supported */ +#define HCI_ERR_INSTANT_PASSED 0x28 /*!< Instant passed */ +#define HCI_ERR_UNSUP_UNIT_KEY 0x29 /*!< Pairing with unit key not supported */ +#define HCI_ERR_TRANSACT_COLLISION 0x2A /*!< Different transaction collision */ +#define HCI_ERR_CHANNEL_CLASS 0x2E /*!< Channel classification not supported */ +#define HCI_ERR_MEMORY 0x2F /*!< Insufficient security */ +#define HCI_ERR_PARAMETER_RANGE 0x30 /*!< Parameter out of mandatory range */ +#define HCI_ERR_ROLE_SWITCH_PEND 0x32 /*!< Role switch pending */ +#define HCI_ERR_RESERVED_SLOT 0x34 /*!< Reserved slot violation */ +#define HCI_ERR_ROLE_SWITCH 0x35 /*!< Role switch failed */ +#define HCI_ERR_INQ_TOO_LARGE 0x36 /*!< Extended inquiry response too large */ +#define HCI_ERR_UNSUP_SSP 0x37 /*!< Secure simple pairing not supported by host */ +#define HCI_ERR_HOST_BUSY_PAIRING 0x38 /*!< Host busy - pairing */ +#define HCI_ERR_NO_CHANNEL 0x39 /*!< Connection rejected no suitable channel */ +#define HCI_ERR_CONTROLLER_BUSY 0x3A /*!< Controller busy */ +#define HCI_ERR_CONN_INTERVAL 0x3B /*!< Unacceptable connection interval */ +#define HCI_ERR_ADV_TIMEOUT 0x3C /*!< Advertising timeout */ +#define HCI_ERR_MIC_FAILURE 0x3D /*!< Connection terminated due to MIC failure */ +#define HCI_ERR_CONN_FAIL 0x3E /*!< Connection failed to be established */ +#define HCI_ERR_MAC_CONN_FAIL 0x3F /*!< MAC connection failed */ +#define HCI_ERR_COARSE_CLK_ADJ_REJ 0x40 /*!< Coarse clock adjustment rejected */ +#define HCI_ERR_TYPE0_SUBMAP_NOT_DEF 0x41 /*!< Type0 submap not defined */ +#define HCI_ERR_UNKNOWN_ADV_ID 0x42 /*!< Unknown advertising identifier */ +#define HCI_ERR_LIMIT_REACHED 0x43 /*!< Limit reached */ +#define HCI_ERR_OP_CANCELLED_BY_HOST 0x44 /*!< Operation cancelled by host */ + +/* Command groups */ +#define HCI_OGF_NOP 0x00 /*!< No operation */ +#define HCI_OGF_LINK_CONTROL 0x01 /*!< Link control */ +#define HCI_OGF_LINK_POLICY 0x02 /*!< Link policy */ +#define HCI_OGF_CONTROLLER 0x03 /*!< Controller and baseband */ +#define HCI_OGF_INFORMATIONAL 0x04 /*!< Informational parameters */ +#define HCI_OGF_STATUS 0x05 /*!< Status parameters */ +#define HCI_OGF_TESTING 0x06 /*!< Testing */ +#define HCI_OGF_LE_CONTROLLER 0x08 /*!< LE controller */ +#define HCI_OGF_VENDOR_SPEC 0x3F /*!< Vendor specific */ + +/* NOP command */ +#define HCI_OCF_NOP 0x00 + +/* Link control commands */ +#define HCI_OCF_DISCONNECT 0x06 +#define HCI_OCF_READ_REMOTE_VER_INFO 0x1D + +/* Link policy commands (none used for LE) */ + +/* Controller and baseband commands */ +#define HCI_OCF_SET_EVENT_MASK 0x01 +#define HCI_OCF_RESET 0x03 +#define HCI_OCF_READ_TX_PWR_LVL 0x2D +#define HCI_OCF_SET_CONTROLLER_TO_HOST_FC 0x31 +#define HCI_OCF_HOST_BUFFER_SIZE 0x33 +#define HCI_OCF_HOST_NUM_CMPL_PKTS 0x35 +#define HCI_OCF_SET_EVENT_MASK_PAGE2 0x63 +#define HCI_OCF_READ_AUTH_PAYLOAD_TO 0x7B +#define HCI_OCF_WRITE_AUTH_PAYLOAD_TO 0x7C + +/* Informational commands */ +#define HCI_OCF_READ_LOCAL_VER_INFO 0x01 +#define HCI_OCF_READ_LOCAL_SUP_CMDS 0x02 +#define HCI_OCF_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_READ_BUF_SIZE 0x05 +#define HCI_OCF_READ_BD_ADDR 0x09 + +/* Status commands */ +#define HCI_OCF_READ_RSSI 0x05 + +/* LE controller commands */ +#define HCI_OCF_LE_SET_EVENT_MASK 0x01 +#define HCI_OCF_LE_READ_BUF_SIZE 0x02 +#define HCI_OCF_LE_READ_LOCAL_SUP_FEAT 0x03 +#define HCI_OCF_LE_SET_RAND_ADDR 0x05 +#define HCI_OCF_LE_SET_ADV_PARAM 0x06 +#define HCI_OCF_LE_READ_ADV_TX_POWER 0x07 +#define HCI_OCF_LE_SET_ADV_DATA 0x08 +#define HCI_OCF_LE_SET_SCAN_RESP_DATA 0x09 +#define HCI_OCF_LE_SET_ADV_ENABLE 0x0A +#define HCI_OCF_LE_SET_SCAN_PARAM 0x0B +#define HCI_OCF_LE_SET_SCAN_ENABLE 0x0C +#define HCI_OCF_LE_CREATE_CONN 0x0D +#define HCI_OCF_LE_CREATE_CONN_CANCEL 0x0E +#define HCI_OCF_LE_READ_WHITE_LIST_SIZE 0x0F +#define HCI_OCF_LE_CLEAR_WHITE_LIST 0x10 +#define HCI_OCF_LE_ADD_DEV_WHITE_LIST 0x11 +#define HCI_OCF_LE_REMOVE_DEV_WHITE_LIST 0x12 +#define HCI_OCF_LE_CONN_UPDATE 0x13 +#define HCI_OCF_LE_SET_HOST_CHAN_CLASS 0x14 +#define HCI_OCF_LE_READ_CHAN_MAP 0x15 +#define HCI_OCF_LE_READ_REMOTE_FEAT 0x16 +#define HCI_OCF_LE_ENCRYPT 0x17 +#define HCI_OCF_LE_RAND 0x18 +#define HCI_OCF_LE_START_ENCRYPTION 0x19 +#define HCI_OCF_LE_LTK_REQ_REPL 0x1A +#define HCI_OCF_LE_LTK_REQ_NEG_REPL 0x1B +#define HCI_OCF_LE_READ_SUP_STATES 0x1C +#define HCI_OCF_LE_RECEIVER_TEST 0x1D +#define HCI_OCF_LE_TRANSMITTER_TEST 0x1E +#define HCI_OCF_LE_TEST_END 0x1F +/* New in version 4.1 */ +#define HCI_OCF_LE_REM_CONN_PARAM_REP 0x20 +#define HCI_OCF_LE_REM_CONN_PARAM_NEG_REP 0x21 +/* New in version 4.2 */ +#define HCI_OCF_LE_SET_DATA_LEN 0x22 +#define HCI_OCF_LE_READ_DEF_DATA_LEN 0x23 +#define HCI_OCF_LE_WRITE_DEF_DATA_LEN 0x24 +#define HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY 0x25 +#define HCI_OCF_LE_GENERATE_DHKEY 0x26 +#define HCI_OCF_LE_ADD_DEV_RES_LIST 0x27 +#define HCI_OCF_LE_REMOVE_DEV_RES_LIST 0x28 +#define HCI_OCF_LE_CLEAR_RES_LIST 0x29 +#define HCI_OCF_LE_READ_RES_LIST_SIZE 0x2A +#define HCI_OCF_LE_READ_PEER_RES_ADDR 0x2B +#define HCI_OCF_LE_READ_LOCAL_RES_ADDR 0x2C +#define HCI_OCF_LE_SET_ADDR_RES_ENABLE 0x2D +#define HCI_OCF_LE_SET_RES_PRIV_ADDR_TO 0x2E +#define HCI_OCF_LE_READ_MAX_DATA_LEN 0x2F +/* New in version 5.0 */ +#define HCI_OCF_LE_READ_PHY 0x30 +#define HCI_OCF_LE_SET_DEF_PHY 0x31 +#define HCI_OCF_LE_SET_PHY 0x32 +#define HCI_OCF_LE_ENHANCED_RECEIVER_TEST 0x33 +#define HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST 0x34 +#define HCI_OCF_LE_SET_ADV_SET_RAND_ADDR 0x35 +#define HCI_OCF_LE_SET_EXT_ADV_PARAM 0x36 +#define HCI_OCF_LE_SET_EXT_ADV_DATA 0x37 +#define HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA 0x38 +#define HCI_OCF_LE_SET_EXT_ADV_ENABLE 0x39 +#define HCI_OCF_LE_READ_MAX_ADV_DATA_LEN 0x3A +#define HCI_OCF_LE_READ_NUM_SUP_ADV_SETS 0x3B +#define HCI_OCF_LE_REMOVE_ADV_SET 0x3C +#define HCI_OCF_LE_CLEAR_ADV_SETS 0x3D +#define HCI_OCF_LE_SET_PER_ADV_PARAM 0x3E +#define HCI_OCF_LE_SET_PER_ADV_DATA 0x3F +#define HCI_OCF_LE_SET_PER_ADV_ENABLE 0x40 +#define HCI_OCF_LE_SET_EXT_SCAN_PARAM 0x41 +#define HCI_OCF_LE_SET_EXT_SCAN_ENABLE 0x42 +#define HCI_OCF_LE_EXT_CREATE_CONN 0x43 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC 0x44 +#define HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL 0x45 +#define HCI_OCF_LE_PER_ADV_TERM_SYNC 0x46 +#define HCI_OCF_LE_ADD_DEV_PER_ADV_LIST 0x47 +#define HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST 0x48 +#define HCI_OCF_LE_CLEAR_PER_ADV_LIST 0x49 +#define HCI_OCF_LE_READ_PER_ADV_LIST_SIZE 0x4A +#define HCI_OCF_LE_READ_TX_POWER 0x4B +#define HCI_OCF_LE_READ_RF_PATH_COMP 0x4C +#define HCI_OCF_LE_WRITE_RF_PATH_COMP 0x4D +#define HCI_OCF_LE_SET_PRIVACY_MODE 0x4E + +/* Opcode manipulation macros */ +#define HCI_OPCODE(ogf, ocf) (((ogf) << 10) + (ocf)) +#define HCI_OGF(opcode) ((opcode) >> 10) +#define HCI_OCF(opcode) ((opcode) & 0x03FF) + +/* Command opcodes */ +#define HCI_OPCODE_NOP HCI_OPCODE(HCI_OGF_NOP, HCI_OCF_NOP) + +#define HCI_OPCODE_DISCONNECT HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_DISCONNECT) +#define HCI_OPCODE_READ_REMOTE_VER_INFO HCI_OPCODE(HCI_OGF_LINK_CONTROL, HCI_OCF_READ_REMOTE_VER_INFO) + +#define HCI_OPCODE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK) +#define HCI_OPCODE_RESET HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_RESET) +#define HCI_OPCODE_READ_TX_PWR_LVL HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_TX_PWR_LVL) +#define HCI_OPCODE_SET_EVENT_MASK_PAGE2 HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_SET_EVENT_MASK_PAGE2) +#define HCI_OPCODE_READ_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_READ_AUTH_PAYLOAD_TO) +#define HCI_OPCODE_WRITE_AUTH_PAYLOAD_TO HCI_OPCODE(HCI_OGF_CONTROLLER, HCI_OCF_WRITE_AUTH_PAYLOAD_TO) + +#define HCI_OPCODE_READ_LOCAL_VER_INFO HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_VER_INFO) +#define HCI_OPCODE_READ_LOCAL_SUP_CMDS HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_CMDS) +#define HCI_OPCODE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BUF_SIZE) +#define HCI_OPCODE_READ_BD_ADDR HCI_OPCODE(HCI_OGF_INFORMATIONAL, HCI_OCF_READ_BD_ADDR) + +#define HCI_OPCODE_READ_RSSI HCI_OPCODE(HCI_OGF_STATUS, HCI_OCF_READ_RSSI) + +#define HCI_OPCODE_LE_SET_EVENT_MASK HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EVENT_MASK) +#define HCI_OPCODE_LE_READ_BUF_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_BUF_SIZE) +#define HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_SUP_FEAT) +#define HCI_OPCODE_LE_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_PARAM) +#define HCI_OPCODE_LE_READ_ADV_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_ADV_TX_POWER) +#define HCI_OPCODE_LE_SET_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_DATA) +#define HCI_OPCODE_LE_SET_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_SCAN_ENABLE) +#define HCI_OPCODE_LE_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN) +#define HCI_OPCODE_LE_CREATE_CONN_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CREATE_CONN_CANCEL) +#define HCI_OPCODE_LE_READ_WHITE_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_WHITE_LIST_SIZE) +#define HCI_OPCODE_LE_CLEAR_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_WHITE_LIST) +#define HCI_OPCODE_LE_ADD_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_WHITE_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_WHITE_LIST) +#define HCI_OPCODE_LE_CONN_UPDATE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CONN_UPDATE) +#define HCI_OPCODE_LE_SET_HOST_CHAN_CLASS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_HOST_CHAN_CLASS) +#define HCI_OPCODE_LE_READ_CHAN_MAP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_CHAN_MAP) +#define HCI_OPCODE_LE_READ_REMOTE_FEAT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_REMOTE_FEAT) +#define HCI_OPCODE_LE_ENCRYPT HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENCRYPT) +#define HCI_OPCODE_LE_RAND HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RAND) +#define HCI_OPCODE_LE_START_ENCRYPTION HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_START_ENCRYPTION) +#define HCI_OPCODE_LE_LTK_REQ_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_REPL) +#define HCI_OPCODE_LE_LTK_REQ_NEG_REPL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_LTK_REQ_NEG_REPL) +#define HCI_OPCODE_LE_READ_SUP_STATES HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_SUP_STATES) +#define HCI_OPCODE_LE_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_RECEIVER_TEST) +#define HCI_OPCODE_LE_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_TEST_END HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_TEST_END) +/* New in version 4.1 */ +#define HCI_OPCODE_LE_REM_CONN_PARAM_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_REP) +#define HCI_OPCODE_LE_REM_CONN_PARAM_NEG_REP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REM_CONN_PARAM_NEG_REP) +/* New in version 4.2 */ +#define HCI_OPCODE_LE_SET_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DATA_LEN) +#define HCI_OPCODE_LE_READ_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_DEF_DATA_LEN) +#define HCI_OPCODE_LE_WRITE_DEF_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_DEF_DATA_LEN) +#define HCI_OPCODE_LE_READ_LOCAL_P256_PUB_KEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_P256_PUB_KEY) +#define HCI_OPCODE_LE_GENERATE_DHKEY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_GENERATE_DHKEY) +#define HCI_OPCODE_LE_ADD_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_RES_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_RES_LIST) +#define HCI_OPCODE_LE_CLEAR_RES_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_RES_LIST) +#define HCI_OPCODE_LE_READ_RES_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RES_LIST_SIZE) +#define HCI_OPCODE_LE_READ_PEER_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PEER_RES_ADDR) +#define HCI_OPCODE_LE_READ_LOCAL_RES_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_LOCAL_RES_ADDR) +#define HCI_OPCODE_LE_SET_ADDR_RES_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADDR_RES_ENABLE) +#define HCI_OPCODE_LE_SET_RES_PRIV_ADDR_TO HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_RES_PRIV_ADDR_TO) +#define HCI_OPCODE_LE_READ_MAX_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_DATA_LEN) +/* New in version 5.0 */ +#define HCI_OPCODE_LE_READ_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PHY) +#define HCI_OPCODE_LE_SET_DEF_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_DEF_PHY) +#define HCI_OPCODE_LE_SET_PHY HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PHY) +#define HCI_OPCODE_LE_ENHANCED_RECEIVER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_RECEIVER_TEST) +#define HCI_OPCODE_LE_ENHANCED_TRANSMITTER_TEST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ENHANCED_TRANSMITTER_TEST) +#define HCI_OPCODE_LE_SET_ADV_SET_RAND_ADDR HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_ADV_SET_RAND_ADDR) +#define HCI_OPCODE_LE_SET_EXT_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_PARAM) +#define HCI_OPCODE_LE_SET_EXT_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_DATA) +#define HCI_OPCODE_LE_SET_EXT_SCAN_RESP_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_RESP_DATA) +#define HCI_OPCODE_LE_SET_EXT_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_ADV_ENABLE) +#define HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_MAX_ADV_DATA_LEN) +#define HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_NUM_SUP_ADV_SETS) +#define HCI_OPCODE_LE_REMOVE_ADV_SET HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_ADV_SET) +#define HCI_OPCODE_LE_CLEAR_ADV_SETS HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_ADV_SETS) +#define HCI_OPCODE_LE_SET_PER_ADV_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_PARAM) +#define HCI_OPCODE_LE_SET_PER_ADV_DATA HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_DATA) +#define HCI_OPCODE_LE_SET_PER_ADV_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PER_ADV_ENABLE) +#define HCI_OPCODE_LE_SET_EXT_SCAN_PARAM HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_PARAM) +#define HCI_OPCODE_LE_SET_EXT_SCAN_ENABLE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_EXT_SCAN_ENABLE) +#define HCI_OPCODE_LE_EXT_CREATE_CONN HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_EXT_CREATE_CONN) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC) +#define HCI_OPCODE_LE_PER_ADV_CREATE_SYNC_CANCEL HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL) +#define HCI_OPCODE_LE_PER_ADV_TERMINATE_SYNC HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_PER_ADV_TERM_SYNC) +#define HCI_OPCODE_LE_ADD_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_ADD_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_REMOVE_DEV_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_REMOVE_DEV_PER_ADV_LIST) +#define HCI_OPCODE_LE_CLEAR_PER_ADV_LIST HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_CLEAR_PER_ADV_LIST) +#define HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_PER_ADV_LIST_SIZE) +#define HCI_OPCODE_LE_READ_TX_POWER HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_TX_POWER) +#define HCI_OPCODE_LE_WRITE_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_WRITE_RF_PATH_COMP) +#define HCI_OPCODE_LE_READ_RF_PATH_COMP HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_READ_RF_PATH_COMP) +#define HCI_OPCODE_LE_SET_PRIVACY_MODE HCI_OPCODE(HCI_OGF_LE_CONTROLLER, HCI_OCF_LE_SET_PRIVACY_MODE) + +/* ARM Vendor Specific */ +#define HCI_OPCODE_LE_VS_ENABLE_READ_FEAT_ON_CONN ((uint16_t)(0xfff3)) + +/* Command parameter lengths */ +#define HCI_LEN_NOP 0 + +#define HCI_LEN_DISCONNECT 3 +#define HCI_LEN_READ_REMOTE_VER_INFO 2 + +#define HCI_LEN_SET_EVENT_MASK 8 +#define HCI_LEN_SET_EVENT_MASK_PAGE2 8 +#define HCI_LEN_RESET 0 +#define HCI_LEN_READ_TX_PWR_LVL 3 +#define HCI_LEN_SET_CONTROLLER_TO_HOST_FC 1 +#define HCI_LEN_HOST_BUFFER_SIZE 8 +#define HCI_LEN_HOST_NUM_CMPL_PKTS 1 + +#define HCI_LEN_READ_LOCAL_VER_INFO 0 +#define HCI_LEN_READ_LOCAL_SUP_CMDS 0 +#define HCI_LEN_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_READ_BUF_SIZE 0 +#define HCI_LEN_READ_BD_ADDR 0 + +#define HCI_LEN_READ_RSSI 2 +#define HCI_LEN_READ_AUTH_PAYLOAD_TO 2 +#define HCI_LEN_WRITE_AUTH_PAYLOAD_TO 4 + +#define HCI_LEN_LE_SET_EVENT_MASK 8 +#define HCI_LEN_LE_READ_BUF_SIZE 0 +#define HCI_LEN_LE_READ_LOCAL_SUP_FEAT 0 +#define HCI_LEN_LE_SET_RAND_ADDR 6 +#define HCI_LEN_LE_SET_ADV_PARAM 15 +#define HCI_LEN_LE_READ_ADV_TX_POWER 0 +#define HCI_LEN_LE_SET_ADV_DATA 32 +#define HCI_LEN_LE_SET_SCAN_RESP_DATA 32 +#define HCI_LEN_LE_SET_ADV_ENABLE 1 +#define HCI_LEN_LE_SET_SCAN_PARAM 7 +#define HCI_LEN_LE_SET_SCAN_ENABLE 2 +#define HCI_LEN_LE_CREATE_CONN 25 +#define HCI_LEN_LE_CREATE_CONN_CANCEL 0 +#define HCI_LEN_LE_READ_WHITE_LIST_SIZE 0 +#define HCI_LEN_LE_CLEAR_WHITE_LIST 0 +#define HCI_LEN_LE_ADD_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_REMOVE_DEV_WHITE_LIST 7 +#define HCI_LEN_LE_CONN_UPDATE 14 +#define HCI_LEN_LE_SET_HOST_CHAN_CLASS 5 +#define HCI_LEN_LE_READ_CHAN_MAP 2 +#define HCI_LEN_LE_READ_REMOTE_FEAT 2 +#define HCI_LEN_LE_ENCRYPT 32 +#define HCI_LEN_LE_RAND 0 +#define HCI_LEN_LE_START_ENCRYPTION 28 +#define HCI_LEN_LE_LTK_REQ_REPL 18 +#define HCI_LEN_LE_LTK_REQ_NEG_REPL 2 +#define HCI_LEN_LE_READ_SUP_STATES 0 +#define HCI_LEN_LE_RECEIVER_TEST 1 +#define HCI_LEN_LE_TRANSMITTER_TEST 3 +#define HCI_LEN_LE_TEST_END 0 +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REP 14 +#define HCI_LEN_LE_REM_CONN_PARAM_NEG_REP 3 +/* New in version 4.2 */ +#define HCI_LEN_LE_SET_DATA_LEN 6 +#define HCI_LEN_LE_READ_DEF_DATA_LEN 0 +#define HCI_LEN_LE_WRITE_DEF_DATA_LEN 4 +#define HCI_LEN_LE_READ_LOCAL_P256_PUB_KEY 0 +#define HCI_LEN_LE_GENERATE_DHKEY 64 +#define HCI_LEN_LE_ADD_DEV_RES_LIST 39 +#define HCI_LEN_LE_REMOVE_DEV_RES_LIST 7 +#define HCI_LEN_LE_CLEAR_RES_LIST 0 +#define HCI_LEN_LE_READ_RES_LIST_SIZE 0 +#define HCI_LEN_LE_READ_PEER_RES_ADDR 7 +#define HCI_LEN_LE_READ_LOCAL_RES_ADDR 7 +#define HCI_LEN_LE_SET_ADDR_RES_ENABLE 1 +#define HCI_LEN_LE_SET_RES_PRIV_ADDR_TO 2 +#define HCI_LEN_LE_READ_MAX_DATA_LEN 0 +/* New in version 5.0 */ +#define HCI_LEN_LE_READ_PHY 2 +#define HCI_LEN_LE_SET_DEF_PHY 3 +#define HCI_LEN_LE_SET_PHY 7 +#define HCI_LEN_LE_ENHANCED_RECEIVER_TEST 3 +#define HCI_LEN_LE_ENHANCED_TRANSMITTER_TEST 4 +#define HCI_LEN_LE_SET_ADV_SET_RAND_ADDR 7 +#define HCI_LEN_LE_SET_EXT_ADV_PARAM 25 +#define HCI_LEN_LE_SET_EXT_ADV_DATA(len) (4 + (len)) +#define HCI_LEN_LE_SET_EXT_SCAN_RESP_DATA(len) (4 + (len)) +#define HCI_LEN_LE_EXT_ADV_ENABLE(numSets) (2 + (4 * (numSets))) +#define HCI_LEN_LE_READ_MAX_ADV_DATA_LEN 0 +#define HCI_LEN_LE_READ_NUM_OF_SUP_ADV_SETS 0 +#define HCI_LEN_LE_REMOVE_ADV_SET 1 +#define HCI_LEN_LE_CLEAR_ADV_SETS 0 +#define HCI_LEN_LE_SET_PER_ADV_PARAM 7 +#define HCI_LEN_LE_SET_PER_ADV_DATA(len) (3 + (len)) +#define HCI_LEN_LE_SET_PER_ADV_ENABLE 2 +#define HCI_LEN_LE_SET_EXT_SCAN_PARAM(numPhys) (3 + (5 * (numPhys))) +#define HCI_LEN_LE_SET_EXT_SCAN_ENABLE 6 +#define HCI_LEN_LE_EXT_CREATE_CONN(numPhys) (10 + (16 * (numPhys))) +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC 14 +#define HCI_LEN_LE_PER_ADV_CREATE_SYNC_CANCEL 0 +#define HCI_LEN_LE_PER_ADV_TERMINATE_SYNC 2 +#define HCI_LEN_LE_ADD_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_REMOVE_DEV_PER_ADV_LIST 8 +#define HCI_LEN_LE_CLEAR_PER_ADV_LIST 0 +#define HCI_LEN_LE_READ_PER_ADV_LIST_SIZE 0 +#define HCI_LEN_LE_READ_TX_POWER 0 +#define HCI_LEN_LE_READ_RF_PATH_COMP 0 +#define HCI_LEN_LE_WRITE_RF_PATH_COMP 4 +#define HCI_LEN_LE_SET_PRIVACY_MODE 8 + +/* Events */ +#define HCI_DISCONNECT_CMPL_EVT 0x05 +#define HCI_ENC_CHANGE_EVT 0x08 +#define HCI_READ_REMOTE_VER_INFO_CMPL_EVT 0x0C +#define HCI_CMD_CMPL_EVT 0x0E +#define HCI_CMD_STATUS_EVT 0x0F +#define HCI_HW_ERROR_EVT 0x10 +#define HCI_NUM_CMPL_PKTS_EVT 0x13 +#define HCI_DATA_BUF_OVERFLOW_EVT 0x1A +#define HCI_ENC_KEY_REFRESH_CMPL_EVT 0x30 +#define HCI_LE_META_EVT 0x3E +#define HCI_AUTH_PAYLOAD_TIMEOUT_EVT 0x57 +#define HCI_VENDOR_SPEC_EVT 0xFF + +/* LE Subevents */ +#define HCI_LE_CONN_CMPL_EVT 0x01 +#define HCI_LE_ADV_REPORT_EVT 0x02 +#define HCI_LE_CONN_UPDATE_CMPL_EVT 0x03 +#define HCI_LE_READ_REMOTE_FEAT_CMPL_EVT 0x04 +#define HCI_LE_LTK_REQ_EVT 0x05 +/* New in version 4.1 */ +#define HCI_LE_REM_CONN_PARAM_REQ_EVT 0x06 +/* New in version 4.2 */ +#define HCI_LE_DATA_LEN_CHANGE_EVT 0x07 +#define HCI_LE_READ_LOCAL_P256_PUB_KEY_CMPL_EVT 0x08 +#define HCI_LE_GENERATE_DHKEY_CMPL_EVT 0x09 +#define HCI_LE_ENHANCED_CONN_CMPL_EVT 0x0A +#define HCI_LE_DIRECT_ADV_REPORT_EVT 0x0B +/* New in version 5.0 */ +#define HCI_LE_PHY_UPDATE_CMPL_EVT 0x0C +#define HCI_LE_EXT_ADV_REPORT_EVT 0x0D +#define HCI_LE_PER_ADV_SYNC_EST_EVT 0x0E +#define HCI_LE_PER_ADV_REPORT_EVT 0x0F +#define HCI_LE_PER_ADV_SYNC_LOST_EVT 0x10 +#define HCI_LE_SCAN_TIMEOUT_EVT 0x11 +#define HCI_LE_ADV_SET_TERM_EVT 0x12 +#define HCI_LE_SCAN_REQ_RCVD_EVT 0x13 +#define HCI_LE_CH_SEL_ALGO_EVT 0x14 + +/* Event parameter lengths */ +#define HCI_LEN_DISCONNECT_CMPL 4 /*!< Disconnect event length. */ +#define HCI_LEN_READ_REMOTE_VER_INFO_CMPL 8 /*!< Read remove version info complete event length. */ +#define HCI_LEN_CMD_CMPL 3 /*!< Command complete event length. */ +#define HCI_LEN_CMD_STATUS 4 /*!< Command status event length. */ +#define HCI_LEN_HW_ERR 1 /*!< Hardware error event length. */ +#define HCI_LEN_NUM_CMPL_PKTS 5 /*!< Number of completed packets event length. */ +#define HCI_LEN_ENC_CHANGE 4 /*!< Encryption change event length. */ +#define HCI_LEN_ENC_KEY_REFRESH_CMPL 3 /*!< Encryption key refresh complete event length. */ +#define HCI_LEN_LE_CONN_CMPL 19 /*!< Connection complete event length. */ +#define HCI_LEN_LE_ADV_RPT_MIN 12 /*!< Advertising report event minimum length. */ +#define HCI_LEN_LE_CONN_UPDATE_CMPL 10 /*!< Connection update complete event length. */ +#define HCI_LEN_LE_READ_REMOTE_FEAT_CMPL 12 /*!< Read remote feature event length. */ +#define HCI_LEN_LE_LTK_REQ 13 /*!< LTK request event length. */ +/* New in version 4.1 */ +#define HCI_LEN_LE_REM_CONN_PARAM_REQ 11 /*!< Remote connection parameter event length. */ +#define HCI_LEN_LE_DATA_LEN_CHANGE 11 /*!< Data length change event length. */ +#define HCI_LEN_LE_READ_PUB_KEY_CMPL 66 /*!< Read local P256 public key compete event length. */ +#define HCI_LEN_LE_GEN_DHKEY_CMPL 34 /*!< Generate DH key complete event length. */ +#define HCI_LEN_LE_ENHANCED_CONN_CMPL 31 /*!< Enhanced connection complete event length. */ +#define HCI_LEN_LE_DIRECT_ADV_REPORT 18 /*!< Direct advertising report event length. */ +#define HCI_LEN_AUTH_PAYLOAD_TIMEOUT 2 /*!< Authenticated payload timeout event length. */ +/* New in version 5.0 */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_CH_SEL_ALGO 4 /*!< Channel selection algorithm event length. */ +#define HCI_LEN_LE_PHY_UPDATE_CMPL 6 /*!< PHY update complete event length. */ +#define HCI_LEN_LE_EXT_ADV_REPORT_MIN 26 /*!< Extended advertising report minimum length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_EST 16 /*!< Periodic advertising sync established event length. */ +#define HCI_LEN_LE_PER_ADV_REPORT 8 /*!< Periodic advertising report event length. */ +#define HCI_LEN_LE_PER_ADV_SYNC_LOST 3 /*!< Periodic advertising sync lost event length. */ +#define HCI_LEN_LE_SCAN_TIMEOUT 1 /*!< Scan timeout event length. */ +#define HCI_LEN_LE_ADV_SET_TERM 6 /*!< Advertising set terminated event length. */ +#define HCI_LEN_LE_SCAN_REQ_RCVD 9 /*!< Scan request received event length. */ + +/* Supported commands */ +#define HCI_SUP_DISCONNECT 0x20 /* Byte 0 */ +#define HCI_SUP_READ_REMOTE_VER_INFO 0x80 /* Byte 2 */ +#define HCI_SUP_SET_EVENT_MASK 0x40 /* Byte 5 */ +#define HCI_SUP_RESET 0x80 /* Byte 5 */ +#define HCI_SUP_READ_TX_PWR_LVL 0x04 /* Byte 10 */ +#define HCI_SUP_READ_LOCAL_VER_INFO 0x08 /* Byte 14 */ +#define HCI_SUP_READ_LOCAL_SUP_FEAT 0x20 /* Byte 14 */ +#define HCI_SUP_READ_BD_ADDR 0x02 /* Byte 15 */ +#define HCI_SUP_READ_RSSI 0x20 /* Byte 15 */ +#define HCI_SUP_SET_EVENT_MASK_PAGE2 0x04 /* Byte 22 */ +#define HCI_SUP_LE_SET_EVENT_MASK 0x01 /* Byte 25 */ +#define HCI_SUP_LE_READ_BUF_SIZE 0x02 /* Byte 25 */ +#define HCI_SUP_LE_READ_LOCAL_SUP_FEAT 0x04 /* Byte 25 */ +#define HCI_SUP_LE_SET_RAND_ADDR 0x10 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_PARAM 0x20 /* Byte 25 */ +#define HCI_SUP_LE_READ_ADV_TX_POWER 0x40 /* Byte 25 */ +#define HCI_SUP_LE_SET_ADV_DATA 0x80 /* Byte 25 */ +#define HCI_SUP_LE_SET_SCAN_RESP_DATA 0x01 /* Byte 26 */ +#define HCI_SUP_LE_SET_ADV_ENABLE 0x02 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_PARAM 0x04 /* Byte 26 */ +#define HCI_SUP_LE_SET_SCAN_ENABLE 0x08 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN 0x10 /* Byte 26 */ +#define HCI_SUP_LE_CREATE_CONN_CANCEL 0x20 /* Byte 26 */ +#define HCI_SUP_LE_READ_WHITE_LIST_SIZE 0x40 /* Byte 26 */ +#define HCI_SUP_LE_CLEAR_WHITE_LIST 0x80 /* Byte 26 */ +#define HCI_SUP_LE_ADD_DEV_WHITE_LIST 0x01 /* Byte 27 */ +#define HCI_SUP_LE_REMOVE_DEV_WHITE_LIST 0x02 /* Byte 27 */ +#define HCI_SUP_LE_CONN_UPDATE 0x04 /* Byte 27 */ +#define HCI_SUP_LE_SET_HOST_CHAN_CLASS 0x08 /* Byte 27 */ +#define HCI_SUP_LE_READ_CHAN_MAP 0x10 /* Byte 27 */ +#define HCI_SUP_LE_READ_REMOTE_FEAT 0x20 /* Byte 27 */ +#define HCI_SUP_LE_ENCRYPT 0x40 /* Byte 27 */ +#define HCI_SUP_LE_RAND 0x80 /* Byte 27 */ +#define HCI_SUP_LE_START_ENCRYPTION 0x01 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_REPL 0x02 /* Byte 28 */ +#define HCI_SUP_LE_LTK_REQ_NEG_REPL 0x04 /* Byte 28 */ +#define HCI_SUP_LE_READ_SUP_STATES 0x08 /* Byte 28 */ +#define HCI_SUP_LE_RECEIVER_TEST 0x10 /* Byte 28 */ +#define HCI_SUP_LE_TRANSMITTER_TEST 0x20 /* Byte 28 */ +#define HCI_SUP_LE_TEST_END 0x40 /* Byte 28 */ +#define HCI_SUP_READ_AUTH_PAYLOAD_TO 0x10 /* Byte 32 */ +#define HCI_SUP_WRITE_AUTH_PAYLOAD_TO 0x20 /* Byte 32 */ +/* New in version 4.1 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_REPL 0x10 /* Byte 33 */ +#define HCI_SUP_LE_REM_CONN_PARAM_REQ_NEG_REPL 0x20 /* Byte 33 */ +/* New in version 4.2 */ +#define HCI_SUP_LE_SET_DATA_LEN 0x40 /* Byte 33 */ +#define HCI_SUP_LE_READ_DEF_DATA_LEN 0x80 /* Byte 33 */ +#define HCI_SUP_LE_WRITE_DEF_DATA_LEN 0x01 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_P256_PUB_KEY 0x02 /* Byte 34 */ +#define HCI_SUP_LE_GENERATE_DHKEY 0x04 /* Byte 34 */ +#define HCI_SUP_LE_ADD_DEV_RES_LIST_EVT 0x08 /* Byte 34 */ +#define HCI_SUP_LE_REMOVE_DEV_RES_LIST 0x10 /* Byte 34 */ +#define HCI_SUP_LE_CLEAR_RES_LIST 0x20 /* Byte 34 */ +#define HCI_SUP_LE_READ_RES_LIST_SIZE 0x40 /* Byte 34 */ +#define HCI_SUP_LE_READ_PEER_RES_ADDR 0x80 /* Byte 34 */ +#define HCI_SUP_LE_READ_LOCAL_RES_ADDR 0x01 /* Byte 35 */ +#define HCI_SUP_LE_SET_ADDR_RES_ENABLE 0x02 /* Byte 35 */ +#define HCI_SUP_LE_SET_RES_PRIV_ADDR_TO 0x04 /* Byte 35 */ +#define HCI_SUP_LE_READ_MAX_DATA_LEN 0x08 /* Byte 35 */ +/* New in version 5.0 */ +#define HCI_SUP_LE_READ_PHY 0x10 /* Byte 35 */ +#define HCI_SUP_LE_SET_DEF_PHY 0x20 /* Byte 35 */ +#define HCI_SUP_LE_SET_PHY 0x40 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_RECEIVER_TEST 0x80 /* Byte 35 */ +#define HCI_SUP_LE_ENHANCED_TRANSMITTER_TEST 0x01 /* Byte 36 */ +#define HCI_SUP_LE_SET_ADV_SET_RAND_ADDR 0x02 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_PARAM 0x04 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_DATA 0x08 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_SCAN_RESP_DATA 0x10 /* Byte 36 */ +#define HCI_SUP_LE_SET_EXT_ADV_ENABLE 0x20 /* Byte 36 */ +#define HCI_SUP_LE_READ_MAX_ADV_DATA_LEN 0x40 /* Byte 36 */ +#define HCI_SUP_LE_READ_NUM_OF_SUP_ADV_SETS 0x80 /* Byte 36 */ +#define HCI_SUP_LE_REMOVE_ADV_SET 0x01 /* Byte 37 */ +#define HCI_SUP_LE_CLEAR_ADV_SETS 0x02 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_PARAM 0x04 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_DATA 0x08 /* Byte 37 */ +#define HCI_SUP_LE_SET_PER_ADV_ENABLE 0x10 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_PARAM 0x20 /* Byte 37 */ +#define HCI_SUP_LE_SET_EXT_SCAN_ENABLE 0x40 /* Byte 37 */ +#define HCI_SUP_LE_EXT_CREATE_CONN 0x80 /* Byte 37 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC 0x01 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_CREATE_SYNC_CANCEL 0x02 /* Byte 38 */ +#define HCI_SUP_LE_PER_ADV_TERMINATE_SYNC 0x04 /* Byte 38 */ +#define HCI_SUP_LE_ADD_DEV_PER_ADV_LIST 0x08 /* Byte 38 */ +#define HCI_SUP_LE_REMOVE_DEV_PER_ADV_LIST 0x10 /* Byte 38 */ +#define HCI_SUP_LE_CLEAR_PER_ADV_LIST 0x20 /* Byte 38 */ +#define HCI_SUP_LE_READ_PER_ADV_LIST_SIZE 0x40 /* Byte 38 */ +#define HCI_SUP_LE_READ_TX_POWER 0x80 /* Byte 38 */ +#define HCI_SUP_LE_READ_RF_PATH_COMP 0x01 /* Byte 39 */ +#define HCI_SUP_LE_WRITE_RF_PATH_COMP 0x02 /* Byte 39 */ +#define HCI_SUP_LE_SET_PRIVACY_MODE 0x04 /* Byte 39 */ +#define HCI_SUP_LE_SET_MIN_NUM_OF_USED_CH 0x08 /* Byte 39 */ + +/* Event mask */ +#define HCI_EVT_MASK_DISCONNECT_CMPL 0x10 /* Byte 0 */ +#define HCI_EVT_MASK_ENC_CHANGE 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_READ_REMOTE_VER_INFO_CMPL 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_HW_ERROR 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_DATA_BUF_OVERFLOW 0x02 /* Byte 3 */ +#define HCI_EVT_MASK_ENC_KEY_REFRESH_CMPL 0x80 /* Byte 5 */ +#define HCI_EVT_MASK_LE_META 0x20 /* Byte 7 */ + +/* Event mask page 2 */ +#define HCI_EVT_MASK_AUTH_PAYLOAD_TIMEOUT 0x80 /* Byte 2 */ + +/* LE event mask */ +#define HCI_EVT_MASK_LE_CONN_CMPL_EVT 0x01 /* Byte 0 */ +#define HCI_EVT_MASK_LE_ADV_REPORT_EVT 0x02 /* Byte 0 */ +#define HCI_EVT_MASK_LE_CONN_UPDATE_CMPL_EVT 0x04 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_REMOTE_FEAT_CMPL_EVT 0x08 /* Byte 0 */ +#define HCI_EVT_MASK_LE_LTK_REQ_EVT 0x10 /* Byte 0 */ +/* New in version 4.1 */ +#define HCI_EVT_MASK_LE_REMOTE_CONN_PARAM_REQ_EVT 0x20 /* Byte 0 */ +/* New in version 4.2 */ +#define HCI_EVT_MASK_LE_DATA_LEN_CHANGE_EVT 0x40 /* Byte 0 */ +#define HCI_EVT_MASK_LE_READ_LOCAL_P256_PUB_KEY_CMPL 0x80 /* Byte 0 */ +#define HCI_EVT_MASK_LE_GENERATE_DHKEY_CMPL 0x01 /* Byte 1 */ +#define HCI_EVT_MASK_LE_ENHANCED_CONN_CMPL_EVT 0x02 /* Byte 1 */ +#define HCI_EVT_MASK_LE_DIRECT_ADV_REPORT_EVT 0x04 /* Byte 1 */ +/* New in version 5.0 */ +#define HCI_EVT_MASK_LE_PHY_UPDATE_CMPL_EVT 0x08 /* Byte 1 */ +#define HCI_EVT_MASK_LE_EXT_ADV_REPORT_EVT 0x10 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_EST_EVT 0x20 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_REPORT_EVT 0x40 /* Byte 1 */ +#define HCI_EVT_MASK_LE_PER_ADV_SYNC_LOST_EVT 0x80 /* Byte 1 */ +#define HCI_EVT_MASK_LE_SCAN_TIMEOUT_EVT 0x01 /* Byte 2 */ +#define HCI_EVT_MASK_LE_ADV_SET_TERM_EVT 0x02 /* Byte 2 */ +#define HCI_EVT_MASK_LE_SCAN_REQ_RCVD_EVT 0x04 /* Byte 2 */ +#define HCI_EVT_MASK_LE_CH_SEL_ALGO_EVT 0x08 /* Byte 2 */ + +/* LE supported features */ +/* New in version 4.0 */ +#define HCI_LE_SUP_FEAT_ENCRYPTION 0x0001 /*!< Encryption supported */ +/* New in version 4.1 */ +#define HCI_LE_SUP_FEAT_CONN_PARAM_REQ_PROC 0x0002 /*!< Connection Parameters Request Procedure supported */ +#define HCI_LE_SUP_FEAT_EXT_REJECT_IND 0x0004 /*!< Extended Reject Indication supported */ +#define HCI_LE_SUP_FEAT_SLV_INIT_FEAT_EXCH 0x0008 /*!< Slave-Initiated Features Exchange supported */ +#define HCI_LE_SUP_FEAT_LE_PING 0x0010 /*!< LE Ping supported */ +/* New in version 4.2 */ +#define HCI_LE_SUP_FEAT_DATA_LEN_EXT 0x0020 /*!< Data Length Extension supported */ +#define HCI_LE_SUP_FEAT_PRIVACY 0x0040 /*!< LL Privacy supported */ +#define HCI_LE_SUP_FEAT_EXT_SCAN_FILT_POLICY 0x0080 /*!< Extended Scan Filter Policy supported */ +/* New in version 5.0 */ +#define HCI_LE_SUP_FEAT_LE_2M_PHY 0x0100 /*!< LE 2M PHY supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_TRANSMITTER 0x0200 /*!< Stable Modulation Index - Transmitter supported */ +#define HCI_LE_SUP_FEAT_STABLE_MOD_IDX_RECEIVER 0x0400 /*!< Stable Modulation Index - Receiver supported */ +#define HCI_LE_SUP_FEAT_LE_CODED_PHY 0x0800 /*!< LE Coded PHY supported */ +#define HCI_LE_SUP_FEAT_LE_EXT_ADV 0x1000 /*!< LE Extended Advertising supported */ +#define HCI_LE_SUP_FEAT_LE_PER_ADV 0x2000 /*!< LE Periodic Advertising supported */ +#define HCI_LE_SUP_FEAT_CH_SEL_2 0x4000 /*!< Channel Selection Algorithm #2 supported */ +#define HCI_LE_SUP_FEAT_LE_POWER_CLASS_1 0x8000 /*!< LE Power Class 1 supported */ + +/* Advertising command parameters */ +#define HCI_ADV_MIN_INTERVAL 0x0020 /*!< Minimum advertising interval */ +#define HCI_ADV_MAX_INTERVAL 0x4000 /*!< Maximum advertising interval */ +#define HCI_ADV_DIRECTED_MAX_DURATION 0x0500 /*!< Maximum high duty cycle connectable directed advertising duration */ +#define HCI_ADV_TYPE_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT 0x01 /*!< Connectable directed high duty cycle advertising */ +#define HCI_ADV_TYPE_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_TYPE_NONCONN_UNDIRECT 0x03 /*!< Nonconnectable undirected advertising */ +#define HCI_ADV_TYPE_CONN_DIRECT_LO_DUTY 0x04 /*!< Connectable directed low duty cycle advertising */ +#define HCI_ADV_CHAN_37 0x01 /*!< Advertising channel 37 */ +#define HCI_ADV_CHAN_38 0x02 /*!< Advertising channel 38 */ +#define HCI_ADV_CHAN_39 0x04 /*!< Advertising channel 39 */ +#define HCI_ADV_FILT_NONE 0x00 /*!< No scan request or connection filtering */ +#define HCI_ADV_FILT_SCAN 0x01 /*!< White list filters scan requests */ +#define HCI_ADV_FILT_CONN 0x02 /*!< White list filters connections */ +#define HCI_ADV_FILT_ALL 0x03 /*!< White list filters scan req. and conn. */ + +/* Scan command parameters */ +#define HCI_SCAN_TYPE_PASSIVE 0 /*!< Passive scan */ +#define HCI_SCAN_TYPE_ACTIVE 1 /*!< Active scan */ +#define HCI_SCAN_INTERVAL_MIN 0x0004 /*!< Minimum scan interval */ +#define HCI_SCAN_INTERVAL_MAX 0x4000 /*!< Maximum scan interval */ +#define HCI_SCAN_INTERVAL_DEFAULT 0x0010 /*!< Default scan interval */ +#define HCI_SCAN_WINDOW_MIN 0x0004 /*!< Minimum scan window */ +#define HCI_SCAN_WINDOW_MAX 0x4000 /*!< Maximum scan window */ +#define HCI_SCAN_WINDOW_DEFAULT 0x0010 /*!< Default scan window */ + +/* Connection command parameters */ +#define HCI_CONN_INTERVAL_MIN 0x0006 /*!< Minimum connection interval */ +#define HCI_CONN_INTERVAL_MAX 0x0C80 /*!< Maximum connection interval */ +#define HCI_CONN_LATENCY_MAX 0x01F3 /*!< Maximum connection latency */ +#define HCI_SUP_TIMEOUT_MIN 0x000A /*!< Minimum supervision timeout */ +#define HCI_SUP_TIMEOUT_MAX 0x0C80 /*!< Maximum supervision timeout */ + +/* Connection event parameters */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_CLOCK_500PPM 0x00 /*!< 500 ppm clock accuracy */ +#define HCI_CLOCK_250PPM 0x01 /*!< 250 ppm clock accuracy */ +#define HCI_CLOCK_150PPM 0x02 /*!< 150 ppm clock accuracy */ +#define HCI_CLOCK_100PPM 0x03 /*!< 100 ppm clock accuracy */ +#define HCI_CLOCK_75PPM 0x04 /*!< 75 ppm clock accuracy */ +#define HCI_CLOCK_50PPM 0x05 /*!< 50 ppm clock accuracy */ +#define HCI_CLOCK_30PPM 0x06 /*!< 30 ppm clock accuracy */ +#define HCI_CLOCK_20PPM 0x07 /*!< 20 ppm clock accuracy */ + +/* Advertising report event parameters */ +#define HCI_ADV_CONN_UNDIRECT 0x00 /*!< Connectable undirected advertising */ +#define HCI_ADV_CONN_DIRECT 0x01 /*!< Connectable directed advertising */ +#define HCI_ADV_DISC_UNDIRECT 0x02 /*!< Discoverable undirected advertising */ +#define HCI_ADV_NONCONN_UNDIRECT 0x03 /*!< Non-connectable undirected advertising */ +#define HCI_ADV_SCAN_RESPONSE 0x04 /*!< Scan response */ + +/*! Extended advertising data operations */ +#define HCI_ADV_DATA_OP_FRAG_INTER 0x00 /*!< Intermediate fragment */ +#define HCI_ADV_DATA_OP_FRAG_FIRST 0x01 /*!< First fragment */ +#define HCI_ADV_DATA_OP_FRAG_LAST 0x02 /*!< Last fragment */ +#define HCI_ADV_DATA_OP_COMP_FRAG 0x03 /*!< Complete extended advertising data */ +#define HCI_ADV_DATA_OP_UNCHANGED_DATA 0x04 /*!< Unchanged data (just update Advertising DID) */ + +/*! Advertising data fragment preference */ +#define HCI_ADV_DATA_FRAG_PREF_FRAG 0x00 /*!< Controller may fragment all Host advertising data */ +#define HCI_ADV_DATA_FRAG_PREF_NO_FRAG 0x01 /*!< Controller should not fragment nor minimize fragmentation of Host advertising data */ + +/*! Number of advertising sets */ +#define HCI_ADV_NUM_SETS_ALL_DISABLE 0x00 /*!< Disable all advertising sets */ + +/*! Maximum number of scanning or initiating PHYs */ +#define HCI_MAX_NUM_PHYS 3 /*! Maximum number of scanning or initiating PHYs */ + +/*! Advertising PHY values */ +#define HCI_ADV_PHY_LE_1M 0x01 /*!< LE 1M PHY */ +#define HCI_ADV_PHY_LE_2M 0x02 /*!< LE 2M PHY */ +#define HCI_ADV_PHY_LE_CODED 0x03 /*!< LE Coded PHY */ + +/*! Scanner PHY value bits */ +#define HCI_SCAN_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_SCAN_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_SCAN_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Initiator PHY value bits */ +#define HCI_INIT_PHY_LE_1M_BIT (1<<0) /*!< LE 1M PHY */ +#define HCI_INIT_PHY_LE_2M_BIT (1<<1) /*!< LE 2M PHY */ +#define HCI_INIT_PHY_LE_CODED_BIT (1<<2) /*!< LE Coded PHY */ + +/*! Advertising event properties type bits */ +#define HCI_ADV_PROP_CONN_ADV_BIT (1<<0) /*!< Connectable advertising bit */ +#define HCI_ADV_PROP_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising bit */ +#define HCI_ADV_PROP_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising bit */ +#define HCI_ADV_PROP_CONN_DIRECT_ADV_BIT (1<<3) /*!< High duty cycle connectable directed advertising bit */ +#define HCI_ADV_PROP_USE_LEG_PDU_BIT (1<<4) /*!< Use legacy advertising PDUs bit */ +#define HCI_ADV_PROP_OMIT_ADV_ADDR_BIT (1<<5) /*!< Omit advertiser's address from all PDUs (anonymous advertising) bit */ +#define HCI_ADV_PROP_INC_TX_PWR_BIT (1<<6) /*!< Include TxPower in extended header of advertising PDU bit */ + +/*! Advertising event properties for legacy PDUs */ +#define HCI_ADV_PROP_LEG_CONN_UNDIRECT 0x13 /*!< Connectable and scannable undirected advertising (00010011b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT 0x1D /*!< Connectable directed high duty cycle advertising (00011101b) */ +#define HCI_ADV_PROP_LEG_SCAN_UNDIRECT 0x12 /*!< Scannable undirected advertising (00010010b) */ +#define HCI_ADV_PROP_LEG_NONCONN_UNDIRECT 0x10 /*!< Non-connectable and non-scannable undirected advertising (00010000b) */ +#define HCI_ADV_PROP_LEG_CONN_DIRECT_LO_DUTY 0x15 /*!< Connectable directed low duty cycle advertising (00010101b) */ + +/*! Extended advertising report event type bits */ +#define HCI_ADV_RPT_CONN_ADV_BIT (1<<0) /*!< Connectable advertising event bit */ +#define HCI_ADV_RPT_SCAN_ADV_BIT (1<<1) /*!< Scannable advertising event bit */ +#define HCI_ADV_RPT_DIRECT_ADV_BIT (1<<2) /*!< Directed advertising event bit */ +#define HCI_ADV_RPT_SCAN_RSP_BIT (1<<3) /*!< Scan response event bit */ +#define HCI_ADV_RPT_LEG_ADV_BIT (1<<4) /*!< Legacy advertising PDU event bit */ +#define HCI_ADV_RPT_DATA_STATUS_BITS (3<<5) /*!< Data status bits */ + +/*! Advertising report event types for legacy PDUs */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT 0x13 /*! Connectable and scannable undirected advertising (0010011b) */ +#define HCI_ADV_RPT_LEG_CONN_DIRECT 0x15 /*! Connectable directed advertising (0010101b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT 0x12 /*! Scannable undirected advertising (0010010b) */ +#define HCI_ADV_RPT_LEG_NONCONN_UNDIRECT 0x10 /*! Non-connectable and non-scannable undirected advertising (0010000b) */ +#define HCI_ADV_RPT_LEG_CONN_UNDIRECT_SCAN_RSP 0x1B /*! Scan response to connectable and scannable undirected advertising (0011011b) */ +#define HCI_ADV_RPT_LEG_SCAN_UNDIRECT_SCAN_RSP 0x1A /*! Scan response to scannable undirected advertising (0011010b) */ + +/*! Advertising report data status */ +#define HCI_ADV_RPT_DATA_CMPL 0x00 /*!< Data complete */ +#define HCI_ADV_RPT_DATA_INCMPL_MORE 0x01 /*!< Data incomplete, more date to come */ +#define HCI_ADV_RPT_DATA_INCMPL_TRUNC 0x02 /*!< Data incomplete, data truncated, no more date to come */ + +/*! Extended advertising report event primary PHY values */ +#define HCI_ADV_RPT_PHY_PRIM_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_PRIM_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Extended advertising report event seconday PHY values */ +#define HCI_ADV_RPT_PHY_SEC_NONE 0x00 /*!< No packets on seconday advertising channel */ +#define HCI_ADV_RPT_PHY_SEC_LE_1M 0x01 /*!< Advertiser PHY is LE 1M */ +#define HCI_ADV_RPT_PHY_SEC_LE_2M 0x02 /*!< Advertiser PHY is LE 2M */ +#define HCI_ADV_RPT_PHY_SEC_LE_CODED 0x03 /*!< Advertiser PHY is LE Coded */ + +/*! Channel selection algorithm used */ +#define HCI_CH_SEL_ALGO_1 0x00 /*!< LE channel selection algorithm #1 used */ +#define HCI_CH_SEL_ALGO_2 0x01 /*!< LE channel selection algorithm #2 used */ + +/*! Minimum number of used channels */ +#define HCI_MIN_NUM_OF_USED_CHAN 8 /*!< Minimum number of used channels */ + +/* Misc command parameters */ +#define HCI_READ_TX_PWR_CURRENT 0 /*!< Read current tx power */ +#define HCI_READ_TX_PWR_MAX 1 /*!< Read maximum tx power */ +#define HCI_TX_PWR_MIN -30 /*!< Minimum tx power dBm */ +#define HCI_TX_PWR_MAX 20 /*!< Maximum tx power dBm */ +#define HCI_TX_PWR_NO_PREFERENCE 127 /*!< Tx power no preference */ +#define HCI_VERSION 6 /*!< HCI specification version */ +#define HCI_RSSI_MIN -127 /*!< Minimum RSSI dBm */ +#define HCI_RSSI_MAX 20 /*!< Maximum RSSI dBm */ +#define HCI_ADDR_TYPE_PUBLIC 0 /*!< Public device address */ +#define HCI_ADDR_TYPE_RANDOM 1 /*!< Random device address */ +#define HCI_ADDR_TYPE_PUBLIC_IDENTITY 2 /*!< Public identity address */ +#define HCI_ADDR_TYPE_RANDOM_IDENTITY 3 /*!< Random identity address */ +#define HCI_ADDR_TYPE_ANONYMOUS 0xFF /*!< Anonymous device address */ +#define HCI_FILT_NONE 0 /*!< Accept all advertising packets */ +#define HCI_FILT_WHITE_LIST 1 /*!< Accept from While List only */ +#define HCI_FILT_RES_INIT 2 /*!< Accept directed advertisements with RPAs */ +#define HCI_FILT_WHITE_LIST_RES_INIT 3 /*!< Accept from White List or directed advertisements with RPAs */ +#define HCI_FILT_PER_ADV_PARAM 0 /*!< Listen to advertiser specified by create sync command parameters */ +#define HCI_FILT_PER_ADV_LIST 1 /*!< Listen to advertiser from Periodic Advertiser List only */ +#define HCI_ROLE_MASTER 0 /*!< Role is master */ +#define HCI_ROLE_SLAVE 1 /*!< Role is slave */ +#define HCI_PRIV_MODE_NETWORK 0x00 /*!< Network privacy mode (default) */ +#define HCI_PRIV_MODE_DEVICE 0x01 /*!< Device privacy mode */ + +/*! PHY types */ +#define HCI_PHY_NONE 0x00 /*! No selected PHY */ +#define HCI_PHY_LE_1M_BIT (1<<0) /*! LE 1M PHY */ +#define HCI_PHY_LE_2M_BIT (1<<1) /*! LE 2M PHY */ +#define HCI_PHY_LE_CODED_BIT (1<<2) /*! LE Coded PHY */ + +/*! All PHYs preference */ +#define HCI_ALL_PHY_ALL_PREFERENCES 0x00 /*! All PHY preferences */ +#define HCI_ALL_PHY_TX_PREFERENCE_BIT (1<<0) /*! Tx PHY preference */ +#define HCI_ALL_PHY_RX_PREFERENCE_BIT (1<<1) /*! Rx PHY preference */ + +/*! PHY options */ +#define HCI_PHY_OPTIONS_NONE 0x00 /*! No preferences */ + +/* Parameter lengths */ +#define HCI_EVT_MASK_LEN 8 /*!< Length of event mask byte array */ +#define HCI_EVT_MASK_PAGE_2_LEN 8 /*!< Length of event mask page 2 byte array */ +#define HCI_LE_EVT_MASK_LEN 8 /*!< Length of LE event mask byte array */ +#define HCI_FEAT_LEN 8 /*!< Length of features byte array */ +#define HCI_ADV_DATA_LEN 31 /*!< Length of advertising data */ +#define HCI_SCAN_DATA_LEN 31 /*!< Length of scan response data */ +#define HCI_EXT_ADV_DATA_LEN 251 /*!< Length of extended advertising data */ +#define HCI_PER_ADV_DATA_LEN 252 /*!< Length of periodic advertising data */ +#define HCI_EXT_ADV_RPT_DATA_LEN 229 /*!< Length of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN 248 /*!< Length of periodic advertising report data */ +#define HCI_CHAN_MAP_LEN 5 /*!< Length of channel map byte array */ +#define HCI_KEY_LEN 16 /*!< Length of encryption key */ +#define HCI_ENCRYPT_DATA_LEN 16 /*!< Length of data used in encryption */ +#define HCI_RAND_LEN 8 /*!< Length of random number */ +#define HCI_LE_STATES_LEN 8 /*!< Length of LE states byte array */ +#define HCI_P256_KEY_LEN 64 /*!< Length of P256 key */ +#define HCI_DH_KEY_LEN 32 /*!< Length of DH Key */ + +#define HCI_EXT_ADV_RPT_DATA_LEN_OFFSET 23 /*!< Length field offset of extended advertising report data */ +#define HCI_PER_ADV_RPT_DATA_LEN_OFFSET 5 /*!< Length field offset of periodic advertising report data */ + +/* Company ID */ +#define HCI_ID_ARM 0x005F /*! ARM Ltd. company ID */ + +/* Manufacturer location in Local version */ +#define HCI_LOCAL_VER_MANUFACTURER_POS 4 + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h new file mode 100644 index 00000000000..8c00ef377c2 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/include/ll_defs.h @@ -0,0 +1,341 @@ +/*************************************************************************************************/ +/*! + * \file + * + * \brief Link layer constant definitions. + * + * $Date: 2017-03-10 20:10:06 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11511 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ + +#ifndef LL_DEFS_H +#define LL_DEFS_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Constants +**************************************************************************************************/ + +/*** Version ***/ + +#define LL_VER_BT_CORE_SPEC_4_0 0x06 /*!< Bluetooth core specification 4.0 */ +#define LL_VER_BT_CORE_SPEC_4_1 0x07 /*!< Bluetooth core specification 4.1 */ +#define LL_VER_BT_CORE_SPEC_4_2 0x08 /*!< Bluetooth core specification 4.2 */ +#define LL_VER_BT_CORE_SPEC_5_0 0x09 /*!< Bluetooth core specification 5.0 */ + +#define LL_COMP_ID_ARM 0x005F /*!< ARM Ltd. company ID. */ + +/*** Common ***/ + +#define LL_RSSI_MIN -127 /*!< Minimum RSSI value. */ +#define LL_RSSI_MAX 20 /*!< Maximum RSSI value. */ +#define LL_RSSI_NOT_AVAIL 127 /*!< RSSI is not available. */ + +#define LL_CRC_LEN 3 /*!< CRC length. */ +#define LL_AA_LEN 4 /*!< Access address length. */ +#define LL_PREAMBLE_LEN_1M 1 /*!< Preamble length (LE 1M PHY). */ +#define LL_PREAMBLE_LEN_2M 2 /*!< Preamble length (LE 2M PHY). */ +#define LL_PREAMBLE_LEN_CODED_BITS 10 /*!< Preamble length (LE Coded PHY). */ +#define LL_CI_LEN_BITS 2 /*!< Coding indicator length (LE Coded PHY). */ +#define LL_TERM1_LEN_BITS 3 /*!< TERM1 length (LE Coded PHY). */ +#define LL_TERM2_LEN_BITS 3 /*!< TERM2 length (LE Coded PHY). */ + +#define LL_RAND_ADDR_MSBS_MASK 0x03 /*!< Mask of 2 most significant bits of BD Random Address */ +#define LL_RAND_ADDR_MSBS_POS 46 /*!< Position of 2 MSBs of BD Random Address */ +#define LL_RAND_ADDR_MSBS_STATIC 0x03 /*!< 2 most significant bits of BD Random Address are '0b11', static random address */ +#define LL_RAND_ADDR_MSBS_RPA 0x01 /*!< 2 most significant bits of BD Random Address are '0b01', resolvable private address */ +#define LL_RAND_ADDR_MSBS_NRPA 0x00 /*!< 2 most significant bits of BD Random Address are '0b00', non-resolvable private address */ +#define LL_RAND_ADDR_MSBS_IVLD 0x02 /*!< 2 most significant bits of BD Random Address are '0b10', invalid random address */ + +/*** Advertising PDU ***/ + +/*! \brief Advertising channel PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_ADV_IND = 0, /*!< Connectable undirected advertising PDU. */ + LL_PDU_ADV_DIRECT_IND = 1, /*!< Connectable directed advertising PDU. */ + LL_PDU_ADV_NONCONN_IND = 2, /*!< Non-connectable undirected advertising PDU. */ + LL_PDU_SCAN_REQ = 3, /*!< Scan request PDU. */ + LL_PDU_SCAN_RSP = 4, /*!< Scan response PDU. */ + LL_PDU_CONNECT_IND = 5, /*!< Connect indication PDU. */ + LL_PDU_ADV_SCAN_IND = 6, /*!< Scannable undirected advertising PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_AUX_SCAN_REQ = 3, /*!< Auxiliary scan request PDU. */ + LL_PDU_AUX_CONNECT_REQ = 5, /*!< Auxiliary connect request PDU. */ + LL_PDU_ADV_EXT_IND = 7, /*!< Extended advertising PDU. */ + LL_PDU_AUX_ADV_IND = 7, /*!< Auxiliary advertising PDU. */ + LL_PDU_AUX_SCAN_RSP = 7, /*!< Auxiliary scan response PDU. */ + LL_PDU_AUX_SYNC_IND = 7, /*!< Auxiliary synchronize PDU. */ + LL_PDU_AUX_CHAIN_IND = 7, /*!< Auxiliary chain PDU. */ + LL_PDU_AUX_CONNECT_RSP = 8, /*!< Auxiliary connect response PDU. */ +}; + +#define LL_SCAN_REQ_PDU_LEN 12 /*!< Size of a scan request PDU. */ +#define LL_CONN_IND_PDU_LEN 34 /*!< Size of a connect indication PDU. */ + +#define LL_CHAN_ADV_MIN_IDX 37 /*!< Minimum advertising channel index. */ +#define LL_CHAN_ADV_MAX_IDX 39 /*!< Maximum advertising channel index. */ +#define LL_NUM_CHAN_ADV 3 /*!< Total number of advertising channels. */ + +#define LL_ADVBU_MAX_LEN 31 /*!< Maximum advertising channel host data length. */ +#define LL_ADVB_MAX_LEN 39 /*!< Maximum advertising channel PDU length. */ +#define LL_ADVB_MIN_LEN (LL_ADVB_MAX_LEN - LL_ADVBU_MAX_LEN) /*!< Minimum advertising channel packet length. */ +#define LL_ADVB_MAX_TIME_1M ((LL_BLE_US_PER_BYTE_1M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time for a 1M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_2M ((LL_BLE_US_PER_BYTE_2M * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Maximum time for a 2M advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S2 ((LL_BLE_US_PER_BYTE_CODED_S2 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Maximum time for a Coded S2 advertising channel PDU. */ +#define LL_ADVB_MAX_TIME_S8 ((LL_BLE_US_PER_BYTE_CODED_S8 * (LL_ADVB_MAX_LEN - LL_ADV_HDR_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Maximum time for a Coded S8 advertising channel PDU. */ + +#define LL_ADV_PKT_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for an advertising packet. */ +#define LL_SCAN_REQ_MAX_USEC ((8 * (LL_ADV_PREFIX_LEN + LL_SCAN_PREFIX_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Maximum time in microseconds for a scan request packet. */ +#define LL_SCAN_RSP_MAX_USEC LL_ADVB_MAX_TIME_1M /*!< Maximum time in microseconds for a scan response packet. */ + +#define LL_ADV_HDR_LEN 2 /*!< Advertising channel header length. */ +#define LL_ADV_HDR_TYPE_OFFS 0 /*!< Advertising header type offset. */ +#define LL_ADV_HDR_TYPE_MSK 0x0F /*!< Advertising header type mask. */ +#define LL_ADV_HDR_LEN_OFFS 1 /*!< Advertising header length offset. */ +#define LL_ADV_HDR_LEN_MSK 0x3F /*!< Advertising header length mask for 4.2. */ +#define LL_ADV_EXT_HDR_LEN_MSK 0xFF /*!< Advertising extension header length mask for 5.0. */ +#define LL_ADV_PREFIX_LEN 6 /*!< Advertising PDU payload prefix length (AdvA). */ +#define LL_SCAN_PREFIX_LEN 6 /*!< Scan request/response PDU payload prefix length (AdvA). */ + +#define LL_ADV_ACCESS_ADDR UINT32_C(0x8E89BED6) /*!< Advertising channel access address. */ +#define LL_ADV_CRC_INIT UINT32_C(0x555555) /*!< Advertising CRC initial value. */ + +#define LL_DIR_ADV_INTER_TICKS 6 /*!< Advertising interval between directed advertising events (3.75 ms). */ +#define LL_DIR_ADV_DUR_TICKS 2048 /*!< Maximum high duty cycle directed advertising duration (1.28 seconds). */ + +enum +{ + LL_EXT_HDR_ADV_ADDR_BIT = (1 << 0), /*!< Extended header AdvA bit. */ + LL_EXT_HDR_TGT_ADDR_BIT = (1 << 1), /*!< Extended header TargetA bit. */ + LL_EXT_HDR_SUPP_INFO_BIT = (1 << 2), /*!< Extended header SuppInfo bit. */ + LL_EXT_HDR_ADI_BIT = (1 << 3), /*!< Extended header AdvDataInfo bit. */ + LL_EXT_HDR_AUX_PTR_BIT = (1 << 4), /*!< Extended header AuxPtr bit. */ + LL_EXT_HDR_SYNC_INFO_BIT = (1 << 5), /*!< Extended header SyncInfo bit. */ + LL_EXT_HDR_TX_PWR_BIT = (1 << 6), /*!< Extended header TxPower bit. */ +}; + +#define LL_MAX_ADV_HANDEL 0xEF /*!< Maximum advertising handle. */ +#define LL_MAX_ADV_SID 0x0F /*!< Maximum advertising SID */ + + +#define LL_EXT_ADV_HDR_MIN_LEN 1 /*!< Minimum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADV_HDR_MAX_LEN 64 /*!< Maximum extended advertising header length (+1 for ExtHdrLen and AdvMode fields). */ +#define LL_EXT_ADVBU_MAX_LEN 251 /*!< Maximum extended advertising channel PDU host data length. */ +#define LL_EXT_ADVB_MAX_LEN 257 /*!< Maximum extended advertising channel PDU length. */ + +#define LL_AUX_PTR_MAX_USEC 2457600 /*!< Maximum AuxPtr offset value in microseconds. */ + +#define LL_SYNC_MIN_TIMEOUT 0x000A /*!< Minimum synchronization timeout. */ +#define LL_SYNC_MAX_TIMEOUT 0x4000 /*!< Maximum synchronization timeout. */ +#define LL_SYNC_MAX_SKIP 0x01F3 /*!< Maximum synchronization skip. */ +#define LL_SYNC_MAX_HANDLE 0x0EFF /*!< Maximum synchronization handle. */ + +#define LL_PER_ADV_INT_MIN 0x0006 /*!< Minimum periodic advertising interval. */ + + +/*** Data PDU ***/ + +/*! \brief Data channel LL Control PDU types. */ +enum +{ + /* --- Core Spec 4.0 --- */ + LL_PDU_CONN_UPDATE_IND = 0x00, /*!< Connection update indication PDU. */ + LL_PDU_CHANNEL_MAP_IND = 0x01, /*!< Channel map indication PDU. */ + LL_PDU_TERMINATE_IND = 0x02, /*!< Terminate indication PDU. */ + LL_PDU_ENC_REQ = 0x03, /*!< Encryption request PDU. */ + LL_PDU_ENC_RSP = 0x04, /*!< Encryption response PDU. */ + LL_PDU_START_ENC_REQ = 0x05, /*!< Start encryption request PDU. */ + LL_PDU_START_ENC_RSP = 0x06, /*!< Start encryption response PDU. */ + LL_PDU_UNKNOWN_RSP = 0x07, /*!< Unknown response PDU. */ + LL_PDU_FEATURE_REQ = 0x08, /*!< Feature request PDU. */ + LL_PDU_FEATURE_RSP = 0x09, /*!< Feature response PDU. */ + LL_PDU_PAUSE_ENC_REQ = 0x0A, /*!< Pause encryption request PDU. */ + LL_PDU_PAUSE_ENC_RSP = 0x0B, /*!< Pause encryption response PDU. */ + LL_PDU_VERSION_IND = 0x0C, /*!< Version indication PDU. */ + LL_PDU_REJECT_IND = 0x0D, /*!< Reject indication PDU. */ + /* --- Core Spec 4.2 --- */ + LL_PDU_SLV_FEATURE_REQ = 0x0E, /*!< Slave feature request PDU. */ + LL_PDU_CONN_PARAM_REQ = 0x0F, /*!< Connection parameter request PDU. */ + LL_PDU_CONN_PARAM_RSP = 0x10, /*!< Connection parameter response PDU. */ + LL_PDU_REJECT_EXT_IND = 0x11, /*!< Reject extended indication PDU. */ + LL_PDU_PING_REQ = 0x12, /*!< Ping request PDU. */ + LL_PDU_PING_RSP = 0x13, /*!< Ping response PDU. */ + LL_PDU_LENGTH_REQ = 0x14, /*!< Data length request PDU. */ + LL_PDU_LENGTH_RSP = 0x15, /*!< Data length response PDU. */ + /* --- Core Spec 5.0 --- */ + LL_PDU_PHY_REQ = 0x16, /*!< PHY request PDU. */ + LL_PDU_PHY_RSP = 0x17, /*!< PHY response PDU. */ + LL_PDU_PHY_UPDATE_IND = 0x18, /*!< PHY update indication PDU. */ + LL_PDU_MIN_USED_CHAN_IND = 0x19, /*!< Minimum used channels indication PDU. */ + LL_PDU_UNSPECIFIED = 0xFF /*!< Unspecified PDU. */ +}; + +/* Data PDU length */ +/* --- Core Spec 4.0 --- */ +#define LL_CONN_UPD_IND_PDU_LEN 12 /*!< Connection update indication PDU length. */ +#define LL_CHAN_MAP_IND_PDU_LEN 8 /*!< Channel map indication PDU length. */ +#define LL_TERMINATE_IND_PDU_LEN 2 /*!< Terminate indication PDU length. */ +#define LL_ENC_REQ_LEN 23 /*!< Encryption request PDU length. */ +#define LL_ENC_RSP_LEN 13 /*!< Encryption response PDU length. */ +#define LL_START_ENC_LEN 1 /*!< Start encryption request/response PDU length. */ +#define LL_UNKNOWN_RSP_LEN 2 /*!< Unknown response PDU length. */ +#define LL_FEATURE_PDU_LEN 9 /*!< Feature request/response PDU length. */ +#define LL_PAUSE_ENC_LEN 1 /*!< Pause encryption request/response PDU length. */ +#define LL_VERSION_IND_PDU_LEN 6 /*!< Version indication PDU length. */ +#define LL_REJECT_IND_PDU_LEN 2 /*!< Reject indication PDU length. */ +/* --- Core Spec 4.2 --- */ +#define LL_CONN_PARAM_PDU_LEN 24 /*!< Connection parameter request or response PDU length. */ +#define LL_REJECT_EXT_IND_PDU_LEN 3 /*!< Reject extended indication PDU length. */ +#define LL_PING_PDU_LEN 1 /*!< Ping request/response PDU length. */ +#define LL_DATA_LEN_PDU_LEN 9 /*!< Data length request or response PDU length. */ +/* --- Core Spec 5.0 --- */ +#define LL_PHY_PDU_LEN 3 /*!< PHY request/response PDU length. */ +#define LL_PHY_UPD_IND_PDU_LEN 5 /*!< PHY update indication PDU length. */ +#define LL_MIN_USED_CHAN_PDU_LEN 3 /*!< Minimum used channels indication PDU length. */ + +#define LL_EMPTY_PDU_LEN 2 /*!< Length of an empty data PDU. */ + +#define LL_DATA_HDR_LEN 2 /*!< Data channel header length. */ +#define LL_DATA_MIC_LEN 4 /*!< Data channel PDU MIC length. */ + +#define LL_DATA_HDR_LLID_MSK 0x03 /*!< Data PDU LLID mask. */ +#define LL_DATA_HDR_LEN_MSK 0xFF /*!< Data header length mask. BLE 4.2 data len extension allows 8 bits. */ + +#define LL_MAX_NUM_CHAN_DATA 37 /*!< Maximum number of used data channels. */ +#define LL_MIN_NUM_CHAN_DATA 2 /*!< Minimum number of used data channels. */ + +/*! \brief Data PDU LLID types. */ +enum +{ + LL_LLID_VS_PDU = 0x00, /*!< Vendor specific PDU. */ + /* N.B. next two enumerations intentionally use identical values. */ + LL_LLID_EMPTY_PDU = 0x01, /*!< Empty PDU. */ + LL_LLID_CONT_PDU = 0x01, /*!< Data PDU: continuation fragment of an L2CAP message. */ + LL_LLID_START_PDU = 0x02, /*!< Data PDU: start of an L2CAP message or a complete L2CAP message with no fragmentation. */ + LL_LLID_CTRL_PDU = 0x03, /*!< Control PDU. */ +}; + +/*** Encryption ***/ + +#define LL_ECC_KEY_LEN 32 /*!< ECC key length. */ + +#define LL_DEF_RES_ADDR_TO_SEC 900 /*!< Default resolvable address timeout in seconds. */ + +#define LL_RAND_LEN 8 /*!< Length of random number */ +#define LL_KEY_LEN 16 /*!< Encryption key length. */ +#define LL_SKD_LEN LL_KEY_LEN /*!< Session key diversifier length. */ +#define LL_IV_LEN 8 /*!< Initialization vector length. */ + +#define LL_DEF_AUTH_TO_MS 30000 /*!< Default authentication timeout in milliseconds. */ + +/*** LLCP ***/ + +#define LL_DATA_LEN_TO_TIME_1M(len) ((LL_BLE_US_PER_BYTE_1M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_1M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_2M(len) ((LL_BLE_US_PER_BYTE_2M * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_2M) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S8(len) ((LL_BLE_US_PER_BYTE_CODED_S8 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S8) + /*!< Convert data length to time. */ +#define LL_DATA_LEN_TO_TIME_CODED_S2(len) ((LL_BLE_US_PER_BYTE_CODED_S2 * ((len) + LL_DATA_MIC_LEN)) + LL_MIN_PKT_TIME_US_CODED_S2) + /*!< Convert data length to time. */ + +#define LL_MIN_INSTANT 6 /*!< Minimum number of CE to apply a CONN_UPD or CHAN_MAP. */ + +#define LL_MAX_DATA_LEN_MIN 27 /*!< Minimum value for maximum Data PDU length */ +#define LL_MAX_DATA_LEN_ABS_MAX 251 /*!< Absolute maximum limit for maximum Data PDU length */ + +#define LL_MAX_DATA_TIME_MIN 328 /*!< Minimum value for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX 17040 /*!< Absolute maximum limit for maximum Data PDU time */ +#define LL_MAX_DATA_TIME_ABS_MAX_1M 2120 /*!< Absolute maximum limit for maximum Data PDU time (LE 1M PHY) */ + +#define LL_T_PRT_SEC 40 /*!< LLCP procedure response timeout in seconds. */ + +#define LL_MAX_ADV_DLY_MS 10 /*!< Maximum advertising delay in milliseconds. */ + +#define LL_MIN_CONN_INTERVAL 6 /*!< Minimum value for connection interval. */ +#define LL_MAX_CONN_INTERVAL 3200 /*!< Maximum value for connection interval. */ + +#define LL_MIN_TX_WIN_SIZE 1 /*!< Minimum value for transmit window size. */ +#define LL_MAX_TX_WIN_SIZE 8 /*!< Maximum value for transmit window size. */ + +#define LL_MAX_CONN_LATENCY 499 /*!< Maximum value for connection slave latency. */ + +#define LL_MIN_SUP_TIMEOUT 10 /*!< Minimum value for connection supervision timeout. */ +#define LL_MAX_SUP_TIMEOUT 3200 /*!< Maximum value for connection supervision timeout. */ + +#define LL_MIN_POWER_THRESHOLD -128 /*!< Minimum value for power threshold. */ +#define LL_MAX_POWER_THRESHOLD 127 /*!< Maximum value for power threshold. */ + +#define LL_ALL_PHYS_MSK 0x7 /*!< All supported LE PHYs mask. */ + +/*** DTM ***/ + +#define LL_DTM_HDR_LEN 2 /*!< Direct Test Mode PDU header length. */ +#define LL_DTM_SYNC_WORD UINT32_C(0x71764129) /*!< Direct Test Mode sync word. */ +#define LL_DTM_CRC_INIT UINT32_C(0x555555) /*!< Direct Test Mode CRC initial value. */ +#define LL_DTM_MAX_INT_US 12500 /*!< Maximum time interval between packets in microseconds. */ +#define LL_DTM_PDU_ABS_MAX_LEN 255 /*!< Absolute maximum DTM PDU length. */ +#define LL_DTM_MAX_CHAN_IDX 39 /*!< Maximum channel index. */ + +/*** Baseband ***/ + +#define LL_CHAN_DATA_MIN_IDX 0 /*!< Minimum data channel index. */ +#define LL_CHAN_DATA_MAX_IDX 36 /*!< Maximum data channel index. */ +#define LL_CHAN_DATA_ALL UINT64_C(0x0000001FFFFFFFFF) /*!< Maximum data channel index. */ + +#define LL_BLE_BIT_PER_US 1 /*!< BLE PHY rate. */ +#define LL_BLE_US_PER_BYTE_1M 8 /*!< BLE PHY speed (LE 1M PHY). */ +#define LL_BLE_US_PER_BYTE_2M 4 /*!< BLE PHY speed (LE 2M PHY). */ +#define LL_BLE_US_PER_BYTE_CODED_S8 64 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BIT_CODED_S8 8 /*!< BLE PHY speed (LE Coded PHY, S=8). */ +#define LL_BLE_US_PER_BYTE_CODED_S2 16 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_US_PER_BIT_CODED_S2 2 /*!< BLE PHY speed (LE Coded PHY, S=2). */ +#define LL_BLE_TIFS_US 150 /*!< BLE inter-frame space. */ +#define LL_BLE_MAFS_US 300 /*!< BLE minimum AUX frame space. */ +#define LL_BLE_US_PER_TICK 625 /*!< Microseconds per BLE tick. */ + +#define LL_MIN_PKT_TIME_US_1M 80 /*!< Minimum packet time (i.e. empty PDU) on LE 1M PHY. */ +#define LL_MIN_PKT_TIME_US_2M 44 /*!< Minimum packet time (i.e. empty PDU) on LE 2M PHY. */ +#define LL_MIN_PKT_TIME_US_CODED_S8 720 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=8. */ +#define LL_MIN_PKT_TIME_US_CODED_S2 462 /*!< Minimum packet time (i.e. empty PDU) on LE Coded PHY, S=2. */ + +#define LL_MIN_ADV_TX_PWR_LVL -20 /*!< Minimum Tx power level for advertising. */ +#define LL_MAX_ADV_TX_PWR_LVL 10 /*!< Maximum Tx power level for advertising. */ + +#define LL_MIN_TX_PWR_LVL -30 /*!< Minimum Tx power level for connections. */ +#define LL_MAX_TX_PWR_LVL 20 /*!< Maximum Tx power level for connections. */ + +#define LL_MAX_TIFS_DEVIATION 2 /*!< Maximum TIFS deviation in microseconds. */ + +#ifdef __cplusplus +}; +#endif + +#endif /* LL_DEFS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h new file mode 100644 index 00000000000..7948f672ed8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bda.h @@ -0,0 +1,143 @@ +/*************************************************************************************************/ +/*! + * \file bda.h + * + * \brief Bluetooth device address utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BDA_H +#define BDA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief BD address length */ +#define BDA_ADDR_LEN 6 + +/*! \brief BD address string length */ +#define BDA_ADDR_STR_LEN (BDA_ADDR_LEN * 2) + +/*! \brief BDA RPA check */ +#define BDA_ADDR_IS_RPA(bda) (((bda)[5] & 0xC0) == 0x40) + +/*! \brief BDA NRPA check */ +#define BDA_ADDR_IS_NRPA(bda) (((bda)[5] & 0xC0) == 0x00) + +/*! \brief BDA static random check */ +#define BDA_ADDR_IS_STATIC(bda) (((bda)[5] & 0xC0) == 0xC0) + +/*! \brief BDA64 RPA check */ +#define BDA64_ADDR_IS_RPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x40) + +/*! \brief BDA64 NRPA check */ +#define BDA64_ADDR_IS_NRPA(bda64) ((((bda64) >> 40) & 0xC0) == 0x00) + +/*! \brief BDA64 static random check */ +#define BDA64_ADDR_IS_STATIC(bda64) ((((bda64) >> 40) & 0xC0) == 0xC0) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! \brief BD address data type */ +typedef uint8_t bdAddr_t[BDA_ADDR_LEN]; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn BdaCpy + * + * \brief Copy a BD address from source to destination. + * + * \param pDst Pointer to destination. + * \param pSrc Pointer to source. + * + * \return None. + */ +/*************************************************************************************************/ +void BdaCpy(uint8_t *pDst, const uint8_t *pSrc); + + +/*************************************************************************************************/ +/*! + * \fn BdaCmp + * + * \brief Compare two BD addresses. + * + * \param pAddr1 First address. + * \param pAddr2 Second address. + * + * \return TRUE if addresses match, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t BdaCmp(const uint8_t *pAddr1, const uint8_t *pAddr2); + +/*************************************************************************************************/ +/*! + * \fn BdaClr + * + * \brief Set a BD address to all zeros. + * + * \param pDst Pointer to destination. + * + * \return pDst + BDA_ADDR_LEN + */ +/*************************************************************************************************/ +uint8_t *BdaClr(uint8_t *pDst); + +/*************************************************************************************************/ +/*! +* \fn BdaIsZeros +* +* \brief Check if a BD address is all zeros. +* +* \param pAddr Pointer to address. +* +* \return TRUE if address is all zeros, FALSE otherwise. +*/ +/*************************************************************************************************/ +bool_t BdaIsZeros(const uint8_t *pAddr); + +/*************************************************************************************************/ +/*! + * \fn Bda2Str + * + * \brief Convert a BD address to a string. + * + * \param pAddr Pointer to BD address. + * + * \return Pointer to string. + */ +/*************************************************************************************************/ +char *Bda2Str(const uint8_t *pAddr); + +#ifdef __cplusplus +}; +#endif + +#endif /* BDA_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h new file mode 100644 index 00000000000..a8749b340fe --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/util/bstream.h @@ -0,0 +1,152 @@ +/*************************************************************************************************/ +/*! + * \file bstream.h + * + * \brief Byte stream to integer conversion macros. + * + * $Date: 2017-02-06 19:25:09 -0600 (Mon, 06 Feb 2017) $ + * $Revision: 11104 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef BSTREAM_H +#define BSTREAM_H + +#include "bda.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! + * Macros for converting a little endian byte buffer to integers. + */ +#define BYTES_TO_UINT16(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8));} + +#define BYTES_TO_UINT24(n, p) {n = ((uint16_t)(p)[0] + ((uint16_t)(p)[1] << 8) + \ + ((uint16_t)(p)[2] << 16));} + +#define BYTES_TO_UINT32(n, p) {n = ((uint32_t)(p)[0] + ((uint32_t)(p)[1] << 8) + \ + ((uint32_t)(p)[2] << 16) + ((uint32_t)(p)[3] << 24));} + +#define BYTES_TO_UINT40(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32));} + +#define BYTES_TO_UINT64(n, p) {n = ((uint64_t)(p)[0] + ((uint64_t)(p)[1] << 8) + \ + ((uint64_t)(p)[2] << 16) + ((uint64_t)(p)[3] << 24) + \ + ((uint64_t)(p)[4] << 32) + ((uint64_t)(p)[5] << 40) + \ + ((uint64_t)(p)[6] << 48) + ((uint64_t)(p)[7] << 56));} + +/*! + * Macros for converting little endian integers to array of bytes + */ +#define UINT16_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)) +#define UINT32_TO_BYTES(n) ((uint8_t) (n)), ((uint8_t)((n) >> 8)), ((uint8_t)((n) >> 16)), ((uint8_t)((n) >> 24)) + +/*! + * Macros for converting little endian integers to single bytes + */ +#define UINT16_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT16_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) + +#define UINT32_TO_BYTE0(n) ((uint8_t) (n)) +#define UINT32_TO_BYTE1(n) ((uint8_t) ((n) >> 8)) +#define UINT32_TO_BYTE2(n) ((uint8_t) ((n) >> 16)) +#define UINT32_TO_BYTE3(n) ((uint8_t) ((n) >> 24)) + +/*! + * Macros for converting a little endian byte stream to integers, with increment. + */ +#define BSTREAM_TO_INT8(n, p) {n = (int8_t)(*(p)++);} +#define BSTREAM_TO_UINT8(n, p) {n = (uint8_t)(*(p)++);} +#define BSTREAM_TO_UINT16(n, p) {BYTES_TO_UINT16(n, p); p += 2;} +#define BSTREAM_TO_UINT24(n, p) {BYTES_TO_UINT24(n, p); p += 3;} +#define BSTREAM_TO_UINT32(n, p) {BYTES_TO_UINT32(n, p); p += 4;} +#define BSTREAM_TO_UINT40(n, p) {BYTES_TO_UINT40(n, p); p += 5;} +#define BSTREAM_TO_UINT64(n, p) {n = BstreamToUint64(p); p += 8;} +#define BSTREAM_TO_BDA(bda, p) {BdaCpy(bda, p); p += BDA_ADDR_LEN;} +#define BSTREAM_TO_BDA64(bda, p) {bda = BstreamToBda64(p); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, with increment. + */ +#define UINT8_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n);} +#define UINT16_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8);} +#define UINT24_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16);} +#define UINT32_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24);} +#define UINT40_TO_BSTREAM(p, n) {*(p)++ = (uint8_t)(n); *(p)++ = (uint8_t)((n) >> 8); \ + *(p)++ = (uint8_t)((n) >> 16); *(p)++ = (uint8_t)((n) >> 24); \ + *(p)++ = (uint8_t)((n) >> 32);} +#define UINT64_TO_BSTREAM(p, n) {Uint64ToBstream(p, n); p += sizeof(uint64_t);} +#define BDA_TO_BSTREAM(p, bda) {BdaCpy(p, bda); p += BDA_ADDR_LEN;} +#define BDA64_TO_BSTREAM(p, bda) {Bda64ToBstream(p, bda); p += BDA_ADDR_LEN;} + +/*! + * Macros for converting integers to a little endian byte stream, without increment. + */ +#define UINT16_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8);} +#define UINT24_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16);} +#define UINT32_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);} +#define UINT40_TO_BUF(p, n) {(p)[0] = (uint8_t)(n); (p)[1] = (uint8_t)((n) >> 8); \ + (p)[2] = (uint8_t)((n) >> 16); (p)[3] = (uint8_t)((n) >> 24);\ + (p)[4] = (uint8_t)((n) >> 32);} + +/*! + * Macros for comparing a little endian byte buffer to integers. + */ +#define BYTES_UINT16_CMP(p, n) ((p)[1] == UINT16_TO_BYTE1(n) && (p)[0] == UINT16_TO_BYTE0(n)) + +/*! + * Macros for IEEE FLOAT type: exponent = byte 3, mantissa = bytes 2-0 + */ +#define FLT_TO_UINT32(m, e) ((m) | ((int32_t)(e) << 24)) +#define UINT32_TO_FLT(m, e, n) {m = UINT32_TO_FLT_M(n); e = UINT32_TO_FLT_E(n);} +#define UINT32_TO_FLT_M(n) ((((n) & 0x00FFFFFF) >= 0x00800000) ? \ + ((int32_t)(((n) | 0xFF000000))) : ((int32_t)((n) & 0x00FFFFFF))) +#define UINT32_TO_FLT_E(n) ((int8_t)(n >> 24)) +/*! + * Macros for IEEE SFLOAT type: exponent = bits 15-12, mantissa = bits 11-0 + */ +#define SFLT_TO_UINT16(m, e) ((m) | ((int16_t)(e) << 12)) +#define UINT16_TO_SFLT(m, e, n) {m = UINT16_TO_SFLT_M(n); e = UINT16_TO_SFLT_E(n);} +#define UINT16_TO_SFLT_M(n) ((((n) & 0x0FFF) >= 0x0800) ? \ + ((int16_t)(((n) | 0xF000))) : ((int16_t)((n) & 0x0FFF))) +#define UINT16_TO_SFLT_E(n) (((n >> 12) >= 0x0008) ? \ + ((int8_t)(((n >> 12) | 0xF0))) : ((int8_t)(n >> 12))) + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +uint64_t BstreamToBda64(const uint8_t *p); +uint64_t BstreamToUint64(const uint8_t *p); +void Bda64ToBstream(uint8_t *p, uint64_t bda); +void Uint64ToBstream(uint8_t *p, uint64_t n); + +#ifdef __cplusplus +}; +#endif + +#endif /* BSTREAM_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h new file mode 100644 index 00000000000..69b40254f5f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_os_int.h @@ -0,0 +1,108 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os_int.h + * + * \brief Software foundation OS platform-specific interface file. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_INT_H +#define WSF_OS_INT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Task events */ +#define WSF_MSG_QUEUE_EVENT 0x01 /* Message queued for event handler */ +#define WSF_TIMER_EVENT 0x02 /* Timer expired for event handler */ +#define WSF_HANDLER_EVENT 0x04 /* Event set for event handler */ + +/* Derive task from handler ID */ +#define WSF_TASK_FROM_ID(handlerID) (((handlerID) >> 4) & 0x0F) + +/* Derive handler from handler ID */ +#define WSF_HANDLER_FROM_ID(handlerID) ((handlerID) & 0x0F) + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Event handler ID data type */ +typedef uint8_t wsfHandlerId_t; + +/* Event handler event mask data type */ +typedef uint8_t wsfEventMask_t; + +/* Task ID data type */ +typedef wsfHandlerId_t wsfTaskId_t; + +/* Task event mask data type */ +typedef uint8_t wsfTaskEvent_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfOsReadyToSleep + * + * \brief Check if WSF is ready to sleep. + * + * \param None. + * + * \return Return TRUE if there are no pending WSF task events set, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t wsfOsReadyToSleep(void); + +/*************************************************************************************************/ +/*! + * \fn wsfOsDispatcher + * + * \brief Event dispatched. Designed to be called repeatedly from infinite loop. + * + * \param None. + * + * \return None. + */ +/*************************************************************************************************/ +void wsfOsDispatcher(void); + +/*************************************************************************************************/ +/*! + * \fn WsfOsShutdown + * + * \brief Shutdown OS. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfOsShutdown(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_INT_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h new file mode 100644 index 00000000000..0347086c06f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/generic/wsf_types.h @@ -0,0 +1,66 @@ +/*************************************************************************************************/ +/*! + * \file wsf_types.h + * + * \brief Platform-independent data types. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TYPES_H +#define WSF_TYPES_H + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/* Integer data types */ +#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \ + (!defined(__ICC8051__) || (__ICC8051__ == 0))) || \ + defined(__CC_ARM) || defined(__IAR_SYSTEMS_ICC__) +#include +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +#endif + +/* Boolean data type */ +typedef uint8_t bool_t; + +#endif /* WSF_TYPES_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h new file mode 100644 index 00000000000..e15476ed4ba --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_buf.h @@ -0,0 +1,199 @@ +/*************************************************************************************************/ +/*! + * \file wsf_buf.h + * + * \brief Buffer pool service. + * + * $Date: 2017-03-04 13:45:34 -0600 (Sat, 04 Mar 2017) $ + * $Revision: 11379 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_BUF_H +#define WSF_BUF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Length of the buffer statistics array */ +#define WSF_BUF_STATS_MAX_LEN 128 + +/*! Failure Codes */ +#define WSF_BUF_ALLOC_FAILED 0x01 + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Buffer pool descriptor structure */ +typedef struct +{ + uint16_t len; /*! length of buffers in pool */ + uint8_t num; /*! number of buffers in pool */ +} wsfBufPoolDesc_t; + +/*! Pool statistics */ +typedef struct +{ + uint16_t bufSize; /*!< Pool buffer size. */ + uint8_t numBuf; /*!< Total number of buffers. */ + uint8_t numAlloc; /*!< Number of outstanding allocations. */ + uint8_t maxAlloc; /*!< High allocation watermark. */ + uint16_t maxReqLen; /*!< Maximum requested buffer length. */ +} WsfBufPoolStat_t; + +/*! WSF buffer diagnostics - buffer allocation failure */ +typedef struct +{ + uint8_t taskId; /*! Task handler ID where failure occured */ + uint16_t len; /*! Length of buffer being allocated */ +} wsfBufDiagAllocFail_t; + +/*! WSF buffer diagnostics message */ +typedef struct +{ + union + { + wsfBufDiagAllocFail_t alloc; /*! Buffer allocation failure */ + } param; + + uint8_t type; /*! Type of error */ +} WsfBufDiag_t; + +/************************************************************************************************** + Callback Function Datatypes +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfBufDiagCback_t + * + * \brief Callback providing WSF buffer diagnostic messages. + * + * \param pInfo Diagnostics message + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfBufDiagCback_t)(WsfBufDiag_t *pInfo); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfBufInit + * + * \brief Initialize the buffer pool service. This function should only be called once + * upon system initialization. + * + * \param bufMemLen Length in bytes of memory pointed to by pBufMem. + * \param pBufMem Memory in which to store the pools used by the buffer pool service. + * \param numPools Number of buffer pools. + * \param pDesc Array of buffer pool descriptors, one for each pool. + * + * \return Amount of pBufMem used or 0 for failures. + */ +/*************************************************************************************************/ +uint16_t WsfBufInit(uint16_t bufMemLen, uint8_t *pBufMem, uint8_t numPools, const wsfBufPoolDesc_t *pDesc); + +/*************************************************************************************************/ +/*! + * \fn WsfBufAlloc + * + * \brief Allocate a buffer. + * + * \param len Length of buffer to allocate. + * + * \return Pointer to allocated buffer or NULL if allocation fails. + */ +/*************************************************************************************************/ +void *WsfBufAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfBufFree + * + * \brief Free a buffer. + * + * \param pBuf Buffer to free. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufFree(void *pBuf); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetAllocStats + * + * \brief Diagnostic function to get the buffer allocation statistics. + * + * \return Buffer allocation statistics array. + */ +/*************************************************************************************************/ +uint8_t *WsfBufGetAllocStats(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetNumPool + * + * \brief Get number of pools. + * + * \return Number of pools. + */ +/*************************************************************************************************/ +uint8_t WsfBufGetNumPool(void); + +/*************************************************************************************************/ +/*! + * \fn WsfBufGetPoolStats + * + * \brief Get statistics for each pool. + * + * \param pStat Buffer to store the statistics. + * \param numPool Number of pool elements. + * + * \return Pool statistics. + */ +/*************************************************************************************************/ +void WsfBufGetPoolStats(WsfBufPoolStat_t *pStat, uint8_t numPool); + +/*************************************************************************************************/ +/*! + * \fn WsfBufDiagRegister + * + * \brief Called to register the buffer diagnostics callback function. + * + * \param pCallback Pointer to the callback function. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfBufDiagRegister(wsfBufDiagCback_t callback); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_BUF_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h new file mode 100644 index 00000000000..abc7c112adc --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_math.h @@ -0,0 +1,48 @@ +/*************************************************************************************************/ +/*! + * \file wsf_math.h + * + * \brief Common math utilities. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2013-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MATH_H +#define WSF_MATH_H + +#include "wsf_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! \brief Returns the minimum of two values. */ +#define WSF_MIN(a,b) ((a) < (b) ? (a) : (b)) + +/*! \brief Returns the maximum of two values. */ +#define WSF_MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MATH_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h new file mode 100644 index 00000000000..7235130f4fa --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_msg.h @@ -0,0 +1,140 @@ +/*************************************************************************************************/ +/*! + * \file wsf_msg.h + * + * \brief Message passing service. + * + * $Date: 2017-03-10 14:08:37 -0600 (Fri, 10 Mar 2017) $ + * $Revision: 11501 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_MSG_H +#define WSF_MSG_H + +#include "wsf_queue.h" +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDataAlloc + * + * \brief Allocate a data message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * \param tailroom Tailroom length in bytes. + * + * \return Pointer to data message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgDataAlloc(uint16_t len, uint8_t tailroom); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgAlloc + * + * \brief Allocate a message buffer to be sent with WsfMsgSend(). + * + * \param len Message length in bytes. + * + * \return Pointer to message buffer or NULL if allocation failed. + */ +/*************************************************************************************************/ +void *WsfMsgAlloc(uint16_t len); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgFree + * + * \brief Free a message buffer allocated with WsfMsgAlloc(). + * + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgFree(void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgSend + * + * \brief Send a message to an event handler. + * + * \param handlerId Event handler ID. + * \param pMsg Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgSend(wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgEnq + * + * \brief Enqueue a message. + * + * \param pQueue Pointer to queue. + * \param handerId Set message handler ID to this value. + * \param pElem Pointer to message buffer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfMsgEnq(wsfQueue_t *pQueue, wsfHandlerId_t handlerId, void *pMsg); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgDeq + * + * \brief Dequeue a message. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to message that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgDeq(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfMsgPeek + * + * \brief Get the next message without removing it from the queue. + * + * \param pQueue Pointer to queue. + * \param pHandlerId Handler ID of returned message; this is a return parameter. + * + * \return Pointer to the next message on the queue or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfMsgPeek(wsfQueue_t *pQueue, wsfHandlerId_t *pHandlerId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MSG_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h new file mode 100644 index 00000000000..0ad337556d5 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_os.h @@ -0,0 +1,179 @@ +/*************************************************************************************************/ +/*! + * \file wsf_os.h + * + * \brief Software foundation OS API. + * + * $Date: 2017-03-02 16:50:43 -0600 (Thu, 02 Mar 2017) $ + * $Revision: 11350 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_OS_H +#define WSF_OS_H + +#include "wsf_os_int.h" +#include "wsf_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Configuration +**************************************************************************************************/ + +/* OS Diagnistics */ +#ifndef WSF_OS_DIAG +#define WSF_OS_DIAG FALSE +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/* Invalid Task Identifier */ +#define WSF_INVALID_TASK_ID 0xFF + +#if WSF_OS_DIAG == TRUE +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WsfActiveHandler +#else +#define WSF_OS_GET_ACTIVE_HANDLER_ID() WSF_INVALID_TASK_ID +#endif /* WSF_OS_DIAG */ + +/************************************************************************************************** + External Variables +**************************************************************************************************/ + +/* Diagnistic Task Identifier */ +extern wsfHandlerId_t WsfActiveHandler; + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Common message structure passed to event handler */ +typedef struct +{ + uint16_t param; /*! General purpose parameter passed to event handler */ + uint8_t event; /*! General purpose event value passed to event handler */ + uint8_t status; /*! General purpose status value passed to event handler */ +} wsfMsgHdr_t; + +/************************************************************************************************** + Callback Function Types +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn wsfEventHandler_t + * + * \brief Event handler callback function. + * + * \param event Mask of events set for the event handler. + * \param pMsg Pointer to message for the event handler. + * + * \return None. + */ +/*************************************************************************************************/ +typedef void (*wsfEventHandler_t)(wsfEventMask_t event, wsfMsgHdr_t *pMsg); + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfSetEvent + * + * \brief Set an event for an event handler. + * + * \param handlerId Handler ID. + * \param event Event or events to set. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfSetEvent(wsfHandlerId_t handlerId, wsfEventMask_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskLock + * + * \brief Lock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskLock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskUnlock + * + * \brief Unlock task scheduling. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskUnlock(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskSetReady + * + * \brief Set the task used by the given handler as ready to run. + * + * \param handlerId Event handler ID. + * \param event Task event mask. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTaskSetReady(wsfHandlerId_t handlerId, wsfTaskEvent_t event); + +/*************************************************************************************************/ +/*! + * \fn WsfTaskMsgQueue + * + * \brief Return the task message queue used by the given handler. + * + * \param handlerId Event handler ID. + * + * \return Task message queue. + */ +/*************************************************************************************************/ +wsfQueue_t *WsfTaskMsgQueue(wsfHandlerId_t handlerId); + +/*************************************************************************************************/ +/*! + * \fn WsfOsSetNextHandler + * + * \brief Set the next WSF handler function in the WSF OS handler array. This function + * should only be called as part of the OS initialization procedure. + * + * \param handler WSF handler function. + * + * \return WSF handler ID for this handler. + */ +/*************************************************************************************************/ +wsfHandlerId_t WsfOsSetNextHandler(wsfEventHandler_t handler); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_OS_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h new file mode 100644 index 00000000000..14d0cf19f75 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_queue.h @@ -0,0 +1,158 @@ +/*************************************************************************************************/ +/*! + * \file wsf_queue.h + * + * \brief General purpose queue service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_QUEUE_H +#define WSF_QUEUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +/*! Initialize a queue */ +#define WSF_QUEUE_INIT(pQueue) {(pQueue)->pHead = NULL; (pQueue)->pTail = NULL;} + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Queue structure */ +typedef struct +{ + void *pHead; /*! head of queue */ + void *pTail; /*! tail of queue */ +} wsfQueue_t; + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEnq + * + * \brief Enqueue an element to the tail of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueEnq(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueDeq + * + * \brief Dequeue an element from the head of a queue. + * + * \param pQueue Pointer to queue. + * + * \return Pointer to element that has been dequeued or NULL if queue is empty. + */ +/*************************************************************************************************/ +void *WsfQueueDeq(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueuePush + * + * \brief Push an element to the head of a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueuePush(wsfQueue_t *pQueue, void *pElem); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueInsert + * + * \brief Insert an element into a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be inserted. + * \param pPrev Pointer to previous element in the queue before element to be inserted. + * Note: set pPrev to NULL if pElem is first element in queue. + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueInsert(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueRemove + * + * \brief Remove an element from a queue. This function is typically used when iterating + * over a queue. + * + * \param pQueue Pointer to queue. + * \param pElem Pointer to element to be removed. + * \param pPrev Pointer to previous element in the queue before element to be removed. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfQueueRemove(wsfQueue_t *pQueue, void *pElem, void *pPrev); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueCount + * + * \brief Count the number of elements in a queue. + * + * \param pQueue Pointer to queue. + * + * \return Number of elements in queue. + */ +/*************************************************************************************************/ +uint16_t WsfQueueCount(wsfQueue_t *pQueue); + +/*************************************************************************************************/ +/*! + * \fn WsfQueueEmpty + * + * \brief Return TRUE if queue is empty. + * + * \param pQueue Pointer to queue. + * + * \return TRUE if queue is empty, FALSE otherwise. + */ +/*************************************************************************************************/ +bool_t WsfQueueEmpty(wsfQueue_t *pQueue); + + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_QUEUE_H */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h new file mode 100644 index 00000000000..7d75e254638 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/ws-core/sw/wsf/include/wsf_timer.h @@ -0,0 +1,167 @@ +/*************************************************************************************************/ +/*! + * \file wsf_timer.h + * + * \brief Timer service. + * + * $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $ + * $Revision: 10805 $ + * + * Copyright (c) 2009-2017 ARM Ltd., all rights reserved. + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*************************************************************************************************/ +#ifndef WSF_TIMER_H +#define WSF_TIMER_H + +#include "wsf_os.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************** + Macros +**************************************************************************************************/ + +#ifndef WSF_MS_PER_TICK +/*! Default milliseconds per tick rate */ +#define WSF_MS_PER_TICK 1 +#endif + +/************************************************************************************************** + Data Types +**************************************************************************************************/ + +/*! Timer ticks data type */ +typedef uint32_t wsfTimerTicks_t; + +/*! Timer structure */ +typedef struct wsfTimer_tag +{ + struct wsfTimer_tag *pNext; /*! pointer to next timer in queue */ + wsfTimerTicks_t ticks; /*! number of ticks until expiration */ + wsfHandlerId_t handlerId; /*! event handler for this timer */ + bool_t isStarted; /*! TRUE if timer has been started */ + wsfMsgHdr_t msg; /*! application-defined timer event parameters */ +} wsfTimer_t; + + +/************************************************************************************************** + Function Declarations +**************************************************************************************************/ + +/*************************************************************************************************/ +/*! + * \fn WsfTimerInit + * + * \brief Initialize the timer service. This function should only be called once + * upon system initialization. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerInit(void); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartSec + * + * \brief Start a timer in units of seconds. Before this function is called parameter + * pTimer->handlerId must be set to the event handler for this timer and parameter + * pTimer->msg must be set to any application-defined timer event parameters. + * + * \param pTimer Pointer to timer. + * \param sec Seconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartSec(wsfTimer_t *pTimer, wsfTimerTicks_t sec); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStartMs + * + * \brief Start a timer in units of milliseconds. + * + * \param pTimer Pointer to timer. + * \param ms Milliseconds until expiration. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerStop + * + * \brief Stop a timer. + * + * \param pTimer Pointer to timer. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerStop(wsfTimer_t *pTimer); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerUpdate + * + * \brief Update the timer service with the number of elapsed ticks. This function is + * typically called only from timer porting code. + * + * \param ticks Number of ticks since last update. + * + * \return None. + */ +/*************************************************************************************************/ +void WsfTimerUpdate(wsfTimerTicks_t ticks); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerNextExpiration + * + * \brief Return the number of ticks until the next timer expiration. Note that this + * function can return zero even if a timer is running, indicating the timer + * has expired but has not yet been serviced. + * + * \param pTimerRunning Returns TRUE if a timer is running, FALSE if no timers running. + * + * \return The number of ticks until the next timer expiration. + */ +/*************************************************************************************************/ +wsfTimerTicks_t WsfTimerNextExpiration(bool_t *pTimerRunning); + +/*************************************************************************************************/ +/*! + * \fn WsfTimerServiceExpired + * + * \brief Service expired timers for the given task. This function is typically called only + * WSF OS porting code. + * + * \param taskId OS Task ID of task servicing timers. + * + * \return Pointer to next expired timer or NULL if there are no expired timers. + */ +/*************************************************************************************************/ +wsfTimer_t *WsfTimerServiceExpired(wsfTaskId_t taskId); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_TIMER_H */ 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 new file mode 100644 index 00000000000..3384be486f3 Binary files /dev/null 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 new file mode 100644 index 00000000000..abd590ab593 Binary files /dev/null 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 new file mode 100644 index 00000000000..a5fb4ab0ce7 Binary files /dev/null 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 new file mode 100644 index 00000000000..31f299594c8 Binary files /dev/null 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 new file mode 100644 index 00000000000..c5f20081e85 Binary files /dev/null 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 new file mode 100644 index 00000000000..85cd5e02ceb Binary files /dev/null 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 new file mode 100644 index 00000000000..1c38f95eeef Binary files /dev/null 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 new file mode 100644 index 00000000000..fa947cc2ea1 Binary files /dev/null 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 new file mode 100644 index 00000000000..b97f1656dcf Binary files /dev/null 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 new file mode 100644 index 00000000000..49243d1927c Binary files /dev/null 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 new file mode 100644 index 00000000000..fe97d4d83fd Binary files /dev/null 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 new file mode 100644 index 00000000000..3efbdd64025 Binary files /dev/null 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 new file mode 100644 index 00000000000..94c6a13f811 Binary files /dev/null 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 new file mode 100644 index 00000000000..4416909af37 Binary files /dev/null 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 new file mode 100644 index 00000000000..a8ba7678d45 Binary files /dev/null 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 new file mode 100644 index 00000000000..cdaedc932fb Binary files /dev/null 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 new file mode 100644 index 00000000000..315783eb749 Binary files /dev/null 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 new file mode 100644 index 00000000000..95fbae95fe1 Binary files /dev/null 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 new file mode 100644 index 00000000000..ded76db7c34 Binary files /dev/null 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 new file mode 100644 index 00000000000..750ca8fec90 Binary files /dev/null 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 new file mode 100644 index 00000000000..72d535b26a7 Binary files /dev/null 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 new file mode 100644 index 00000000000..444a46fa9b0 Binary files /dev/null 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 new file mode 100644 index 00000000000..bb4be319bec Binary files /dev/null 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 new file mode 100644 index 00000000000..084e7453839 Binary files /dev/null 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 new file mode 100644 index 00000000000..33ec662464a Binary files /dev/null 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 new file mode 100644 index 00000000000..c7ee6fa277a Binary files /dev/null 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 new file mode 100644 index 00000000000..be4fc74df19 Binary files /dev/null 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 new file mode 100644 index 00000000000..c11e06b141d Binary files /dev/null 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 new file mode 100644 index 00000000000..136a7ad1cc4 Binary files /dev/null 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 new file mode 100644 index 00000000000..f4ddab2ae05 Binary files /dev/null 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 new file mode 100644 index 00000000000..140192865e3 Binary files /dev/null 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 new file mode 100644 index 00000000000..a3d7380c34c Binary files /dev/null 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 new file mode 100644 index 00000000000..ac246b29c05 Binary files /dev/null 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 new file mode 100644 index 00000000000..bfc21b106d7 Binary files /dev/null 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 new file mode 100644 index 00000000000..cbd3dc6d89e Binary files /dev/null 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 new file mode 100644 index 00000000000..e6938ca404c Binary files /dev/null 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 new file mode 100644 index 00000000000..796744a5b1a Binary files /dev/null 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 new file mode 100644 index 00000000000..70429b7acd6 Binary files /dev/null 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 new file mode 100644 index 00000000000..5f4cbb09a35 Binary files /dev/null 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 new file mode 100644 index 00000000000..6086a112c33 Binary files /dev/null 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 new file mode 100644 index 00000000000..d607932aee1 Binary files /dev/null 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 new file mode 100644 index 00000000000..084248d9050 Binary files /dev/null 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 new file mode 100644 index 00000000000..84e168ea2e3 Binary files /dev/null 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 new file mode 100644 index 00000000000..eaeda2da13d Binary files /dev/null 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 new file mode 100644 index 00000000000..4eb2a563e1e Binary files /dev/null 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 new file mode 100644 index 00000000000..97b9b3b1e58 Binary files /dev/null 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 new file mode 100644 index 00000000000..9e6790f9ef4 Binary files /dev/null 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 new file mode 100644 index 00000000000..1488a250db4 Binary files /dev/null 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_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h new file mode 100644 index 00000000000..7423e8cecc4 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/hci_mbed_os_adaptation.h @@ -0,0 +1,65 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HCI_MBED_OS_ADAPTATION_H_ +#define HCI_MBED_OS_ADAPTATION_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Write data to the driver. + * + * @param type HCI packet type. + * @param len Number of bytes to write + * @param pData Pointer to the data to write. + * @return the actual number of data bytes written, + * + * @note type parameter allows the driver layer to prepend the data with a + * header on the same write transaction. + * @note mbed os wrapper of hciDrvWrite + */ +uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData); + +/** + * Start the hci reset sequence. + * @note stable wrapper around hciCoreResetStart. + * @note definition provided in mbed OS. + */ +void hci_mbed_os_start_reset_sequence(void); + +/** + * Handle hci messages during the reset sequence. + * @param msg: The HCI message to handle. + * @note stable wrapper of hciCoreResetSequence. + * @note definition provided in mbed os. + */ +void hci_mbed_os_handle_reset_sequence(uint8_t* msg); + +/** + * Signal to the stack that the reset sequence is done. + * @note shall be called from mbed OS when the reset sequence has been done. + */ +void hci_mbed_os_signal_reset_sequence_done(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* HCI_MBED_OS_ADAPTATION_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h new file mode 100644 index 00000000000..45c601c81f8 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/mbed_os_adaptation/wsf_mbed_os_adaptation.h @@ -0,0 +1,44 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * SPDX-License-Identifier: LicenseRef-PBL + * + * This file and the related binary are licensed under the + * Permissive Binary License, Version 1.0 (the "License"); + * you may not use these files except in compliance with the License. + * + * You may obtain a copy of the License here: + * LICENSE-permissive-binary-license-1.0.txt and at + * https://www.mbed.com/licenses/PBL-1.0 + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WSF_MBED_OS_ADAPTATION_H_ +#define WSF_MBED_OS_ADAPTATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrap core_util_critical_section_enter + */ +void wsf_mbed_os_critical_section_enter(void); + +/** + * Wrap core_util_critical_section_exit + */ +void wsf_mbed_os_critical_section_exit(void); + +/** + * Signal an event insertion in the Cordio stack to ble API. + */ +void wsf_mbed_ble_signal_event(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* WSF_MBED_OS_ADAPTATION_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp index c381e733f55..f303c23d068 100644 --- a/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_Maxim/MaximGattServer.cpp @@ -383,11 +383,11 @@ void MaximGattServer::attCback(attEvt_t *pEvt) uint8_t MaximGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) { GattReadCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .offset = offset, - .len = *pAttr->pLen, - .data = pAttr->pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .offset = */ offset, + /* .len = */ *pAttr->pLen, + /* .data = */ pAttr->pValue }; getInstance().handleDataReadEvent(&cbParams); @@ -426,12 +426,12 @@ uint8_t MaximGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint } GattWriteCallbackParams cbParams = { - .connHandle = connId, - .handle = handle, - .writeOp = writeOp, - .offset = offset, - .len = len, - .data = pValue + /* .connHandle = */ connId, + /* .handle = */ handle, + /* .writeOp = */ writeOp, + /* .offset = */ offset, + /* .len = */ len, + /* .data = */ pValue }; getInstance().handleDataWrittenEvent(&cbParams); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp index d6f815d64ec..fdf0ec76ca5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp index 4c5365f1b70..26f53848f8d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xGattServer.cpp @@ -440,12 +440,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -480,12 +480,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp index 4f11a9d8ae9..c81d632434e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp index 99059f6623a..8090e8498b0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_discovery.cpp @@ -63,11 +63,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_READ_RSP: { GattReadCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle, - .offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.read_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.read_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.read_rsp.handle, + /* .offset = */ p_ble_evt->evt.gattc_evt.params.read_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.read_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.read_rsp.data, }; gattClient.processReadResponse(&response); } @@ -75,12 +75,12 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_WRITE_RSP: { GattWriteCallbackParams response = { - .connHandle = p_ble_evt->evt.gattc_evt.conn_handle, - .handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle, - .writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), - .offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset, - .len = p_ble_evt->evt.gattc_evt.params.write_rsp.len, - .data = p_ble_evt->evt.gattc_evt.params.write_rsp.data, + /* .connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle, + /* .handle = */ p_ble_evt->evt.gattc_evt.params.write_rsp.handle, + /* .writeOp = */ (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op), + /* .offset = */ p_ble_evt->evt.gattc_evt.params.write_rsp.offset, + /* .len = */ p_ble_evt->evt.gattc_evt.params.write_rsp.len, + /* .data = */ p_ble_evt->evt.gattc_evt.params.write_rsp.data, }; gattClient.processWriteResponse(&response); } @@ -88,11 +88,11 @@ void bleGattcEventHandler(const ble_evt_t *p_ble_evt) case BLE_GATTC_EVT_HVX: { GattHVXCallbackParams params; - params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle; - params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle; - params.type = static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); - params.len = p_ble_evt->evt.gattc_evt.params.hvx.len; - params.data = p_ble_evt->evt.gattc_evt.params.hvx.data; + /* params.connHandle = */ p_ble_evt->evt.gattc_evt.conn_handle; + /* params.handle = */ p_ble_evt->evt.gattc_evt.params.hvx.handle; + /* params.type = */ static_cast(p_ble_evt->evt.gattc_evt.params.hvx.type); + /* params.len = */ p_ble_evt->evt.gattc_evt.params.hvx.len; + /* params.data = */ p_ble_evt->evt.gattc_evt.params.hvx.data; gattClient.processHVXEvent(¶ms); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 4a520305246..2a1c0af1a68 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -503,12 +503,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.write.op), - .offset = gattsEventP->params.write.offset, - .len = gattsEventP->params.write.len, - .data = gattsEventP->params.write.data + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.write.op), + /* .offset = */ gattsEventP->params.write.offset, + /* .len = */ gattsEventP->params.write.len, + /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; @@ -539,7 +539,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) if (req->length == 0) { req->attr_handle = input_req.handle; req->offset = input_req.offset; - } else { + } else { // it should be the subsequent write if ((req->offset + req->length) != input_req.offset) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply); @@ -627,12 +627,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply); GattWriteCallbackParams writeParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .writeOp = static_cast(input_req.op), - .offset = req->offset, - .len = req->length, - .data = req->data, + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .writeOp = */ static_cast(input_req.op), + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, }; handleDataWrittenEvent(&writeParams); releaseLongWriteRequest(conn_handle); @@ -649,7 +649,7 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) * 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 = { @@ -662,12 +662,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } } }; - + if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { reply.params.write.update = 0; } - + sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); /* @@ -679,12 +679,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .writeOp = static_cast(gattsEventP->params.authorize_request.request.write.op), - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .writeOp = */ static_cast(gattsEventP->params.authorize_request.request.write.op), + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } @@ -789,4 +789,4 @@ void nRF5xGattServer::releaseAllWriteRequests() { req.data = NULL; } } -} \ No newline at end of file +} diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp index 87ac20c8ff0..79f691bfcf6 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xServiceDiscovery.cpp @@ -24,8 +24,8 @@ nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHan characteristicDiscoveryStarted(connectionHandle); ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange); ble_error_t err = BLE_ERROR_NONE; @@ -170,8 +170,8 @@ nRF5xServiceDiscovery::progressCharacteristicDiscovery(void) if (startHandle < endHandle) { ble_gattc_handle_range_t handleRange = { - .start_handle = startHandle, - .end_handle = endHandle + (uint16_t) startHandle, + (uint16_t) endHandle }; if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) { terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED); @@ -288,8 +288,8 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt if (state == DISCOVER_SERVICE_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) { UUID::LongUUIDBytes_t uuid; - -#if (NRF_SD_BLE_API_VERSION >= 3) + +#if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); (void) sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(const_cast(p_gattc_evt), &iter); @@ -308,7 +308,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt } else if (state == DISCOVER_CHARACTERISTIC_UUIDS) { if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) { UUID::LongUUIDBytes_t uuid; - + #if (NRF_SD_BLE_API_VERSION >= 3) ble_gattc_handle_value_t iter; memset(&iter, 0, sizeof(ble_gattc_handle_value_t)); @@ -317,7 +317,7 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gatt #else memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID); #endif - + unsigned charIndex = charUUIDDiscoveryQueue.dequeue(); characteristics[charIndex].setupLongUUID(uuid, UUID::LSB);