1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_async2/dispatcher.h" 17 #include "pw_bluetooth/gatt/client2.h" 18 #include "pw_bluetooth/internal/raii_ptr.h" 19 #include "pw_bluetooth/low_energy/channel.h" 20 #include "pw_bluetooth/types.h" 21 22 namespace pw::bluetooth::low_energy { 23 24 /// Class that represents a connection to a peer. This can be used to interact 25 /// with GATT services and establish LE L2CAP channels. 26 /// 27 /// The lifetime of this object is tied to that of the LE connection it 28 /// represents. Destroying the object results in a disconnection. 29 class Connection2 { 30 public: 31 /// Possible errors when updating the connection parameters. 32 enum class ConnectionParameterUpdateError : uint8_t { 33 kFailure, 34 kInvalidParameters, 35 kRejected, 36 }; 37 38 /// Possible reasons a connection was disconnected. 39 enum class DisconnectReason : uint8_t { 40 kFailure, 41 kRemoteUserTerminatedConnection, 42 /// This usually indicates that the link supervision timeout expired. 43 kConnectionTimeout, 44 }; 45 46 /// Actual connection parameters returned by the controller. 47 struct ConnectionParameters { 48 /// The connection interval indicates the frequency of link layer connection 49 /// events over which data channel PDUs can be transmitted. See Core Spec 50 /// v6, Vol 6, Part B, Section 4.5.1 for more information on the link 51 /// layer connection events. 52 /// - Range: 0x0006 to 0x0C80 53 /// - Time: N * 1.25 ms 54 /// - Time Range: 7.5 ms to 4 s. 55 uint16_t interval; 56 57 /// The maximum allowed peripheral connection latency in number of 58 /// connection events. See Core Spec v5, Vol 6, Part B, Section 4.5.1. 59 /// - Range: 0x0000 to 0x01F3 60 uint16_t latency; 61 62 /// This defines the maximum time between two received data packet PDUs 63 /// before the connection is considered lost. See Core Spec v6, Vol 6, 64 /// Part B, Section 4.5.2. 65 /// - Range: 0x000A to 0x0C80 66 /// - Time: N * 10 ms 67 /// - Time Range: 100 ms to 32 s 68 uint16_t supervision_timeout; 69 }; 70 71 /// Connection parameters that either the local device or a peer device are 72 /// requesting. 73 struct RequestedConnectionParameters { 74 /// Minimum value for the connection interval. This shall be less than or 75 /// equal to `max_interval`. The connection interval indicates the frequency 76 /// of link layer connection events over which data channel PDUs can be 77 /// transmitted. See Core Spec v6, Vol 6, Part B, Section 4.5.1 for more 78 /// information on the link layer connection events. 79 /// - Range: 0x0006 to 0x0C80 80 /// - Time: N * 1.25 ms 81 /// - Time Range: 7.5 ms to 4 s. 82 uint16_t min_interval; 83 84 /// Maximum value for the connection interval. This shall be greater than or 85 /// equal to `min_interval`. The connection interval indicates the frequency 86 /// of link layer connection events over which data channel PDUs can be 87 /// transmitted. See Core Spec v6, Vol 6, Part B, Section 4.5.1 for more 88 /// information on the link layer connection events. 89 /// - Range: 0x0006 to 0x0C80 90 /// - Time: N * 1.25 ms 91 /// - Time Range: 7.5 ms to 4 s. 92 uint16_t max_interval; 93 94 /// Maximum peripheral latency for the connection in number of connection 95 /// events. See Core Spec v6, Vol 6, Part B, Section 4.5.1. 96 /// - Range: 0x0000 to 0x01F3 97 uint16_t max_latency; 98 99 /// This defines the maximum time between two received data packet PDUs 100 /// before the connection is considered lost. See Core Spec v6, Vol 6, 101 /// Part B, Section 4.5.2. 102 /// - Range: 0x000A to 0x0C80 103 /// - Time: N * 10 ms 104 /// - Time Range: 100 ms to 32 s 105 uint16_t supervision_timeout; 106 }; 107 108 /// Represents parameters that are set on a per-connection basis. 109 struct ConnectionOptions { 110 /// When true, the connection operates in bondable mode. This means pairing 111 /// will form a bond, or persist across disconnections, if the peer is also 112 /// in bondable mode. When false, the connection operates in non-bondable 113 /// mode, which means the local device only allows pairing that does not 114 /// form a bond. 115 bool bondable_mode = true; 116 117 /// When present, service discovery performed following the connection is 118 /// restricted to primary services that match this field. Otherwise, by 119 /// default all available services are discovered. 120 std::optional<Uuid> service_filter; 121 122 /// When present, specifies the initial connection parameters. Otherwise, 123 /// the connection parameters will be selected by the implementation. 124 std::optional<RequestedConnectionParameters> parameters; 125 126 /// When present, specifies the ATT MTU to request. The actual MTU used may 127 /// be smaller depending on peer and controller support. If none is 128 /// specified, the host implementation will select the ATT MTU. Note that an 129 /// MTU of 247 is the largest that can fit into a single LE data packet with 130 /// the Data Length Extension. 131 /// - LE ATT MTU Range: 23 to 517 132 /// - LE EATT MTU Range: 64 to 517 133 std::optional<uint16_t> att_mtu; 134 }; 135 136 struct ConnectL2capParameters { 137 /// The identifier of the service to connect to. 138 Psm psm; 139 /// Maximum supported packet size for receiving. 140 uint16_t max_receive_packet_size; 141 /// The security requirements that must be met before data is exchanged on 142 /// the channel. If the requirements cannot be met, channel establishment 143 /// will fail. 144 SecurityRequirements security_requirements; 145 }; 146 147 /// If a disconnection has not occurred, destroying this object will result in 148 /// disconnection. 149 virtual ~Connection2() = default; 150 151 /// Returns Ready after the peer disconnects or there is a connection error 152 /// that caused a disconnection. Awakens `cx` on disconnect. 153 virtual async2::Poll<DisconnectReason> PendDisconnect( 154 async2::Context& cx) = 0; 155 156 /// Returns a GATT client to the connected peer that is valid for the lifetime 157 /// of this `Connection2` object. `Connection2` is considered alive as long as 158 /// `PendDisconnect()` returns pending and the object hasn't been destroyed. 159 virtual gatt::Client2* GattClient() = 0; 160 161 /// Returns the current ATT Maximum Transmission Unit. By subtracting ATT 162 /// headers from the MTU, the maximum payload size of messages can be 163 /// calculated. 164 virtual uint16_t AttMtu() = 0; 165 166 /// Returns Pending until the ATT MTU changes, at which point `cx` will be 167 /// awoken. Returns Ready with the new ATT MTU once the ATT MTU has been 168 /// changed. The ATT MTU can only be changed once. 169 virtual async2::Poll<uint16_t> PendAttMtuChange(async2::Context& cx) = 0; 170 171 /// Returns the current connection parameters. 172 virtual ConnectionParameters Parameters() = 0; 173 174 /// Requests an update to the connection parameters. 175 /// @returns Asynchronously returns the result of the request. 176 virtual async2::OnceReceiver< 177 pw::expected<void, ConnectionParameterUpdateError>> 178 RequestParameterUpdate(RequestedConnectionParameters parameters) = 0; 179 180 /// Connect to an L2CAP LE connection-oriented channel. 181 /// @param parameters The parameters to configure the channel with. 182 /// @return The result of the connection procedure. On success, contains a 183 /// `Channel` that can be used to exchange data. 184 virtual async2::OnceReceiver<pw::Result<Channel::Ptr>> ConnectL2cap( 185 ConnectL2capParameters parameters) = 0; 186 187 private: 188 /// Request to disconnect this connection. This method is called by the 189 /// ~Connection::Ptr() when it goes out of scope, the API client should never 190 /// call this method. 191 virtual void Disconnect() = 0; 192 193 public: 194 /// Movable `Connection2` smart pointer. When `Connection::Ptr` is destroyed 195 /// the `Connection2` will disconnect automatically. 196 using Ptr = internal::RaiiPtr<Connection2, &Connection2::Disconnect>; 197 }; 198 199 } // namespace pw::bluetooth::low_energy 200