diff --git a/features/FEATURE_BLE/ble/SafeEnum.h b/features/FEATURE_BLE/ble/SafeEnum.h new file mode 100644 index 0000000000..0f9a0a5554 --- /dev/null +++ b/features/FEATURE_BLE/ble/SafeEnum.h @@ -0,0 +1,155 @@ +/* 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_SAFE_ENUM_H_ +#define BLE_SAFE_ENUM_H_ + +#include +#include + +namespace ble { + +/** + * Helper class used to define safe enumerations. + * + * C++ 98 enums expose different security holes: + * - Scope The scope of the enum is the scope defining it. In other words, + * enumerator defined at namespace scope are in the same scope that other + * enumerator defined in that namespace even if they belong to a different + * enumeration. + * As a result it is really easy to collide names between two different + * enumerators. At the end, the programmer has to protect its declaration + * with long prefixing. + * - Unsafe comparison: enumerators really just are named integer and can be + * implicitly converted to integer. As a result it is possible to compare + * value of different enum type. + * - Layout: The layout type of enumerations is implementation defined. + * + * This template class expose a framework to overcome those issues: + * + * First enum has to be defined in a structure which inherit from this class. + * The target type is the name of the structure containing the enumeration + * while LayoutType is the inner type used to stored the enum. + * + * Comparison operator are provided so it is not possible to compare a SafeEnum + * of a type to another SafeEnum of a different type. + * + * Implicit conversion to integer is not defined, users have to either use the + * value function which return the integer value stored in an EnumType. Client + * class can also define their own conversion operation. + * + * @tparam Target structure containing the enumeration definition. + * @tparam LayoutType Inner type used to store enumeration value. + * + * @code + + struct color_t : SafeEnum { + enum type { + RED, + GREEN, + BLACK + }; + + color_t(type) : SafeEnum(type) { } + }; + + // use an uint8_t to store the enumeration value + struct shape_t : SafeEnum { + enum type { + RECTANGLE, + CIRCLE, + TRIANGLE + }; + + shape_t(type) : SafeEnum(type) { } + }; + + // shape enumerator is in the shape_t scope. + shape_t shape = shape_t::RECTANGLE; + + shape_t shape = color_t::RED; // Compilation error + + if (shape == shape_t::CIRCLE) { + } + + // compilation error + if (shape == color_t::RED) { + + } + + void sink(shape_t); (1) + void sink(color_t); (2) + + sink(shape); // use overload (1) + sink(color); // use overload (2) + + // explicit access to the value is mandatory when a SafeEnum value is used + // as the condition in a switch statement + switch(shape.value()) { + case shape_t::RECTANGLE: + break; + } + + * @endcode + */ +template +struct SafeEnum { + + /** + * Construction of an enumeration value. + */ + SafeEnum(LayoutType value) : _value(value) { } + + /** + * Equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs and rhs are equal and false + * otherwise. + */ + friend bool operator==(SafeEnum lhs, SafeEnum rhs) { + return lhs._value == rhs._value; + } + + /** + * Not equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs and rhs are not equal and false + * otherwise. + */ + friend bool operator!=(SafeEnum lhs, SafeEnum rhs) { + return !(lhs == rhs); + } + + /** + * Explicit access to the inner value of the SafeEnum instance. + */ + LayoutType value() const { + return _value; + } + +private: + LayoutType _value; +}; + +} // namespace ble + +#endif /* BLE_SAFE_ENUM_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/GapEvents.h b/features/FEATURE_BLE/ble/pal/GapEvents.h new file mode 100644 index 0000000000..34b7c7487a --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/GapEvents.h @@ -0,0 +1,443 @@ +/* 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_GAP_MESSAGE_H_ +#define BLE_PAL_GAP_MESSAGE_H_ + +#include "GapTypes.h" +#include "ble/ArrayView.h" + +namespace ble { +namespace pal { + +/** + * Enumeration of GAP event types + */ +struct GapEventType : SafeEnum { + enum type { + /** + * Event type used by GapUnexpectedErrorEvent + */ + UNEXPECTED_ERROR, + + /** + * Event type used by GapConnectionCompleteEvent + */ + CONNECTION_COMPLETE, + + /** + * Event type used by GapAdvertisingReportEvent + */ + ADVERTISING_REPORT, + + /** + * Event type used by GapConnectionUpdateEvent + * */ + CONNECTION_UPDATE, + + /** + * Event type used by GapRemoteConnectionParameterRequestEvent + */ + REMOTE_CONNECTION_PARAMETER_REQUEST, + + /** + * Event type used by GapDisconnectionCompleteEvent + */ + DISCONNECTION_COMPLETE + }; + + GapEventType(type event_type) : SafeEnum(event_type) { } +}; + + +/** + * Base class of a Gap Event. + * + * Client should use the field type to deduce the actual type of the event. + */ +struct GapEvent { + + const GapEventType type; + +protected: + GapEvent(GapEventType type) : type(type) { } + + // Disable copy construction and copy assignement operations. + GapEvent(const GapEvent&); + GapEvent& operator=(const GapEvent&); +}; + + +/** + * Model an unexpected error that happen during a gap procedure. + * + * This class is mainly used to notify user code of an unexpected error returned + * in an HCI command complete event. + */ +struct GapUnexpectedErrorEvent : public GapEvent { + GapUnexpectedErrorEvent(uint16_t opcode, uint8_t error_code) : + GapEvent(GapEventType::UNEXPECTED_ERROR), + opcode(opcode), error_code(error_code) { } + + /** + * Opcode composed of the OCF and OGF of the command which has returned an + * error. + */ + const uint16_t opcode; + + /** + * Error code + */ + const uint8_t error_code; +}; + + +/** + * Indicate to both ends (slave or master) the end of the connection process. + * + * This structure should be used for Connection Complete Events and Enhanced + * Connection Complete Event. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.1 LE Connection Complete Event + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection + */ +struct GapConnectionCompleteEvent : public GapEvent { + /** + * Construct a new GapConnectionCompleteEvent. + * + * @param status Status of the operation: 0x00 in case of success otherwise + * the error code associated with the failure. + * + * @param connection_handle handle of the connection created. This handle + * will be used to address the connection in any connection oriented + * operation. + * + * @param role Role of the LE subsystem in the connection. + * + * @param address_type Type of address used by the peer for this connection. + * + * @param address Address of the peer used to establish the connection. + * + * @param connection_interval Connection interval used on this connection. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + * + * @param connection_latency Number of connection events the slave can + * drop. + * + * @param supervision_timeout Supervision timeout of the connection. It + * shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.1 LE Connection Complete Event + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection + * Complete Event + */ + GapConnectionCompleteEvent( + uint8_t status, + connection_handle_t connection_handle, + connection_role_t role, + advertising_peer_address_type_t peer_address_type, + const address_t& peer_address, + uint16_t connection_interval, + uint16_t connection_latency, + uint16_t supervision_timeout + ) : + GapEvent(GapEventType::CONNECTION_COMPLETE), + status(status), + connection_handle(connection_handle), + role(role), + peer_address_type(peer_address_type), + peer_address(peer_address), + connection_interval(connection_interval), + connection_latency(connection_latency), + supervision_timeout(supervision_timeout) { + } + + /* + * @param status Indicate if the connection succesfully completed or not: + * - 0: Connection successfuly completed + * - [0x01 : 0xFF] Connection failed to complete, the value represent + * the code for the error. + */ + const uint8_t status; + + /** + * Handle of the connection created, valid if status is equal to 0. + * @important Valid if status is equal to 0. + */ + const connection_handle_t connection_handle; + + /** + * Role of the device in the connection + * @important Valid if status is equal to 0. + */ + const connection_role_t role; + + /** + * Peer address type. + */ + const advertising_peer_address_type_t peer_address_type; + + /** + * Peer address. + */ + const address_t peer_address; + + /** + * Connection interval used in this connection. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + */ + const uint16_t connection_interval; + + /** + * Number of connection events the slave can drop. + */ + const uint16_t connection_latency; + + /** + * Supervision timeout of the connection + * It shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + */ + const uint16_t supervision_timeout; +}; + + +/** + * Report advertising from one or more LE device. + * + * @important This class has to be implemented by the BLE port. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.2 LE Advertising Report Event + */ +struct GapAdvertisingReportEvent : public GapEvent { + + /** + * POD representing an advertising captured by the LE subsystem. + */ + struct advertising_t { + received_advertising_type_t type; + connection_peer_address_type_t address_type; + const address_t& address; + ArrayView data; + int8_t rssi; + }; + + GapAdvertisingReportEvent() : GapEvent(GapEventType::ADVERTISING_REPORT) { } + + virtual ~GapAdvertisingReportEvent() { } + + /** + * Count of advertising in this event. + */ + virtual uint8_t size() const = 0; + + /** + * Access the advertising at index i. + */ + virtual advertising_t operator[](uint8_t i) const = 0; +}; + + +/** + * Indicates the connection update process completion. + * + * If no parameters are updated after a connection update request from the peer + * then this event shall not be emmited. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.3 LE Connection Update Complete + * Event. + */ +struct GapConnectionUpdateEvent : public GapEvent { + + /** + * Construct a connection update event for a successful process. + * + * @param status Status of the connection update event operation. If equal + * to 0x00 then the process was successful, otherwise the status indicates + * the reason of the faillure. + * + * @param connection_handle Handle of the connection updated. + * + * @param connection_interval New connection interval used by the connection. + * + * @param Connection_latency New connection latency used by the connection. + * + * @param supervision_timeout New connection supervision timeout. + */ + GapConnectionUpdateEvent( + uint8_t status, + connection_handle_t connection_handle, + uint16_t connection_interval, + uint16_t connection_latency, + uint16_t supervision_timeout + ) : + GapEvent(GapEventType::CONNECTION_UPDATE), + status(status), + connection_handle(connection_handle), + connection_interval(connection_interval), + connection_latency(connection_latency), + supervision_timeout(supervision_timeout) { + } + + /** + * If equal to 0, the connection update has succesfully completed otherwise + * the process has failled and this field represent the error associated to + * the faillure. + */ + const uint8_t status; + + /** + * Handle of the connection which has completed the connection update + * process. + */ + const connection_handle_t connection_handle; + + /** + * New connection interval used by the connection. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + */ + const uint16_t connection_interval; + + /* + * New number of connection events the slave can drop. + */ + const uint16_t connection_latency; + + /* + * New supervision timeout of the connection. + * It shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + */ + const uint16_t supervision_timeout; +}; + + +/** + * indicate a request from the peer to change the connection parameters. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.6 LE Remote Connection Parameter + * Request Event. + */ +struct GapRemoteConnectionParameterRequestEvent : public GapEvent { + /** + * Construct a new remote connection parameter request event. + * + * @param connection_handle Handle of the connection with the peer + * requesting the parameter update + * + * @param min_connection_interval Minimum value of the connection interval + * requested by the peer. + * + * @param max_connection_interval Maximum value of the connection interval + * requested by the peer. + * + * @param connection_latency Slave latency requested by the peer. + * + * @param supervision_timeout Supervision timeout requested by the peer. + */ + GapRemoteConnectionParameterRequestEvent( + connection_handle_t connection_handle, + uint16_t min_connection_interval, + uint16_t max_connection_interval, + uint16_t connection_latency, + uint16_t supervision_timeout + ) : GapEvent(GapEventType::REMOTE_CONNECTION_PARAMETER_REQUEST), + connection_handle(connection_handle), + min_connection_interval(min_connection_interval), + max_connection_interval(max_connection_interval), + connection_latency(connection_latency), + supervision_timeout(supervision_timeout) { + } + + /** + * Handle of the connection with the peer requesting the parameter update. + */ + const connection_handle_t connection_handle; + + /** + * Minimum value of the connection interval requested by the peer. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + */ + const uint16_t min_connection_interval; + + /** + * Maximum value of the connection interval requested by the peer. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + */ + const uint16_t max_connection_interval; + + /* + * Slave latency requested by the peer. + */ + const uint16_t connection_latency; + + /* + * Supervision timeout requested by the peer. + * It shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + */ + const uint16_t supervision_timeout; +}; + + +/** + * Indicate the end of a disconnection process. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.5 Disconnection Complete Event. + */ +struct GapDisconnectionCompleteEvent : public GapEvent { + /** + * Construct a disconnection complete event. + * + * @param status Status of the procedure. If equal to 0 then the + * disconnection process complete successfully. Otherwise it represents the + * error code associated with the faillure. + * + * @param connection_handle Handle of the connection disconnected. + * + * @param reason Reason of the disconnection + */ + GapDisconnectionCompleteEvent( + uint8_t status, + connection_handle_t connection_handle, + uint8_t reason + ) : GapEvent(GapEventType::DISCONNECTION_COMPLETE), + status(status), + connection_handle(connection_handle), + reason(reason) { + } + + /** + * Status of the procedure. If equal to 0 then the procedure was a success + * otherwise this variable contains the error code associated with the + * faillure. + */ + const uint8_t status; + + /** + * Handle of the connection used for the procedure. + */ + const connection_handle_t connection_handle; + + /** + * Reason for disconnection. + * + * @important ignored in case of faillure. + */ + const uint8_t reason; +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GAP_MESSAGE_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/GapTypes.h b/features/FEATURE_BLE/ble/pal/GapTypes.h new file mode 100644 index 0000000000..405b7c1d1b --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/GapTypes.h @@ -0,0 +1,610 @@ +/* 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_GAP_TYPES_H_ +#define BLE_PAL_GAP_TYPES_H_ + +#include +#include "ble/BLETypes.h" +#include "ble/SafeEnum.h" + +namespace ble { +namespace pal { + +/** + * Type of advertising the LE subsystem can use when it advertise. + */ +struct advertising_type_t : SafeEnum { + enum type { + /** + * Connectable and scannable undirected advertising . + */ + ADV_IND = 0x00, + + /** + * Connectable high duty cycle directed advertising + */ + ADV_DIRECT_IND = 0x01, + + /** + * Scannable undirected advertising + */ + ADV_SCAN_IND = 0x02, + + /** + * Non connectable undirected advertising + */ + ADV_NONCONN_IND = 0x03, + + /** + * Connectable low duty cycle directed advertising + */ + ADV_DIRECT_IND_LOW_DUTY_CYCLE = 0x04 + }; + + /** + * Construct a new advertising_type_t value. + */ + advertising_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Type used to model the own address used during the following GAP operations: + * advertising, scanning and initiating + */ +struct own_address_type_t : SafeEnum { + enum type { + /** + * Use the public device address + */ + PUBLIC_ADDRESS = 0x00, + + /** + * Use the random device address + */ + RANDOM_ADDRESS = 0x01, + + /** + * Generated resolvable private address based on the local IRK from the + * resolving list. Use the public address if no entry match in the resolving + * list. + */ + RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK = 0x02, + + /** + * Generated resolvable private address based on the local IRK from the + * resolving list. Use the random address if no entry match in the resolving + * list. + */ + RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK = 0x03, + }; + + /** + * Construct a new instance of own_address_type_t. + */ + own_address_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Type modeling the peer address type during direct advertising. + */ +struct advertising_peer_address_type_t : + SafeEnum { + enum type { + /** + * Public device address or identity address. + */ + PUBLIC_ADDRESS = 0x00, + + /** + * Random device address or random (static) identity address. + */ + RANDOM_ADDRESS = 0x01 + }; + + /** + * Construct a new instance of advertising_peer_address_type_t. + */ + advertising_peer_address_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Peer address type used during connection initiating. + */ +struct connection_peer_address_type_t : + SafeEnum { + enum type { + /** + * Public device address + */ + PUBLIC_ADDRESS = 0x00, + + /** + * Random device address + */ + RANDOM_ADDRESS = 0x01, + + /** + * Public identity address. + * @note remove once privacy mode is supported. + */ + PUBLIC_IDENTITY_ADDRESS = 0x02, + + /** + * Random (static) identity address. + * @note remove once privacy mode is supported. + */ + RANDOM_IDENTITY_ADDRESS = 0x03 + }; + + /** + * Construct a new connection_peer_address_type_t instance. + */ + connection_peer_address_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Address type used in whitelist operations + */ +struct whitelist_address_type_t : SafeEnum { + enum type { + PUBLIC_DEVICE_ADDRESS = 0x00, + RANDOM_DEVICE_ADDRESS = 0x01, + /* TODO: to be added with bluetooth 5 support: + ANONYMOUS_ADVERTISEMENT_DEVICE_ADRESS + */ + }; + + /** + * Construct a new whitelist_address_type_t instance. + */ + whitelist_address_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Channel map which can be used during advertising. + */ +struct advertising_channel_map_t : SafeEnum { + enum type { + ADVERTISING_CHANNEL_37 = (1 << 0), + ADVERTISING_CHANNEL_38 = (1 << 1), + ADVERTISING_CHANNEL_37_AND_38 = + ADVERTISING_CHANNEL_37 | ADVERTISING_CHANNEL_38, + ADVERTISING_CHANNEL_39 = (1 << 2), + ADVERTISING_CHANNEL_37_AND_39 = + ADVERTISING_CHANNEL_37 | ADVERTISING_CHANNEL_39, + ADVERTISING_CHANNEL_38_AND_39 = + ADVERTISING_CHANNEL_38 | ADVERTISING_CHANNEL_39, + ALL_ADVERTISING_CHANNELS = + ADVERTISING_CHANNEL_37 | ADVERTISING_CHANNEL_38 | ADVERTISING_CHANNEL_39 + }; + + /** + * Construct a new advertising_channel_map_t instance. + */ + advertising_channel_map_t(type value) : + SafeEnum(value) { } +}; + + +/** + * HCI Error codes. + */ +struct hci_error_code_t : SafeEnum { + enum type { + SUCCESS = 0x00, + UNKNOWN_HCI_COMMAND = 0x01, + UNKNOWN_CONNECTION_IDENTIFIER = 0x02, + HARDWARE_FAILLURE = 0x03, + PAGE_TIMEOUT = 0x04, + AUTHENTICATION_FAILLURE = 0x05, + PIN_OR_KEY_MISSING = 0x06, + MEMORY_CAPACITY_EXCEEDED = 0x07, + CONNECTION_TIMEOUT = 0x08, + CONNECTION_LIMIT_EXCEEDED = 0x09, + SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED = 0x0A, + CONNECTION_ALREADY_EXIST = 0x0B, + COMMAND_DISALLOWED = 0x0C, + CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES = 0x0D, + CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS = 0x0E, + CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR = 0x0F, + CONNECTION_ACCEPT_TIMEOUT_EXCEEDED = 0x10, + UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE = 0x11, + INVALID_HCI_COMMAND_PARAMETERS = 0x12, + REMOTE_USER_TERMINATED_CONNECTION = 0x13, + REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES = 0x14, + REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF = 0x15, + CONNECTION_TERMINATED_BY_LOCAL_HOST = 0x16, + REPEATED_ATTEMPTS = 0x17, + PAIRING_NOT_ALLOWED = 0x18, + UNKNOWN_LMP_PDU = 0x19, + UNSUPPORTED_REMOTE_FEATURE = 0x1A, + UNSUPPORTED_LMP_FEATURE = 0x1A, + SCO_OFFSET_REJECTED = 0x1B, + SCO_INTERVAL_REJECTED = 0x1C, + SCO_AIR_MODE_REJECTED = 0x1D, + INVALID_LMP_PARAMETERS = 0x1E, + INVALID_LL_PARAMETERS = 0x1E, + UNSPECIFIED_ERROR = 0x1F, + UNSUPPORTED_LMP_PARAMETER_VALUE = 0x20, + UNSUPPORTED_LL_PARAMETER_VALUE = 0x20, + ROLE_CHANGE_NOT_ALLOWED = 0x21, + LMP_RESPONSE_TIMEOUT = 0x22, + LL_RESPONSE_TIMEOUT = 0x22, + LMP_ERROR_TRANSACTION_COLLISION = 0x23, + LL_PROCEDURE_COLLISION = 0x23, + LMP_PDU_NOT_ALLOWED = 0x24, + ENCRYPTION_MODE_NOT_ACCEPTABLE = 0x25, + LINK_KEY_CANNOT_BE_CHANGED = 0x26, + REQUESTED_QOS_NOT_SUPPORTED = 0x27, + INSTANT_PASSED = 0x28, + PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29, + DIFFERENT_TRANSACTION_COLLISION = 0x2A, + RESERVED_FOR_FUTURE_USE = 0x2B, + QOS_UNACCEPTABLE_PARAMETER = 0x2C, + QOS_REJECTED = 0x2D, + CHANNEL_CLASSIFICATION_NOT_SUPPORTED = 0x2E, + INSUFFICIENT_SECURITY = 0x2F, + PARAMETER_OUT_OF_MANDATORY_RANGE = 0x30, + //RESERVED_FOR_FUTURE_USE = 0x31, + ROLE_SWITCH_PENDING = 0x32, + //RESERVED_FOR_FUTURE_USE = 0x33, + RESERVED_SLOT_VIOLATION = 0x34, + ROLE_SWITCH_FAILED = 0x35, + EXTENDED_INQUIRY_RESPONSE_TOO_LARGE = 0x36, + SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST = 0x37, + HOST_BUSY_PAIRING = 0x38, + CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND = 0x39, + CONTROLLER_BUSY = 0x3A, + UNACCEPTABLE_CONNECTION_PARAMETERS = 0x3B, + ADVERTISING_TIMEOUT = 0x3C, + CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE = 0x3D, + CONNECTION_FAILED_TO_BE_ESTABLISHED = 0x3E, + MAC_CONNECTION_FAILED = 0x3F, + COARSE_CLOCK_ADJUSTMENT_REJECTED_BUT_WILL_TRY_TO_ADJUST_USING_CLOCK_DRAGGING = 0x40, + TYPE0_SUBMAP_NOT_DEFINED = 0x41, + UNKNOWN_ADVERTISING_IDENTIFIER = 0x42, + LIMIT_REACHED = 0x43, + OPERATION_CANCELLED_BY_HOST = 0x44 + }; + + /** + * Construct a new hci_error_code_t instance. + */ + hci_error_code_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Reasons which can be used to end a connection. + */ +struct disconnection_reason_t : SafeEnum { + enum type { + AUTHENTICATION_FAILLURE = 0x05, + REMOTE_USER_TERMINATED_CONNECTION = 0x13, + REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES = 0x14, + REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF = 0x15, + UNSUPPORTED_REMOTE_FEATURE = 0x1A, + PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29, + UNACCEPTABLE_CONNECTION_PARAMETERS = 0x3B + }; + + /** + * Construct a new disconnection_reason_t instance. + */ + disconnection_reason_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Filter policy which can be used during advertising. + */ +struct advertising_filter_policy_t : + SafeEnum { + enum type { + /** + * Process connection and scan requests from all devices. The whitelist is + * not used. + */ + NO_FILTER = 0x00, + + /** + * Process connection requests from all devices but filter out scan requests + * of devices which are not in the whitelist. + */ + FILTER_SCAN_REQUESTS = 0x01, + + /** + * Process scan requests from all devices but filter out connection requests + * of devices which are not in the whitelist. + */ + FILTER_CONNECTION_REQUEST = 0x02, + + /** + * Filter out scan or connection requests of devices which are not in the + * whitelist. + */ + FILTER_SCAN_AND_CONNECTION_REQUESTS = 0x03 + }; + + /** + * Construct a new instance of advertising_filter_policy_t. + */ + advertising_filter_policy_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Filter policy which can be used during a scan. + */ +struct scanning_filter_policy_t : SafeEnum { + enum type { + /** + * Accept all advertising packets except directed advertising packet not + * addressed to this device. + */ + NO_FILTER = 0x00, + + /** + * Accept only advertising packets from devices in the whitelist except + * directed advertising packet not addressed to this device. + */ + FILTER_ADVERTISING = 0x01 + + // EXTENDED ADVERTISING FILTER POLICY (accept private resolvable direct advertising) + }; + + /** + * Construct a new instance of scanning_filter_policy_t. + */ + scanning_filter_policy_t(type value) : + SafeEnum(value) { } + +}; + + +/** + * Filter policy which can be used during connection initiation. + */ +struct initiator_policy_t : SafeEnum { + enum type { + /** + * The whitelist is not used to determine which advertiser to connect to. + */ + NO_FILTER, + + /** + * Whitelist is used to determine which advertiser to connect to. + */ + USE_WHITE_LIST + }; + + initiator_policy_t(type value) : + SafeEnum(value) { } +}; + + +/** + * MAC address data type. + */ +struct address_t { + /** + * Create an invalid mac address, equal to FF:FF:FF:FF:FF:FF + */ + address_t() { + memset(value, 0xFF, sizeof(value)); + } + + /** + * Initialize a mac address from an array of bytes. + * + * @param input_value value of the MAC address. + */ + address_t(const uint8_t (&input_value)[6]) { + memcpy(value, input_value, sizeof(value)); + } + + /** + * Initialize a mac address from a pointer to a buffer. + * + * @param input_value Buffer containing the mac address. It shall be at + * least 6 long. + * + * @param tag Tag used to select this constructor. The value does not matter. + */ + address_t(const uint8_t* input_value, bool tag) { + memcpy(value, input_value, sizeof(value)); + } + + /** + * Equal operator between two addresses. + */ + friend bool operator==(const address_t& lhs, const address_t& rhs) { + return memcmp(lhs.value, rhs.value, sizeof(lhs.value)) == 0; + } + + /** + * Non equal operator between two addresses. + */ + friend bool operator!=(const address_t& lhs, const address_t& rhs) { + return !(lhs == rhs); + } + + /** + * Subscript operator to access mac address content + */ + uint8_t operator[](uint8_t i) const { + return value[i]; + } + + /** + * Return the pointer to the buffer holding mac address. + */ + const uint8_t* data() const { + return value; + } + + /** + * Size in byte of a mac address. + */ + static uint8_t size() { + return sizeof(value); + } + +private: + uint8_t value[6]; +}; + + +/** + * Hold advertising data. + */ +struct advertising_data_t { + /** + * Construct advertising data from an array. + * + * @param input_value Reference to the array containing the advertising data + */ + advertising_data_t(const uint8_t (&input_value)[31]) { + memcpy(value, input_value, sizeof(value)); + } + + /** + * Construct advertising data from a pointer to a buffer. + * + * @param input_value Pointer to the buffer containing the advertising data. + * + * @param len Length of the buffer. + */ + advertising_data_t(const uint8_t* input_value, size_t len) { + const size_t actual_len = std::min(len, sizeof(value)); + memcpy(value, input_value, actual_len); + memset(value + actual_len, 0x00, sizeof(value) - actual_len); + } + + /** + * Equal operator between two advertising data. + */ + friend bool operator==( + const advertising_data_t& lhs, const advertising_data_t& rhs + ) { + return memcmp(lhs.value, rhs.value, sizeof(lhs.value)) == 0; + } + + /** + * Non equal operator between two advertising data. + */ + friend bool operator!=( + const advertising_data_t& lhs, const advertising_data_t& rhs + ) { + return !(lhs == rhs); + } + + /** + * Subscript operator used to access the content of the advertising data. + */ + uint8_t operator[](uint8_t i) const { + return value[i]; + } + + /** + * Return a pointer to the advertising data buffer. + */ + const uint8_t* data() const { + return value; + } + + /** + * Return (fixed) size of advertising data. + */ + static uint8_t size() { + return sizeof(value); + } + +private: + uint8_t value[31]; +}; + + +/** + * Type of advertising the LE subsystem can use when it advertise. + */ +struct received_advertising_type_t : + SafeEnum { + enum type { + /** + * Connectable and scannable undirected advertising . + */ + ADV_IND = 0x00, + + /** + * Connectable high duty cycle directed advertising + */ + ADV_DIRECT_IND = 0x01, + + /** + * Scannable undirected advertising + */ + ADV_SCAN_IND = 0x02, + + /** + * Non connectable undirected advertising + */ + ADV_NONCONN_IND = 0x03, + + /** + * Response to a scan request. + */ + SCAN_RESPONSE = 0x04 + }; + + /** + * Construct a new received_advertising_type_t value. + */ + received_advertising_type_t(type value) : + SafeEnum(value) { } +}; + + +/** + * Model connection role. Used in GapConnectionCompleteEvent. + */ +struct connection_role_t : SafeEnum { + enum type { + MASTER, + SLAVE + }; + + connection_role_t(type value) : SafeEnum(value) { } +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GAP_TYPES_H_ */ diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h new file mode 100644 index 0000000000..288b0f9d08 --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -0,0 +1,696 @@ +/* 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_GAP_H_ +#define BLE_PAL_GAP_H_ + +#include "platform/Callback.h" +#include "GapTypes.h" +#include "GapEvents.h" + +namespace ble { +namespace pal { + +/** + * Adaptation interface for the GAP layer. + * + * Define the primitive necessary to realize GAP operations. the API and event + * follow closely the definition of the HCI commands and events used + * by that layer. + */ +struct Gap { + /** + * 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 use 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; + + /** + * Return the public device address. + * + * @note The public device address is usually acquired at initialization and + * stored in the instance. + * + * @return the public device address. + */ + virtual address_t get_device_address() = 0; + + /** + * Return the current random address. + * + * @note The random address is usually acquired at initialization and stored + * in the instance. + * + * @return the random device address. + */ + virtual address_t get_random_address() = 0; + + /** + * Set the random address which will used be during scan, connection or + * advertising process if the own address type selected is random. + * + * Changing the address during scan, connection or advertising process is + * forbiden. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.4 LE set random address command. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + */ + virtual ble_error_t set_random_address(const address_t& address) = 0; + + /** + * Set the advertising parameters which will be used during the advertising + * process. + * + * @param advertising_interval_min: Minimum advertising interval which can + * be used during undirected and low duty cycle directed advertising. This + * parameter shall be less than or equal to advertising_interval_max. This + * parameter shall be in the range [0x20 : 0x4000] where each unit is equal + * to 0.625ms. + * This parameter is not used by directed high duty cycle advertising. + * + * @param advertising_interval_max: Maximum advertising interval which can + * be used during undirected and low duty cycle directed advertising. This + * parameter shall be more than or equal to advertising_interval_min. This + * parameter shall be in the range [0x20 : 0x4000] where each unit is equal + * to 0.625ms. + * This parameter is not used by directed high duty cycle advertising. + * + * @param advertising_type Packet type that is used during the + * advertising process. Direct advertising require valid peer addresses + * parameters and ignore the filter policy set. + * If the High duty cycle advertising is used then the advertising parameter + * intervals are ignored. + * + * @param own_address_type Own address type used during advertising. + * If own address type is equal to RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK + * or RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK then the peer address + * parameters (type and address) will be used to find the local IRK. + * + * @param peer_address_type Address type of the peer. + * This parameter shall be valid if directed advertising is used ( + * ADV_DIRECT_IND or ADV_DIRECT_IND_LOW_DUTY_CYCLE). This parameter should + * be valid if the own address type is equal to 0x02 or 0x03. + * In other cases, this parameter is ignored. + * + * @param peer_address Public device address, Random device addres, Public + * identity address or Random static identity address of the device targeted + * by the advertising. + * This parameter shall be valid if directed advertising is used ( + * ADV_DIRECT_IND or ADV_DIRECT_IND_LOW_DUTY_CYCLE). This parameter should + * be valid if the own address type is equal to 0x02 or 0x03. + * In other cases, this parameter is ignored. + * + * @param advertising_channel_map Map of the channel used to send + * advertising data. + * + * @param advertising_filter_policy Filter policy applied during the + * advertising process. The subsystem should use the whitelist to apply the + * policy. This parameter is ignored if the advertising type is directed ( + * ADV_DIRECT_IND or ADV_DIRECT_IND_LOW_DUTY_CYCLE). + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.5 LE set advertising parameters + * command. + */ + virtual ble_error_t set_advertising_parameters( + uint16_t advertising_interval_min, + uint16_t advertising_interval_max, + advertising_type_t advertising_type, + own_address_type_t own_address_type, + advertising_peer_address_type_t peer_address_type, + const address_t& peer_address, + advertising_channel_map_t advertising_channel_map, + advertising_filter_policy_t advertising_filter_policy + ) = 0; + + /** + * Set the data sends in advertising packet. If the advertising is + * currently enabled, the data shall be used when a new advertising packet + * is issued. + * + * @param advertising_data_length Number of significant bytes in the + * advertising data. + * + * @param advertising_data The data sends in advertising packets. Non + * significant bytes shall be equal to 0. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.5 LE set advertising data + * command. + */ + virtual ble_error_t set_advertising_data( + uint8_t advertising_data_length, + const advertising_data_t& advertising_data + ) = 0; + + /** + * Set the data sends in scan response packets. If the advertising is + * currently enabled, the data shall be used when a new scan response is + * issued. + * + * @param scan_response_data_length Number of significant bytes in the + * scan response data. + * + * @param scan_response_data The data sends in scan response packets. Non + * significant bytes shall be equal to 0. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.8 LE set scan response data + * command. + */ + virtual ble_error_t set_scan_response_data( + uint8_t scan_response_data_length, + const advertising_data_t& scan_response_data + ) = 0; + + /** + * Start or stop advertising. + * + * The process use advertising and scan response data set with + * set_advertising_data and set_scan_response_data while the parameters used + * are the one set by set_advertising_parameters. + * + * The advertising shall continue until: + * - The advertising is manually disabled (advertising_enable(false)). + * - A connection is created. + * - Time out in case of high duty cycle directed advertising. + * + * If the random address has not been set and the advertising parameter + * own_address_type is set to 0x01 then the procedure shall fail. + * + * If the random address has not been set and the advertising parameter + * own_address_type is set to RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK and + * the peer address is not in the resolving list then the procedure shall + * fail. + * + * @param enable If true start the advertising process, if the process was + * already runing and own_address_type is equal to 0x02 or 0x03, the + * subsystem can change the random address. + * If false and the advertising is running then the process should be + * stoped. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.9 LE set advertising enable + * command. + * + * @note If the advertising type is ADV_DIRECT_IND and the connection is not + * created during the time allowed to the procedure then a + * ConnectionComplete event shall be emmited with its error code set to + * ADVERTISING_TIMEOUT. + * + * @note Successfull connection shall emit a ConnectionComplete event. It + * also means advertising is disabled. + */ + virtual ble_error_t advertising_enable(bool enable) = 0; + + /** + * Set the parameter of the scan process. + * + * This command shall not be effective when the scanning process is running. + * + * @param active_scanning If true the subsystem does active scanning and + * the bluetooth subsystem shall send scanning PDUs. It shall also listen + * to scan responses. If false no scanning PDUs are sent during the scan + * process. + * + * @param scan_interval The time interval between two subsequent LE scans in + * unit of 0.625ms. This parameter shall be in the range [0x0004 : 0x4000]. + * + * @param scan_window Duration of the LE scan. It shall be less than or + * equal to scan_interval value. This parameter shall be in the range + * [0x0004 : 0x4000] and is in unit of 0.625ms. + * + * @param own_address_type Own address type used in scan request packets. + * + * @param filter_policy Filter policy applied when scanning. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.10 LE set scan parameters + * command. + */ + virtual ble_error_t set_scan_parameters( + bool active_scanning, + uint16_t scan_interval, + uint16_t scan_window, + own_address_type_t own_address_type, + scanning_filter_policy_t filter_policy + ) = 0; + + /** + * Start/stop scanning process. + * + * Parameters of the scanning process shall be set before the scan launch + * by using the function set_scan_parameters. + * + * @parameter enable Start the scanning process if true and stop it if + * false. If the scan process is already started, enabling it again will + * only update the duplicate filtering; based on the new parameter. + * + * @parameter filter_duplicates Enable duplicate filtering if true, + * otherwise disable it. + * + * @important advertising data or scan response data is not considered + * significant when determining duplicate advertising reports. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.11 LE set scan enable command. + */ + virtual ble_error_t scan_enable( + bool enable, + bool filter_duplicates + ) = 0; + + /** + * Create a new le connection to a connectable advertiser. + * + * @param scan_interval Hint to the le subsystem indicating how + * frequently it should scan for the peer address. It represent the time + * interval between two subsequent scan for the peer. It shall be in the + * range [0x0004 : 0x4000] and the time is in unit of 0.625ms. + * + * @param scan_window Hint to the le subsystem indicating for how long it + * should scan during a scan interval. The value shall be smaller or equal + * to scan_interval. If it is equal to scan_interval then scanning should + * run continuously. It shall be in the range [0x0004 : 0x4000] and the time + * is in unit of 0.625ms. + * + * @param initiator_policy Used to determine if the whitelist is used to + * determine the address to connect to. If the whitelist is not used, the + * connection shall be made against an advertiser matching the peer_address + * and the peer_address_type parameters. Otherwise those parameters are + * ignored. + * + * @param peer_address_type Type of address used by the advertiser. Not used + * if initiator_policy use the whitelist. + * + * @param Address used by the advertiser in its advertising packets. Not + * used if initiator_policy use the whitelist. + * + * @param own_address_type Type of address used in the connection request + * packet. + * + * @param connection_interval_min Minimum interval between two connection + * events allowed for the connection. It shall be less than or equal to + * connection_interval_max. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_interval_max Maximum interval between two connection + * events allowed for the connection. It shall be greater than or equal to + * connection_interval_min. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_latency Number of connection events the slave can drop + * if it has nothing to communicate to the master. This value shall be in + * the range [0x0000 : 0x01F3]. + * + * @param supervision_timeout Link supervision timeout for the connection. + * It shall be larger than: + * (1 + connection_latency) * connection_interval_max * 2 + * Note: connection_interval_max is in ms in this formulae. + * Everytime the master or the slave receive a valid packet from the peer, + * the supervision timer is reset. If the supervision timer reaches + * supervision_timeout then the connection is considered lost and a + * disconnect event shall be emmited. + * This value shall be in the range [0x000A : 0x0C80] and is in unit of 10 + * ms. + * + * @param minimum_connection_event_length Informative parameter of the + * minimum length a connection event. It shall be less than or equal to + * maximum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @param maximum_connection_event_length Informative parameter of the + * maximum length a connection event. It shall be more than or equal to + * minimum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.12 LE create connection command. + */ + virtual ble_error_t create_connection( + uint16_t scan_interval, + uint16_t scan_window, + initiator_policy_t initiator_policy, + connection_peer_address_type_t peer_address_type, + const address_t& peer_address, + own_address_type_t own_address_type, + uint16_t connection_interval_min, + uint16_t connection_interval_max, + uint16_t connection_latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length + ) = 0; + + /** + * Cancel the ongoing connection creation process. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.13 LE create connection cancel + * command. + */ + virtual ble_error_t cancel_connection_creation() = 0; + + /** + * Return the number of total whitelist entries that can be stored in the + * le subsystem. + * + * @note The value returned can change over time. + * + * @return The number of entries that can be stored in the LE subsystem. It + * range from 0x01 to 0xFF. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.14 LE read white list size + * command. + */ + virtual uint8_t read_white_list_capacity() = 0; + + /** + * Clear the whitelist stored in the LE subsystem. + * + * @important This command shall not be issued if the whitelist is being + * used by the advertising, scanning or connection creation procedure. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.15 LE clear white list command. + */ + virtual ble_error_t clear_whitelist() = 0; + + /** + * Add a device to the LE subsystem Whitelist. + * + * @param address_type address_type Type of the address to add in the + * whitelist. + * + * @param address Address of the device. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @important This command shall not be issued if the whitelist is being + * used by the advertising, scanning or connection creation procedure. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.16 LE add device to white list + * command. + */ + virtual ble_error_t add_device_to_whitelist( + whitelist_address_type_t address_type, + address_t address + ) = 0; + + /** + * Remove a device from the LE subsystem Whitelist. + * + * @param address_type address_type Type of the address of the device to + * remove from the whitelist. + * + * @param address Address of the device to remove from the whitelist + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @important This command shall not be issued if the whitelist is being + * used by the advertising, scanning or connection creation procedure. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.17 LE remove device from white + * list command. + */ + virtual ble_error_t remove_device_from_whitelist( + whitelist_address_type_t address_type, + address_t address + ) = 0; + + /** + * Start a connection update procedure. + * + * This procedure change the parameter used for a connection it can be + * master or slave initiated. + * + * The peer will received a connection parameters request and will either + * accept or reject the new parameters for the connection. + * + * Once the peer response has been received, the procedure ends and a + * Connection update complete event is emmited. + * + * @param connection Handle of the connection. + * + * @param connection_interval_min Minimum interval between two connection + * events allowed for the connection. It shall be less than or equal to + * connection_interval_max. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_interval_max Maximum interval between two connection + * events allowed for the connection. It shall be greater than or equal to + * connection_interval_min. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_latency Number of connection events the slave can drop + * if it has nothing to communicate to the master. This value shall be in + * the range [0x0000 : 0x01F3]. + * + * @param supervision_timeout Link supervision timeout for the connection. + * It shall be larger than: + * (1 + connection_latency) * connection_interval_max * 2 + * Note: connection_interval_max is in ms in this formulae. + * Everytime the master or the slave receive a valid packet from the peer, + * the supervision timer is reset. If the supervision timer reaches + * supervision_timeout then the connection is considered lost and a + * disconnect event shall be emmited. + * This value shall be in the range [0x000A : 0x0C80] and is in unit of 10 + * ms. + * + * @param minimum_connection_event_length Informative parameter of the + * minimum length a connection event. It shall be less than or equal to + * maximum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @param maximum_connection_event_length Informative parameter of the + * maximum length a connection event. It shall be more than or equal to + * minimum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.18 LE Connection update command. + * + */ + virtual ble_error_t connection_parameters_update( + connection_handle_t connection, + uint16_t connection_interval_min, + uint16_t connection_interval_max, + uint16_t connection_latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length + ) = 0; + + /** + * Accept connection parameter request. + * + * This command sends a positive response to a connection parameter request + * from a peer. + * + * @param connection Handle of the connection. + * + * @param connection_interval_min Minimum interval between two connection + * events allowed for the connection. It shall be less than or equal to + * connection_interval_max. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_interval_max Maximum interval between two connection + * events allowed for the connection. It shall be greater than or equal to + * connection_interval_min. This value shall be in range [0x0006 : 0x0C80] + * and is in unit of 1.25ms. + * + * @param connection_latency Number of connection events the slave can drop + * if it has nothing to communicate to the master. This value shall be in + * the range [0x0000 : 0x01F3]. + * + * @param supervision_timeout Link supervision timeout for the connection. + * It shall be larger than: + * (1 + connection_latency) * connection_interval_max * 2 + * Note: connection_interval_max is in ms in this formulae. + * Everytime the master or the slave receive a valid packet from the peer, + * the supervision timer is reset. If the supervision timer reaches + * supervision_timeout then the connection is considered lost and a + * disconnect event shall be emmited. + * This value shall be in the range [0x000A : 0x0C80] and is in unit of 10 + * ms. + * + * @param minimum_connection_event_length Informative parameter of the + * minimum length a connection event. It shall be less than or equal to + * maximum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @param maximum_connection_event_length Informative parameter of the + * maximum length a connection event. It shall be more than or equal to + * minimum_connection_event_length. It shall be in the range + * [0x0000 : 0xFFFF]. It should also be less than the expected connection + * interval. The unit is 0.625ms. + * + * @note Usually parameters of this function match the connection parameters + * received in the connection parameter request event. + * + * @important: Once the new connection parameters are in used a Connection + * Update Complete event shall be emmited. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.31 LE remote connection parameter + * request reply command. + */ + virtual ble_error_t accept_connection_parameter_request( + connection_handle_t connection_handle, + uint16_t interval_min, + uint16_t interval_max, + uint16_t latency, + uint16_t supervision_timeout, + uint16_t minimum_connection_event_length, + uint16_t maximum_connection_event_length + ) = 0; + + /** + * Reject a connection parameter update request. + * + * @param connection_handle handle to the peer which has issued the + * connection parameter request. + * + * @param rejection_reason Indicate to the peer why the proposed connection + * parameters were rejected. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.32 LE Remote Connection Parameter + * Request Negative Reply Command. + */ + virtual ble_error_t reject_connection_parameter_request( + connection_handle_t connection_handle, + hci_error_code_t rejection_reason + ) = 0; + + /** + * Start a disconnection procedure. + * + * Once the procedure is complete it should emit a disconnection complete + * event. + * + * @param connection Handle of the connection to terminate. + * + * @param disconnection_reason Indicates the reason for ending the + * connection. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.1.6 disconenct command. + */ + virtual ble_error_t disconnect( + connection_handle_t connection, + disconnection_reason_t disconnection_reason + ) = 0; + + /** + * Register a callback which will handle Gap events. + * + * @param cb The callback object which will handle Gap events from the + * LE subsystem. + * It accept a single parameter in input: The event received. + */ + void when_gap_event_received(mbed::Callback cb) + { + _gap_event_cb = cb; + } + +protected: + Gap() { } + + virtual ~Gap() { } + + /** + * Implementation shall call this function whenever the LE subsystem + * generate a Gap event. + * + * @param gap_event The event to emit to higher layer. + */ + void emit_gap_event(const GapEvent& gap_event) + { + if (_gap_event_cb) { + _gap_event_cb(gap_event); + } + } + +private: + /** + * Callback called when an event is emitted by the LE subsystem. + */ + mbed::Callback _gap_event_cb; + + // Disallow copy construction and copy assignment. + Gap(const Gap&); + Gap& operator=(const Gap&); +}; + +} // namespace pal +} // namespace ble + +#endif /* BLE_PAL_GAP_H_ */