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 <memory> 17 18 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 19 #include "pw_bluetooth_sapphire/internal/host/common/macros.h" 20 #include "pw_bluetooth_sapphire/internal/host/common/packet_view.h" 21 22 namespace bt::hci { 23 24 // A Packet is a move-only object that can be used to hold sent and received HCI 25 // packets. The Packet template is parameterized over the protocol packet header 26 // type. 27 // 28 // Instances of Packet cannot be created directly as the template does not 29 // specify the backing buffer, which should be provided by a subclass. 30 // 31 // Header-type-specific functionality can be provided in specializations of the 32 // Packet template. 33 // 34 // USAGE: 35 // 36 // Each Packet consists of a PacketView into a buffer that actually stores the 37 // data. A buffer should be provided in a subclass implementation. While the 38 // buffer must be sufficiently large to store the packet, the packet contents 39 // can be much smaller. 40 // 41 // template <typename HeaderType, size_t BufferSize> 42 // class FixedBufferPacket : public Packet<HeaderType> { 43 // public: 44 // void Init(size_t payload_size) { 45 // this->init_view(MutablePacketView<HeaderType>(&buffer_, 46 // payload_size)); 47 // } 48 // 49 // private: 50 // StaticByteBuffer<BufferSize> buffer_; 51 // }; 52 // 53 // std::unique_ptr<Packet<MyHeaderType>> packet = 54 // std::make_unique<FixedBufferPacket<MyHeaderType, 255>>(payload_size); 55 // 56 // Use Packet::view() to obtain a read-only view into the packet contents: 57 // 58 // auto foo = packet->view().header().some_header_field; 59 // 60 // Use Packet::mutable_view() to obtain a mutable view into the packet, which 61 // allows the packet contents and the size of the packet to be modified: 62 // 63 // packet->mutable_view()->mutable_header()->some_header_field = foo; 64 // packet->mutable_view()->set_payload_size(my_new_size); 65 // 66 // // Copy data directly into the buffer. 67 // auto mutable_bytes = packet->mutable_view()->mutable_bytes(); 68 // std::memcpy(mutable_bytes.mutable_data(), data, mutable_bytes.size()); 69 // 70 // SPECIALIZATIONS: 71 // 72 // Additional functionality that is specific to a protocol header type can be 73 // provided in a specialization of the Packet template. 74 // 75 // using MagicPacket = Packet<MagicHeader>; 76 // 77 // template <> 78 // class Packet<MagicHeader> : public PacketBase<MagicHeader, MagicPacket> { 79 // public: 80 // // Initializes packet with pancakes. 81 // void InitPancakes(); 82 // }; 83 // 84 // // Create an instance of FixedBufferPacket declared above. 85 // std::unique_ptr<MagicPacket> packet = 86 // std::make_unique<FixedBufferPacket<MagicHeader, 255>>(); 87 // packet->InitPancakes(); 88 // 89 // This pattern is used by EventPacket, ACLDataPacket, and ScoDataPacket 90 // 91 // THREAD-SAFETY: 92 // 93 // Packet is NOT thread-safe without external locking. 94 95 // PacketBase provides basic view functionality. Intended to be inherited by the 96 // Packet template and all of its specializations. 97 template <typename HeaderType, typename T> 98 class PacketBase { 99 public: 100 virtual ~PacketBase() = default; 101 view()102 const PacketView<HeaderType>& view() const { return view_; } mutable_view()103 MutablePacketView<HeaderType>* mutable_view() { return &view_; } 104 105 protected: PacketBase(const MutablePacketView<HeaderType> & view)106 explicit PacketBase(const MutablePacketView<HeaderType>& view) 107 : view_(view) {} 108 109 private: 110 MutablePacketView<HeaderType> view_; 111 112 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(PacketBase); 113 }; 114 115 // The basic Packet template. See control_packets.h and acl_data_packet.h 116 // for specializations that add functionality beyond that of PacketBase. 117 template <typename HeaderType> 118 class Packet : public PacketBase<HeaderType, Packet<HeaderType>> { 119 protected: 120 using PacketBase<HeaderType, Packet<HeaderType>>::PacketBase; 121 }; 122 123 } // namespace bt::hci 124