1 // Copyright 2023 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 15 #pragma once 16 #include <optional> 17 18 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h" 19 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection_request.h" 20 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_interrogator.h" 21 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h" 22 #include "pw_bluetooth_sapphire/internal/host/gap/pairing_state.h" 23 #include "pw_bluetooth_sapphire/internal/host/gap/peer.h" 24 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h" 25 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h" 26 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 27 #include "pw_bluetooth_sapphire/internal/host/sco/sco_connection_manager.h" 28 #include "pw_bluetooth_sapphire/internal/host/sm/types.h" 29 30 namespace bt::gap { 31 32 class PeerCache; 33 class PairingState; 34 35 // Represents an ACL connection that is currently open with the controller (i.e. 36 // after receiving a Connection Complete and before either user disconnection or 37 // Disconnection Complete). 38 class BrEdrConnection final { 39 public: 40 // |send_auth_request_cb| is called during pairing, and should send the 41 // authenticaion request HCI command. |disconnect_cb| is called when an error 42 // occurs and the link should be disconnected. |on_peer_disconnect_cb| is 43 // called when the peer disconnects and this connection should be destroyed. 44 using Request = BrEdrConnectionRequest; 45 BrEdrConnection(Peer::WeakPtr peer, 46 std::unique_ptr<hci::BrEdrConnection> link, 47 fit::closure send_auth_request_cb, 48 fit::callback<void()> disconnect_cb, 49 fit::closure on_peer_disconnect_cb, 50 l2cap::ChannelManager* l2cap, 51 hci::Transport::WeakPtr transport, 52 std::optional<Request> request, 53 pw::async::Dispatcher& pw_dispatcher); 54 55 ~BrEdrConnection(); 56 57 BrEdrConnection(BrEdrConnection&&) = default; 58 59 void Interrogate(BrEdrInterrogator::ResultCallback callback); 60 61 // Called after interrogation completes to mark this connection as available 62 // for upper layers, i.e. L2CAP. Also signals any requesters with a successful 63 // status and this connection. If not called and this connection is deleted 64 // (e.g. by disconnection), requesters will be signaled with 65 // |HostError::kNotSupported| (to indicate interrogation error). 66 void OnInterrogationComplete(); 67 68 // Add a request callback that will be called when OnInterrogationComplete() 69 // is called (or immediately if OnInterrogationComplete() has already been 70 // called). 71 void AddRequestCallback(Request::OnComplete cb); 72 73 // If |OnInterrogationComplete| has been called, opens an L2CAP channel using 74 // the preferred parameters |params| on the L2cap provided. Otherwise, calls 75 // |cb| with a nullptr. 76 void OpenL2capChannel(l2cap::Psm psm, 77 l2cap::ChannelParameters params, 78 l2cap::ChannelCallback cb); 79 80 // See ScoConnectionManager for documentation. 81 using ScoRequestHandle = sco::ScoConnectionManager::RequestHandle; 82 ScoRequestHandle OpenScoConnection( 83 bt::StaticPacket< 84 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>, 85 sco::ScoConnectionManager::OpenConnectionCallback callback); 86 ScoRequestHandle AcceptScoConnection( 87 std::vector<bt::StaticPacket< 88 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>> 89 parameters, 90 sco::ScoConnectionManager::AcceptConnectionCallback callback); 91 92 // Attach connection inspect node as a child of |parent| named |name|. 93 void AttachInspect(inspect::Node& parent, std::string name); 94 link()95 const hci::Connection& link() const { return *link_; } link()96 hci::BrEdrConnection& link() { return *link_; } peer_id()97 PeerId peer_id() const { return peer_id_; } pairing_state()98 PairingState& pairing_state() { return *pairing_state_; } 99 100 // Returns the duration that this connection has been alive. 101 pw::chrono::SystemClock::duration duration() const; 102 security_properties()103 sm::SecurityProperties security_properties() const { 104 BT_ASSERT(pairing_state_); 105 return pairing_state_->security_properties(); 106 } 107 set_security_mode(BrEdrSecurityMode mode)108 void set_security_mode(BrEdrSecurityMode mode) { 109 BT_ASSERT(pairing_state_); 110 pairing_state_->set_security_mode(mode); 111 } 112 113 private: 114 // |conn_token| is a token received from Peer::MutBrEdr::RegisterConnection(). 115 void set_peer_connection_token(Peer::ConnectionToken conn_token); 116 117 // Called by |pairing_state_| when pairing completes with |status|. 118 void OnPairingStateStatus(hci_spec::ConnectionHandle handle, 119 hci::Result<> status); 120 interrogation_complete()121 bool interrogation_complete() const { return !request_.has_value(); } 122 123 PeerId peer_id_; 124 Peer::WeakPtr peer_; 125 std::unique_ptr<hci::BrEdrConnection> link_; 126 std::optional<Request> request_; 127 std::unique_ptr<PairingState> pairing_state_; 128 l2cap::ChannelManager* l2cap_; 129 std::unique_ptr<sco::ScoConnectionManager> sco_manager_; 130 std::unique_ptr<BrEdrInterrogator> interrogator_; 131 // Time this object was constructed. 132 pw::chrono::SystemClock::time_point create_time_; 133 // Called when an error occurs and this connection should be disconnected. 134 fit::callback<void()> disconnect_cb_; 135 136 struct InspectProperties { 137 inspect::StringProperty peer_id; 138 }; 139 InspectProperties inspect_properties_; 140 inspect::Node inspect_node_; 141 142 std::optional<Peer::InitializingConnectionToken> peer_init_token_; 143 // Ensures that this peer is marked "connected" once pairing completes. 144 // Unregisters the connection from PeerCache when this connection is 145 // destroyed. 146 Peer::ConnectionToken peer_conn_token_; 147 148 pw::async::Dispatcher& dispatcher_; 149 150 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrConnection); 151 }; 152 153 } // namespace bt::gap 154