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_containers/intrusive_forward_list.h"
18 #include "pw_function/function.h"
19 #include "pw_span/span.h"
20 
21 namespace pw::bluetooth::proxy {
22 
23 class L2capChannelManager;
24 
25 // Base class for peer-to-peer L2CAP-based channels supporting reading.
26 //
27 // Read channels invoke a client-supplied read callback for packets sent by
28 // the peer to the channel.
29 class L2capReadChannel : public IntrusiveForwardList<L2capReadChannel>::Item {
30  public:
31   L2capReadChannel(const L2capReadChannel& other) = delete;
32   L2capReadChannel& operator=(const L2capReadChannel& other) = delete;
33   L2capReadChannel(L2capReadChannel&& other);
34   // Move assignment operator allows channels to be erased from pw::Vector.
35   L2capReadChannel& operator=(L2capReadChannel&& other);
36 
37   virtual ~L2capReadChannel();
38 
39   // Handle an Rx L2CAP PDU.
40   //
41   // Implementations should call `SendPayloadFromControllerToClient` after
42   // recombining/processing the PDU (e.g. after updating channel state and
43   // screening out certain PDUs).
44   //
45   // Return true if the PDU was consumed by the channel. Otherwise, return false
46   // and the PDU will be forwarded by `ProxyHost` on to the Bluetooth host.
47   [[nodiscard]] virtual bool HandlePduFromController(
48       pw::span<uint8_t> l2cap_pdu) = 0;
49 
50   // Handle a Tx L2CAP PDU.
51   //
52   // Implementations should call `SendPayloadFromHostToClient` after
53   // recombining/processing the PDU (e.g. after updating channel state and
54   // screening out certain PDUs).
55   //
56   // Return true if the PDU was consumed by the channel. Otherwise, return false
57   // and the PDU will be forwarded by `ProxyHost` on to the Bluetooth
58   // controller.
59   [[nodiscard]] virtual bool HandlePduFromHost(pw::span<uint8_t> l2cap_pdu) = 0;
60 
61   // Handle fragmented Rx L2CAP PDU.
62   // TODO: https://pwbug.dev/365179076 - Support recombination & delete this.
63   virtual void OnFragmentedPduReceived();
64 
65   // Get the source L2CAP channel ID.
local_cid()66   uint16_t local_cid() const { return local_cid_; }
67 
68   // Get the ACL connection handle.
connection_handle()69   uint16_t connection_handle() const { return connection_handle_; }
70 
71  protected:
72   explicit L2capReadChannel(L2capChannelManager& l2cap_channel_manager,
73                             pw::Function<void(pw::span<uint8_t> payload)>&&
74                                 payload_from_controller_fn,
75                             uint16_t connection_handle,
76                             uint16_t local_cid);
77 
78   // Returns whether or not ACL connection handle & local L2CAP channel
79   // identifier are valid parameters for a packet.
80   [[nodiscard]] static bool AreValidParameters(uint16_t connection_handle,
81                                                uint16_t local_cid);
82 
SendPayloadFromControllerToClient(pw::span<uint8_t> payload)83   void SendPayloadFromControllerToClient(pw::span<uint8_t> payload) {
84     if (payload_from_controller_fn_) {
85       payload_from_controller_fn_(payload);
86     }
87   }
88 
89  private:
90   static constexpr uint16_t kMaxValidConnectionHandle = 0x0EFF;
91 
92   // ACL connection handle of this channel.
93   uint16_t connection_handle_;
94   // L2CAP channel ID of this channel.
95   uint16_t local_cid_;
96   // Client-provided controller read callback.
97   pw::Function<void(pw::span<uint8_t> payload)> payload_from_controller_fn_;
98 
99   L2capChannelManager& l2cap_channel_manager_;
100 };
101 
102 }  // namespace pw::bluetooth::proxy
103