• 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 "pw_bluetooth_sapphire/internal/host/l2cap/bredr_signaling_channel.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
18 
19 namespace bt::l2cap::internal {
20 
BrEdrSignalingChannel(Channel::WeakPtr chan,pw::bluetooth::emboss::ConnectionRole role,pw::async::Dispatcher & dispatcher)21 BrEdrSignalingChannel::BrEdrSignalingChannel(
22     Channel::WeakPtr chan,
23     pw::bluetooth::emboss::ConnectionRole role,
24     pw::async::Dispatcher& dispatcher)
25     : SignalingChannel(std::move(chan), role, dispatcher) {
26   set_mtu(kDefaultMTU);
27 
28   // Add default handler for incoming Echo Request commands.
29   ServeRequest(kEchoRequest,
30                [](const ByteBuffer& req_payload, Responder* responder) {
31                  responder->Send(req_payload);
32                });
33 }
34 
TestLink(const ByteBuffer & data,DataCallback cb)35 bool BrEdrSignalingChannel::TestLink(const ByteBuffer& data, DataCallback cb) {
36   return SendRequest(
37       kEchoRequest,
38       data,
39       [cb = std::move(cb)](Status status, const ByteBuffer& rsp_payload) {
40         if (status == Status::kSuccess) {
41           cb(rsp_payload);
42         } else {
43           cb(BufferView());
44         }
45         return ResponseHandlerAction::kCompleteOutboundTransaction;
46       });
47 }
48 
DecodeRxUnit(ByteBufferPtr sdu,const SignalingPacketHandler & cb)49 void BrEdrSignalingChannel::DecodeRxUnit(ByteBufferPtr sdu,
50                                          const SignalingPacketHandler& cb) {
51   // "Multiple commands may be sent in a single C-frame over Fixed Channel CID
52   // 0x0001 (ACL-U) (v5.0, Vol 3, Part A, Section 4)"
53   BT_DEBUG_ASSERT(sdu);
54   if (sdu->size() < sizeof(CommandHeader)) {
55     bt_log(DEBUG, "l2cap-bredr", "sig: dropped malformed ACL signaling packet");
56     return;
57   }
58 
59   size_t sdu_offset = 0;
60   while (sdu_offset + sizeof(CommandHeader) <= sdu->size()) {
61     const auto header_data = sdu->view(sdu_offset, sizeof(CommandHeader));
62     SignalingPacket packet(&header_data);
63 
64     uint16_t expected_payload_length = le16toh(packet.header().length);
65     size_t remaining_sdu_length =
66         sdu->size() - sdu_offset - sizeof(CommandHeader);
67     if (remaining_sdu_length < expected_payload_length) {
68       bt_log(DEBUG,
69              "l2cap-bredr",
70              "sig: expected more bytes (%zu < %u); drop",
71              remaining_sdu_length,
72              expected_payload_length);
73       SendCommandReject(
74           packet.header().id, RejectReason::kNotUnderstood, BufferView());
75       return;
76     }
77 
78     const auto packet_data =
79         sdu->view(sdu_offset, sizeof(CommandHeader) + expected_payload_length);
80     cb(SignalingPacket(&packet_data, expected_payload_length));
81 
82     sdu_offset += packet_data.size();
83   }
84 
85   if (sdu_offset != sdu->size()) {
86     bt_log(DEBUG,
87            "l2cap-bredr",
88            "sig: incomplete packet header "
89            "(expected: %zu, left: %zu)",
90            sizeof(CommandHeader),
91            sdu->size() - sdu_offset);
92   }
93 }
94 
IsSupportedResponse(CommandCode code) const95 bool BrEdrSignalingChannel::IsSupportedResponse(CommandCode code) const {
96   switch (code) {
97     case kCommandRejectCode:
98     case kConnectionResponse:
99     case kConfigurationResponse:
100     case kDisconnectionResponse:
101     case kEchoResponse:
102     case kInformationResponse:
103       return true;
104   }
105 
106   // Other response-type commands are for AMP/LE and are not supported.
107   return false;
108 }
109 
110 }  // namespace bt::l2cap::internal
111