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