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