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