• 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 #include <endian.h>
16 
17 #include <array>
18 #include <cstdint>
19 
20 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
21 #include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h"
22 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
23 #include "pw_unit_test/framework.h"
24 
25 using bt::ContainersEqual;
26 using bt::StaticByteBuffer;
27 
28 namespace bt::hci::test {
29 namespace {
30 
31 constexpr hci_spec::OpCode kTestOpCode = 0x07FF;
32 constexpr hci_spec::EventCode kTestEventCode = 0xFF;
33 
34 struct TestPayload {
35   uint8_t foo;
36 } __attribute__((packed));
37 
TEST(PacketTest,CommandPacket)38 TEST(PacketTest, CommandPacket) {
39   constexpr size_t kPayloadSize = sizeof(TestPayload);
40   auto packet = CommandPacket::New(kTestOpCode, kPayloadSize);
41 
42   EXPECT_EQ(kTestOpCode, packet->opcode());
43   EXPECT_EQ(kPayloadSize, packet->view().payload_size());
44 
45   uint8_t foo = 0x7F;
46   packet->mutable_payload<TestPayload>()->foo = foo;
47 
48   // clang-format off
49 
50   StaticByteBuffer kExpected(
51       0xFF, 0x07,  // opcode
52       0x01,        // parameter_total_size
53       foo
54   );
55 
56   // clang-format on
57 
58   EXPECT_TRUE(ContainersEqual(kExpected, packet->view().data()));
59 }
60 
TEST(PacketTest,EventPacket)61 TEST(PacketTest, EventPacket) {
62   constexpr size_t kPayloadSize = sizeof(TestPayload);
63   auto packet = EventPacket::New(kPayloadSize);
64   uint8_t foo = 0x7F;
65 
66   // clang-format off
67  StaticByteBuffer bytes(
68       0xFF,  // event code
69       0x01,  // parameter_total_size
70       foo   // foo
71   );
72   packet->mutable_view()->mutable_data().Write(bytes);
73   packet->InitializeFromBuffer();
74   // clang-format on
75 
76   EXPECT_EQ(kTestEventCode, packet->event_code());
77   EXPECT_EQ(kPayloadSize, packet->view().payload_size());
78   EXPECT_EQ(foo, packet->params<TestPayload>().foo);
79 }
80 
TEST(PacketTest,EventPacketReturnParams)81 TEST(PacketTest, EventPacketReturnParams) {
82   uint8_t return_parameter = 0x7F;
83 
84   // clang-format off
85  StaticByteBuffer correct_size_bad_event_code(
86       // Event header
87       0xFF, 0x04,  // (event_code is not CommandComplete)
88 
89       // hci_spec::CommandCompleteEventParams
90       0x01, 0xFF, 0x07,
91 
92       return_parameter);
93   auto cmd_complete_small_payload = StaticByteBuffer(
94       // Event header
95       0x0E, 0x03,
96 
97       // hci_spec::CommandCompleteEventParams
98       0x01, 0xFF, 0x07);
99   auto valid = StaticByteBuffer(
100       // Event header
101       0x0E, 0x04,
102 
103       // hci_spec::CommandCompleteEventParams
104       0x01, 0xFF, 0x07,
105 
106       return_parameter);
107   // clang-format on
108 
109   // Allocate a large enough packet which we'll reuse for the 3 payloads.
110   auto packet = EventPacket::New(valid.size());
111 
112   // If the event code or the payload size don't match, then return_params()
113   // should return nullptr.
114   packet->mutable_view()->mutable_data().Write(correct_size_bad_event_code);
115   packet->InitializeFromBuffer();
116   EXPECT_EQ(nullptr, packet->return_params<TestPayload>());
117 
118   packet->mutable_view()->mutable_data().Write(cmd_complete_small_payload);
119   packet->InitializeFromBuffer();
120   EXPECT_EQ(nullptr, packet->return_params<TestPayload>());
121 
122   // Reset packet size to the original so that |valid| can fit.
123   packet->mutable_view()->Resize(valid.size());
124 
125   // Valid case
126   packet->mutable_view()->mutable_data().Write(valid);
127   packet->InitializeFromBuffer();
128   ASSERT_NE(nullptr, packet->return_params<TestPayload>());
129   EXPECT_EQ(return_parameter, packet->return_params<TestPayload>()->foo);
130 }
131 
TEST(PacketTest,EventPacketStatus)132 TEST(PacketTest, EventPacketStatus) {
133   // clang-format off
134   auto evt = StaticByteBuffer(
135       // Event header
136       0x05, 0x04,  // (event_code is DisconnectionComplete)
137 
138       // Disconnection Complete event parameters
139       0x03,        // status: hardware failure
140       0x01, 0x00,  // handle: 0x0001
141       0x16         // reason: terminated by local host
142   );
143   // clang-format on
144 
145   auto packet = EventPacket::New(evt.size());
146   packet->mutable_view()->mutable_data().Write(evt);
147   packet->InitializeFromBuffer();
148 
149   Result<> status = packet->ToResult();
150   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE),
151             status);
152 }
153 
TEST(PacketTest,CommandCompleteEventStatus)154 TEST(PacketTest, CommandCompleteEventStatus) {
155   // clang-format off
156   auto evt = StaticByteBuffer(
157       // Event header
158       0x0E, 0x04,  // (event code is CommandComplete)
159 
160       // hci_spec::CommandCompleteEventParams
161       0x01, 0xFF, 0x07,
162 
163       // Return parameters (status: hardware failure)
164       0x03);
165   // clang-format on
166 
167   auto packet = EventPacket::New(evt.size());
168   packet->mutable_view()->mutable_data().Write(evt);
169   packet->InitializeFromBuffer();
170 
171   Result<> status = packet->ToResult();
172   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE),
173             status);
174 }
175 
TEST(PacketTest,EventPacketMalformed)176 TEST(PacketTest, EventPacketMalformed) {
177   // clang-format off
178   auto evt = StaticByteBuffer(
179       // Event header
180       0x05, 0x03,  // (event_code is DisconnectionComplete)
181 
182       // Disconnection Complete event parameters
183       0x03,        // status: hardware failure
184       0x01, 0x00   // handle: 0x0001
185       // event is one byte too short
186   );
187   // clang-format on
188 
189   auto packet = EventPacket::New(evt.size());
190   packet->mutable_view()->mutable_data().Write(evt);
191   packet->InitializeFromBuffer();
192 
193   Result<> status = packet->ToResult();
194   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
195 }
196 
TEST(PacketTest,LEEventParams)197 TEST(PacketTest, LEEventParams) {
198   uint8_t subevent_payload = 0x7F;
199 
200   // clang-format off
201   auto correct_size_bad_event_code = StaticByteBuffer(
202       // Event header
203       0xFE, 0x02,  // (event_code is not hci_spec::kLEMetaEventCode)
204 
205       // Subevent code
206       0xFF,
207 
208       subevent_payload);
209   auto payload_too_small = StaticByteBuffer(
210       0x3E, 0x01,
211 
212       // Subevent code
213       0xFF);
214   auto valid = StaticByteBuffer(
215       // Event header
216       0x3E, 0x02,
217 
218       // Subevent code
219       0xFF,
220 
221       subevent_payload);
222   // clang-format on
223 
224   auto packet = EventPacket::New(valid.size());
225 
226   // If the event code or the payload size don't match, then return_params()
227   // should return nullptr.
228   packet->mutable_view()->mutable_data().Write(correct_size_bad_event_code);
229   packet->InitializeFromBuffer();
230   EXPECT_EQ(nullptr, packet->subevent_params<TestPayload>());
231 
232   packet->mutable_view()->mutable_data().Write(payload_too_small);
233   packet->InitializeFromBuffer();
234   EXPECT_EQ(nullptr, packet->subevent_params<TestPayload>());
235 
236   // Valid case
237   packet->mutable_view()->Resize(valid.size());
238   packet->mutable_view()->mutable_data().Write(valid);
239   packet->InitializeFromBuffer();
240 
241   EXPECT_NE(nullptr, packet->subevent_params<TestPayload>());
242   EXPECT_EQ(subevent_payload, packet->subevent_params<TestPayload>()->foo);
243 }
244 
TEST(PacketTest,ACLDataPacketFromFields)245 TEST(PacketTest, ACLDataPacketFromFields) {
246   constexpr size_t kLargeDataLength = 10;
247   constexpr size_t kSmallDataLength = 1;
248 
249   auto packet =
250       ACLDataPacket::New(0x007F,
251                          hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
252                          hci_spec::ACLBroadcastFlag::kActivePeripheralBroadcast,
253                          kSmallDataLength);
254   packet->mutable_view()->mutable_payload_data().Fill(0);
255 
256   // First 12-bits: 0x07F
257   // Upper 4-bits: 0b0101
258   EXPECT_TRUE(
259       ContainersEqual(packet->view().data(),
260                       std::array<uint8_t, 5>{{0x7F, 0x50, 0x01, 0x00, 0x00}}));
261 
262   packet =
263       ACLDataPacket::New(0x0FFF,
264                          hci_spec::ACLPacketBoundaryFlag::kCompletePDU,
265                          hci_spec::ACLBroadcastFlag::kActivePeripheralBroadcast,
266                          kSmallDataLength);
267   packet->mutable_view()->mutable_payload_data().Fill(0);
268 
269   // First 12-bits: 0xFFF
270   // Upper 4-bits: 0b0111
271   EXPECT_TRUE(
272       ContainersEqual(packet->view().data(),
273                       std::array<uint8_t, 5>{{0xFF, 0x7F, 0x01, 0x00, 0x00}}));
274 
275   packet =
276       ACLDataPacket::New(0x0FFF,
277                          hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
278                          hci_spec::ACLBroadcastFlag::kPointToPoint,
279                          kLargeDataLength);
280   packet->mutable_view()->mutable_payload_data().Fill(0);
281 
282   // First 12-bits: 0xFFF
283   // Upper 4-bits: 0b0000
284   EXPECT_TRUE(ContainersEqual(packet->view().data(),
285                               std::array<uint8_t, 14>{{0xFF,
286                                                        0x0F,
287                                                        0x0A,
288                                                        0x00,
289                                                        0x00,
290                                                        0x00,
291                                                        0x00,
292                                                        0x00,
293                                                        0x00,
294                                                        0x00,
295                                                        0x00,
296                                                        0x00,
297                                                        0x00}}));
298 }
299 
TEST(PacketTest,ACLDataPacketFromBuffer)300 TEST(PacketTest, ACLDataPacketFromBuffer) {
301   constexpr size_t kLargeDataLength = 256;
302   constexpr size_t kSmallDataLength = 1;
303 
304   // The same test cases as ACLDataPacketFromFields test above but in the
305   // opposite direction.
306 
307   // First 12-bits: 0x07F
308   // Upper 4-bits: 0b0101
309   auto bytes = StaticByteBuffer(0x7F, 0x50, 0x01, 0x00, 0x00);
310   auto packet = ACLDataPacket::New(kSmallDataLength);
311   packet->mutable_view()->mutable_data().Write(bytes);
312   packet->InitializeFromBuffer();
313 
314   EXPECT_EQ(0x007F, packet->connection_handle());
315   EXPECT_EQ(hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
316             packet->packet_boundary_flag());
317   EXPECT_EQ(hci_spec::ACLBroadcastFlag::kActivePeripheralBroadcast,
318             packet->broadcast_flag());
319   EXPECT_EQ(kSmallDataLength, packet->view().payload_size());
320 
321   // First 12-bits: 0xFFF
322   // Upper 4-bits: 0b0111
323   bytes = StaticByteBuffer(0xFF, 0x7F, 0x01, 0x00, 0x00);
324   packet->mutable_view()->mutable_data().Write(bytes);
325   packet->InitializeFromBuffer();
326 
327   EXPECT_EQ(0x0FFF, packet->connection_handle());
328   EXPECT_EQ(hci_spec::ACLPacketBoundaryFlag::kCompletePDU,
329             packet->packet_boundary_flag());
330   EXPECT_EQ(hci_spec::ACLBroadcastFlag::kActivePeripheralBroadcast,
331             packet->broadcast_flag());
332   EXPECT_EQ(kSmallDataLength, packet->view().payload_size());
333 
334   packet = ACLDataPacket::New(kLargeDataLength);
335   packet->mutable_view()->mutable_data().Write(
336       StaticByteBuffer(0xFF, 0x0F, 0x00, 0x01));
337   packet->InitializeFromBuffer();
338 
339   EXPECT_EQ(0x0FFF, packet->connection_handle());
340   EXPECT_EQ(hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
341             packet->packet_boundary_flag());
342   EXPECT_EQ(hci_spec::ACLBroadcastFlag::kPointToPoint,
343             packet->broadcast_flag());
344   EXPECT_EQ(kLargeDataLength, packet->view().payload_size());
345 }
346 
347 }  // namespace
348 }  // namespace bt::hci::test
349