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