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