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 <lib/fit/function.h> 17 18 #include "pw_bluetooth_sapphire/internal/host/common/assert.h" 19 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 20 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 21 22 namespace bt::l2cap::internal { 23 24 // The interface between a Channel, and the module implementing the 25 // mode-specific transmit logic. The primary purposes of an TxEngine are a) to 26 // transform SDUs into PDUs, and b) to transmit/retransmit the PDUs at the 27 // appropriate time. See Bluetooth Core Spec v5.0, Volume 3, Part A, Sec 2.4, 28 // "Modes of Operation" for more information about the possible modes. 29 class TxEngine { 30 public: 31 // Type defining the callback that a TxEngine uses to deliver a PDU to lower 32 // layers. The callee may assume that the ByteBufferPtr owns an instance of a 33 // DynamicByteBuffer or SlabBuffer. 34 using SendFrameCallback = fit::function<void(ByteBufferPtr pdu)>; 35 36 // Creates a transmit engine, which will invoke |send_frame_callback| 37 // when a PDU is ready for transmission. This callback may be invoked 38 // synchronously from QueueSdu(), as well as asynchronously (e.g. when a 39 // retransmission timer expires). 40 // 41 // NOTE: The user of this class must ensure that a synchronous invocation of 42 // |send_frame_callback| does not deadlock. E.g., the callback must not 43 // attempt to lock the same mutex as the caller of QueueSdu(). TxEngine(ChannelId channel_id,uint16_t max_tx_sdu_size,SendFrameCallback send_frame_callback)44 TxEngine(ChannelId channel_id, 45 uint16_t max_tx_sdu_size, 46 SendFrameCallback send_frame_callback) 47 : channel_id_(channel_id), 48 max_tx_sdu_size_(max_tx_sdu_size), 49 send_frame_callback_(std::move(send_frame_callback)) { 50 BT_ASSERT(max_tx_sdu_size_); 51 } 52 virtual ~TxEngine() = default; 53 54 // Queues an SDU for transmission, returning true on success. 55 // 56 // * As noted in the ctor documentation, this _may_ result in a synchronous 57 // invocation of |send_frame_callback_|. 58 // * It is presumed that the ByteBufferPtr owns an instance of a 59 // DynamicByteBuffer or SlabBuffer. 60 virtual bool QueueSdu(ByteBufferPtr) = 0; 61 62 protected: 63 const ChannelId channel_id_; 64 const uint16_t max_tx_sdu_size_; 65 // Invoked when a PDU is ready for transmission. 66 const SendFrameCallback send_frame_callback_; 67 68 private: 69 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(TxEngine); 70 }; 71 72 } // namespace bt::l2cap::internal 73