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 "pw_bluetooth/controller.h" 17 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h" 18 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h" 19 #include "pw_bluetooth_sapphire/internal/host/transport/data_buffer_info.h" 20 #include "pw_bluetooth_sapphire/internal/host/transport/sco_data_packet.h" 21 22 namespace bt::hci { 23 24 class Transport; 25 26 // Represents the Bluetooth SCO Data channel and manages the Host->Controller 27 // SCO data flow when SCO is not offloaded. ScoDataChannel uses a pull model, 28 // where packets are queued in the connections and only read by ScoDataChannel 29 // when controller buffer space is available. 30 // TODO(fxbug.dev/42173137): Only 1 connection's bandwidth is configured with 31 // the transport driver at a time, so performance may be poor if multiple 32 // connections are registered. The connection used for the current configuration 33 // is selected randomly. 34 // TODO(fxbug.dev/42171056): ScoDataChannel assumes that HCI flow control via 35 // HCI_Number_Of_Completed_Packets events is supported by the controller. Some 36 // controllers don't support this form of flow control. 37 class ScoDataChannel { 38 public: 39 // Registered SCO connections must implement this interface to send and 40 // receive packets. 41 class ConnectionInterface { 42 public: 43 virtual ~ConnectionInterface() = default; 44 45 virtual hci_spec::ConnectionHandle handle() const = 0; 46 47 // These parameters must specify a data path of 48 // pw::bluetooth::emboss::ScoDataPath::HCI. 49 virtual bt::StaticPacket< 50 pw::bluetooth::emboss::SynchronousConnectionParametersWriter> 51 parameters() = 0; 52 53 // ScoDataChannel will call this method to get the next packet to send to 54 // the controller. If no packet is available, return nullptr. 55 virtual std::unique_ptr<ScoDataPacket> GetNextOutboundPacket() = 0; 56 57 // This method will be called when a packet is received for this connection. 58 virtual void ReceiveInboundPacket( 59 std::unique_ptr<ScoDataPacket> packet) = 0; 60 61 // Called when there is an internal error and this connection has been 62 // unregistered. Unregistering this connection is unnecessary, but harmless. 63 virtual void OnHciError() = 0; 64 }; 65 66 static std::unique_ptr<ScoDataChannel> Create( 67 const DataBufferInfo& buffer_info, 68 CommandChannel* command_channel, 69 pw::bluetooth::Controller* hci); 70 virtual ~ScoDataChannel() = default; 71 72 // Register a connection. The connection must have a data path of 73 // pw::bluetooth::emboss::ScoDataPath::kHci. 74 virtual void RegisterConnection(WeakPtr<ConnectionInterface> connection) = 0; 75 76 // Unregister a connection when it is disconnected. 77 // |UnregisterConnection| does not clear the controller packet count, so 78 // |ClearControllerPacketCount| must be called after |UnregisterConnection| 79 // and the HCI_Disconnection_Complete event has been received. 80 virtual void UnregisterConnection(hci_spec::ConnectionHandle handle) = 0; 81 82 // Resets controller packet count for |handle| so that controller buffer 83 // credits can be reused. This must be called on the 84 // HCI_Disconnection_Complete event to notify ScoDataChannel that packets in 85 // the controller's buffer for |handle| have been flushed. See Core Spec v5.1, 86 // Vol 2, Part E, Section 4.3. This must be called after 87 // |UnregisterConnection|. 88 virtual void ClearControllerPacketCount( 89 hci_spec::ConnectionHandle handle) = 0; 90 91 // Called by connections when an outbound packet is available (via 92 // ConnectionInterface::GetNextOutboundPacket). 93 virtual void OnOutboundPacketReadable() = 0; 94 95 // The controller's SCO max data length (not including header). 96 virtual uint16_t max_data_length() const = 0; 97 }; 98 99 } // namespace bt::hci 100