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