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