• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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