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