• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <lib/fit/function.h>
17 
18 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
19 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
20 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
21 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
22 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
23 #include "pw_bluetooth_sapphire/internal/host/transport/error.h"
24 #include "pw_bluetooth_sapphire/internal/host/transport/link_type.h"
25 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
26 
27 namespace bt::hci {
28 
29 // A Connection represents a logical link connection to a peer. It maintains
30 // link-specific configuration parameters (such as the connection handle) and
31 // state (e.g kConnected/kDisconnected). Controller procedures that are related
32 // to managing a logical link are performed by a Connection, e.g. disconnecting
33 // the link.
34 //
35 // Connection instances are intended to be uniquely owned. The owner of an
36 // instance is also the owner of the underlying link and the lifetime of a
37 // Connection determines the lifetime of the link.
38 //
39 // Connection is not expected to be constructed directly. Users should instead
40 // construct a specialization based on the link type: LowEnergyConnection,
41 // BrEdrConnection, or ScoConnection,
42 class Connection {
43  public:
44   enum class State {
45     // Default state of a newly created Connection. This is the only connection
46     // state that is
47     // considered "open".
48     kConnected,
49 
50     // HCI Disconnect command has been sent, but HCI Disconnection Complete
51     // event has not yet been
52     // received. This state is skipped when the disconnection is initiated by
53     // the peer.
54     kWaitingForDisconnectionComplete,
55 
56     // HCI Disconnection Complete event has been received.
57     kDisconnected
58   };
59 
60   // The destructor closes this connection.
61   virtual ~Connection();
62 
63   // Returns a string representation.
64   virtual std::string ToString() const;
65 
66   // Returns the 12-bit connection handle of this connection. This handle is
67   // used to identify an individual logical link maintained by the controller.
handle()68   hci_spec::ConnectionHandle handle() const { return handle_; }
69 
70   // The local device address used while establishing the connection.
local_address()71   const DeviceAddress& local_address() const { return local_address_; }
72 
73   // The peer address used while establishing the connection.
peer_address()74   const DeviceAddress& peer_address() const { return peer_address_; }
75 
state()76   State state() const { return conn_state_; }
77 
78   // Assigns a callback that will be run when the peer disconnects.
79   using PeerDisconnectCallback = fit::function<void(
80       const Connection& connection, pw::bluetooth::emboss::StatusCode reason)>;
set_peer_disconnect_callback(PeerDisconnectCallback callback)81   void set_peer_disconnect_callback(PeerDisconnectCallback callback) {
82     peer_disconnect_callback_ = std::move(callback);
83   }
84 
85   // Send HCI Disconnect and set state to closed. Must not be called on an
86   // already disconnected connection.
87   virtual void Disconnect(pw::bluetooth::emboss::StatusCode reason);
88 
89  protected:
90   // |on_disconnection_complete| will be called when the disconnection complete
91   // event is received, which may be after this object is destroyed (which is
92   // why this isn't a virtual method).
93   Connection(hci_spec::ConnectionHandle handle,
94              const DeviceAddress& local_address,
95              const DeviceAddress& peer_address,
96              Transport::WeakPtr hci,
97              fit::callback<void()> on_disconnection_complete);
98 
hci()99   const Transport::WeakPtr& hci() { return hci_; }
100 
peer_disconnect_callback()101   PeerDisconnectCallback& peer_disconnect_callback() {
102     return peer_disconnect_callback_;
103   }
104 
105  private:
106   // Checks |event|, unregisters link, and clears pending packets count.
107   // If the disconnection was initiated by the peer, call
108   // |peer_disconnect_callback|. Returns true if event was valid and for this
109   // connection. This method is static so that it can be called in an event
110   // handler after this object has been destroyed.
111   static CommandChannel::EventCallbackResult OnDisconnectionComplete(
112       const WeakSelf<Connection>::WeakPtr& self,
113       hci_spec::ConnectionHandle handle,
114       const EventPacket& event,
115       fit::callback<void()> on_disconnection_complete);
116 
117   hci_spec::ConnectionHandle handle_;
118 
119   // Addresses used while creating the link.
120   DeviceAddress local_address_;
121   DeviceAddress peer_address_;
122 
123   PeerDisconnectCallback peer_disconnect_callback_;
124 
125   State conn_state_;
126 
127   Transport::WeakPtr hci_;
128 
129   WeakSelf<Connection> weak_self_;
130 
131   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Connection);
132 };
133 
134 }  // namespace bt::hci
135