• 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 <atomic>
17 #include <memory>
18 #include <thread>
19 
20 #include "pw_bluetooth/controller.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/inspect.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
24 #include "pw_bluetooth_sapphire/internal/host/transport/acl_data_channel.h"
25 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
26 #include "pw_bluetooth_sapphire/internal/host/transport/sco_data_channel.h"
27 
28 namespace bt::hci {
29 
30 // Represents the HCI transport layer. This object owns the HCI command, ACL,
31 // and SCO channels and provides the necessary control-flow mechanisms to send
32 // and receive HCI packets from the underlying Bluetooth controller.
33 class Transport final : public WeakSelf<Transport> {
34  public:
35   explicit Transport(std::unique_ptr<pw::bluetooth::Controller> hci,
36                      pw::async::Dispatcher& dispatcher);
37 
38   // Initializes the command channel and features. The result will be reported
39   // via |complete_callback|.
40   //
41   // NOTE: AclDataChannel and ScoDataChannel will be left uninitialized. They
42   // must be initialized after available data buffer information has been
43   // obtained from the controller (via HCI_Read_Buffer_Size and
44   // HCI_LE_Read_Buffer_Size).
45   void Initialize(fit::callback<void(bool /*success*/)> complete_callback);
46 
47   // TODO(armansito): hci::Transport::~Transport() should send a shutdown
48   // message to the bt-hci device, which would be responsible for sending
49   // HCI_Reset upon exit.
50   ~Transport();
51 
52   // Initializes the ACL data channel with the given parameters. Returns false
53   // if an error occurs during initialization. Initialize() must have been
54   // called successfully prior to calling this method.
55   bool InitializeACLDataChannel(const DataBufferInfo& bredr_buffer_info,
56                                 const DataBufferInfo& le_buffer_info);
57 
58   // Initializes the SCO data channel with the given parameters. Returns false
59   // if an error occurs during initialization.
60   bool InitializeScoDataChannel(const DataBufferInfo& buffer_info);
61 
62   pw::bluetooth::Controller::FeaturesBits GetFeatures();
63 
64   // Returns a pointer to the HCI command and event flow control handler.
65   // CommandChannel is guaranteed to live as long as Transport, but may stop
66   // processing packets after the Transport error callback has been called.
command_channel()67   CommandChannel* command_channel() const { return command_channel_.get(); }
68 
69   // Returns a pointer to the HCI ACL data flow control handler. Nullptr until
70   // InitializeACLDataChannel() has succeeded.
71   // AclDataChannel is guaranteed to live as long as Transport.
acl_data_channel()72   AclDataChannel* acl_data_channel() const { return acl_data_channel_.get(); }
73 
74   // Returns a pointer to the HCI SCO data flow control handler. Nullptr until
75   // InitializeScoDataChannel succeeds.
76   // ScoDataChannel is guaranteed to live as long as Transport.
sco_data_channel()77   ScoDataChannel* sco_data_channel() const { return sco_data_channel_.get(); }
78 
79   // Set a callback that should be invoked when any one of the underlying
80   // channels experiences a fatal error (e.g. the HCI device has disappeared).
81   //
82   // When this callback is called the channels will be in an invalid state and
83   // packet processing is no longer guaranteed to work. However, the channel
84   // pointers are guaranteed to still be valid. It is the responsibility of the
85   // callback implementation to clean up this Transport instance.
86   void SetTransportErrorCallback(fit::closure callback);
87 
88   // Attach hci transport inspect node as a child node of |parent|.
89   static constexpr const char* kInspectNodeName = "hci";
90   void AttachInspect(inspect::Node& parent,
91                      const std::string& name = kInspectNodeName);
92 
93  private:
94   // Callback called by CommandChannel or ACLDataChannel on errors.
95   void OnChannelError();
96 
97   pw::async::Dispatcher& dispatcher_;
98 
99   // HCI inspect node.
100   inspect::Node hci_node_;
101 
102   // Callback invoked when the transport is closed (due to a channel error).
103   fit::closure error_cb_;
104 
105   std::unique_ptr<pw::bluetooth::Controller> controller_;
106 
107   std::optional<pw::bluetooth::Controller::FeaturesBits> features_;
108 
109   // The HCI command and event flow control handler.
110   // CommandChannel must be constructed first & shut down last because
111   // AclDataChannel and ScoDataChannel depend on it. CommandChannel must live as
112   // long as Transport to meet the expectations of upper layers, which may try
113   // to send commands on destruction.
114   std::unique_ptr<CommandChannel> command_channel_;
115 
116   // The ACL data flow control handler.
117   std::unique_ptr<AclDataChannel> acl_data_channel_;
118 
119   // The SCO data flow control handler.
120   std::unique_ptr<ScoDataChannel> sco_data_channel_;
121 
122   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Transport);
123 };
124 
125 }  // namespace bt::hci
126