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 "pw_bluetooth_sapphire/internal/host/l2cap/le_signaling_channel.h"
16
17 #include <pw_assert/check.h>
18 #include <pw_bytes/endian.h>
19
20 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h"
22
23 namespace bt::l2cap::internal {
24
LESignalingChannel(Channel::WeakPtr chan,pw::bluetooth::emboss::ConnectionRole role,pw::async::Dispatcher & dispatcher)25 LESignalingChannel::LESignalingChannel(
26 Channel::WeakPtr chan,
27 pw::bluetooth::emboss::ConnectionRole role,
28 pw::async::Dispatcher& dispatcher)
29 : SignalingChannel(std::move(chan), role, dispatcher) {
30 set_mtu(kMinLEMTU);
31 }
32
DecodeRxUnit(ByteBufferPtr sdu,const SignalingPacketHandler & cb)33 void LESignalingChannel::DecodeRxUnit(ByteBufferPtr sdu,
34 const SignalingPacketHandler& cb) {
35 // "[O]nly one command per C-frame shall be sent over [the LE] Fixed Channel"
36 // (v5.0, Vol 3, Part A, Section 4).
37 PW_DCHECK(sdu);
38 if (sdu->size() < sizeof(CommandHeader)) {
39 bt_log(DEBUG, "l2cap-le", "sig: dropped malformed LE signaling packet");
40 return;
41 }
42
43 SignalingPacket packet(sdu.get());
44 uint16_t expected_payload_length = pw::bytes::ConvertOrderFrom(
45 cpp20::endian::little, packet.header().length);
46 if (expected_payload_length != sdu->size() - sizeof(CommandHeader)) {
47 bt_log(DEBUG,
48 "l2cap-le",
49 "sig: packet size mismatch (expected: %u, recv: %zu); drop",
50 expected_payload_length,
51 sdu->size() - sizeof(CommandHeader));
52 SendCommandReject(
53 packet.header().id, RejectReason::kNotUnderstood, BufferView());
54 return;
55 }
56
57 cb(SignalingPacket(sdu.get(), expected_payload_length));
58 }
59
IsSupportedResponse(CommandCode code) const60 bool LESignalingChannel::IsSupportedResponse(CommandCode code) const {
61 switch (code) {
62 case kCommandRejectCode:
63 case kConnectionParameterUpdateResponse:
64 case kDisconnectionResponse:
65 case kLECreditBasedConnectionResponse:
66 return true;
67 }
68
69 // Other response-type commands are for AMP/BREDR and are not supported.
70 return false;
71 }
72
73 } // namespace bt::l2cap::internal
74