1 // Copyright 2024 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 
17 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
18 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
19 #include "pw_bluetooth_sapphire/internal/host/iso/iso_common.h"
20 #include "pw_bluetooth_sapphire/internal/host/iso/iso_stream.h"
21 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
22 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
23 
24 namespace bt::iso {
25 
26 // Responsible for owning and managing IsoStream objects associated with a
27 // single LE connection.
28 // When operating as a Central, establishes an outgoing streams. When operating
29 // as a Peripheral, processes incoming stream requests .
30 class IsoStreamManager final {
31  public:
32   explicit IsoStreamManager(hci_spec::ConnectionHandle handle,
33                             hci::Transport::WeakPtr hci);
34   ~IsoStreamManager();
35 
36   // Start waiting on an incoming request to create an Isochronous channel for
37   // the specified CIG/CIS |id|. If we are already waiting on |id|, or if a
38   // stream has already been established with the given |id|, returns
39   // kAlreadyExists. |cb| will be invoked when we receive an incoming ISO
40   // channel request with a matching CIG/CIS |id|, and will indicate the status
41   // of establishing a channel and on success the associated channel parameters.
42   [[nodiscard]] AcceptCisStatus AcceptCis(CigCisIdentifier id,
43                                           CisEstablishedCallback cb);
44 
45   // Indicates if we are currently waiting on a connection for the specified
46   // CIG/CIS combination
HandlerRegistered(const CigCisIdentifier & id)47   bool HandlerRegistered(const CigCisIdentifier& id) const {
48     return accept_handlers_.count(id) != 0;
49   }
50 
51   using WeakPtr = WeakSelf<IsoStreamManager>::WeakPtr;
GetWeakPtr()52   IsoStreamManager::WeakPtr GetWeakPtr() { return weak_self_.GetWeakPtr(); }
53 
54  private:
55   // Process an incoming CIS request. Currently rejects all requests.
56   void OnCisRequest(const hci::EventPacket& event);
57 
58   // Process a disconnection and shut down a CIS.
59   void OnDisconnect(const hci::EventPacket& event);
60 
61   void AcceptCisRequest(
62       const pw::bluetooth::emboss::LECISRequestSubeventView& event_view,
63       CisEstablishedCallback cb);
64 
65   // Send a rejection in response to an incoming CIS request.
66   void RejectCisRequest(
67       const pw::bluetooth::emboss::LECISRequestSubeventView& event_view);
68 
69   hci_spec::ConnectionHandle acl_handle_;
70 
71   // LE event handler for incoming CIS requests
72   hci::CommandChannel::EventHandlerId cis_request_handler_;
73   // Event handler for disconnect events
74   hci::CommandChannel::EventHandlerId disconnect_handler_;
75 
76   hci::CommandChannel::WeakPtr cmd_;
77 
78   hci::Transport::WeakPtr hci_;
79 
80   // The streams that we are currently waiting on, and the associated callback
81   // when the connection is resolved (either accepted and established, or failed
82   // to establish).
83   std::unordered_map<CigCisIdentifier, CisEstablishedCallback> accept_handlers_;
84 
85   // All of the allocated streams.
86   std::unordered_map<CigCisIdentifier, std::unique_ptr<IsoStream>> streams_;
87 
88   WeakSelf<IsoStreamManager> weak_self_;
89 
90   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(IsoStreamManager);
91 };
92 
93 }  // namespace bt::iso
94