xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/transport/control_packets.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/transport/control_packets.h"
16 
17 #include <pw_bluetooth/hci_android.emb.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/hci-spec/vendor_protocol.h"
20 
21 namespace bt::hci {
22 
23 namespace android_hci = hci_spec::vendor::android;
24 namespace android_emb = pw::bluetooth::vendor::android_hci;
25 
CommandPacket(hci_spec::OpCode opcode,size_t packet_size)26 CommandPacket::CommandPacket(hci_spec::OpCode opcode, size_t packet_size)
27     : DynamicPacket(packet_size) {
28   PW_CHECK(packet_size >=
29                pw::bluetooth::emboss::CommandHeader::IntrinsicSizeInBytes(),
30            "command packet size must be at least 3 bytes to accomodate header");
31   auto header = view<pw::bluetooth::emboss::CommandHeaderWriter>();
32   header.opcode_bits().BackingStorage().WriteUInt(opcode);
33   header.parameter_total_size().Write(
34       packet_size -
35       pw::bluetooth::emboss::CommandHeader::IntrinsicSizeInBytes());
36 }
37 
opcode() const38 hci_spec::OpCode CommandPacket::opcode() const {
39   return header_view().opcode_bits().BackingStorage().ReadUInt();
40 }
41 
ogf() const42 uint8_t CommandPacket::ogf() const {
43   return header_view().opcode_bits().ogf().Read();
44 }
45 
ocf() const46 uint16_t CommandPacket::ocf() const {
47   return header_view().opcode_bits().ocf().Read();
48 }
49 
header_view() const50 pw::bluetooth::emboss::CommandHeaderView CommandPacket::header_view() const {
51   return view<pw::bluetooth::emboss::CommandHeaderView>();
52 }
53 
EventPacket(size_t packet_size)54 EventPacket::EventPacket(size_t packet_size) : DynamicPacket(packet_size) {
55   PW_CHECK(
56       packet_size >= pw::bluetooth::emboss::EventHeader::IntrinsicSizeInBytes(),
57       "event packet size must be at least 2 bytes to accomodate header");
58 }
59 
event_code() const60 hci_spec::EventCode EventPacket::event_code() const {
61   return view<pw::bluetooth::emboss::EventHeaderView>()
62       .event_code_uint()
63       .Read();
64 }
65 
StatusCode() const66 std::optional<pw::bluetooth::emboss::StatusCode> EventPacket::StatusCode()
67     const {
68   switch (event_code()) {
69     case hci_spec::kAuthenticationCompleteEventCode:
70       return StatusCodeFromView<
71           pw::bluetooth::emboss::AuthenticationCompleteEventView>();
72     case hci_spec::kChangeConnectionLinkKeyCompleteEventCode:
73       return StatusCodeFromView<
74           pw::bluetooth::emboss::ChangeConnectionLinkKeyCompleteEventView>();
75     case hci_spec::kCommandCompleteEventCode:
76       return StatusCodeFromView<
77           pw::bluetooth::emboss::SimpleCommandCompleteEventView>();
78     case hci_spec::kCommandStatusEventCode:
79       return StatusCodeFromView<
80           pw::bluetooth::emboss::CommandStatusEventView>();
81     case hci_spec::kConnectionCompleteEventCode:
82       return StatusCodeFromView<
83           pw::bluetooth::emboss::ConnectionCompleteEventView>();
84     case hci_spec::kDisconnectionCompleteEventCode:
85       return StatusCodeFromView<
86           pw::bluetooth::emboss::DisconnectionCompleteEventView>();
87     case hci_spec::kEncryptionChangeEventCode:
88       return StatusCodeFromView<
89           pw::bluetooth::emboss::EncryptionChangeEventV1View>();
90     case hci_spec::kEncryptionKeyRefreshCompleteEventCode:
91       return StatusCodeFromView<
92           pw::bluetooth::emboss::EncryptionKeyRefreshCompleteEventView>();
93     case hci_spec::kInquiryCompleteEventCode:
94       return StatusCodeFromView<
95           pw::bluetooth::emboss::InquiryCompleteEventView>();
96     case hci_spec::kReadRemoteExtendedFeaturesCompleteEventCode:
97       return StatusCodeFromView<
98           pw::bluetooth::emboss::ReadRemoteExtendedFeaturesCompleteEventView>();
99     case hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode:
100       return StatusCodeFromView<
101           pw::bluetooth::emboss::
102               ReadRemoteSupportedFeaturesCompleteEventView>();
103     case hci_spec::kReadRemoteVersionInfoCompleteEventCode:
104       return StatusCodeFromView<
105           pw::bluetooth::emboss::ReadRemoteVersionInfoCompleteEventView>();
106     case hci_spec::kRemoteNameRequestCompleteEventCode: {
107       // Tests expect that a kPacketMalformed status is returned for incomplete
108       // events, even if they contain the status field.
109       pw::bluetooth::emboss::RemoteNameRequestCompleteEventView event_view(
110           data().data(), size());
111       if (!event_view.IsComplete()) {
112         return std::nullopt;
113       }
114       return event_view.status().UncheckedRead();
115     }
116     case hci_spec::kRoleChangeEventCode:
117       return StatusCodeFromView<pw::bluetooth::emboss::RoleChangeEventView>();
118     case hci_spec::kSimplePairingCompleteEventCode:
119       return StatusCodeFromView<
120           pw::bluetooth::emboss::SimplePairingCompleteEventView>();
121     case hci_spec::kSynchronousConnectionCompleteEventCode:
122       return StatusCodeFromView<
123           pw::bluetooth::emboss::SynchronousConnectionCompleteEventView>();
124     case hci_spec::kVendorDebugEventCode: {
125       hci_spec::EventCode subevent_code =
126           view<pw::bluetooth::emboss::VendorDebugEventView>()
127               .subevent_code()
128               .Read();
129 
130       switch (subevent_code) {
131         case android_hci::kLEMultiAdvtStateChangeSubeventCode: {
132           return StatusCodeFromView<
133               android_emb::LEMultiAdvtStateChangeSubeventView>();
134         }
135 
136         default: {
137           BT_PANIC("Emboss vendor subevent (%#.2x) not implemented",
138                    subevent_code);
139           break;
140         }
141       }
142 
143       break;
144     }
145 
146     case hci_spec::kLEMetaEventCode: {
147       hci_spec::EventCode subevent_code =
148           view<pw::bluetooth::emboss::LEMetaEventView>().subevent_code().Read();
149 
150       switch (subevent_code) {
151         case hci_spec::kLECISEstablishedSubeventCode: {
152           return StatusCodeFromView<
153               pw::bluetooth::emboss::LECISEstablishedSubeventView>();
154         }
155         case hci_spec::kLEConnectionCompleteSubeventCode: {
156           return StatusCodeFromView<
157               pw::bluetooth::emboss::LEConnectionCompleteSubeventView>();
158         }
159         case hci_spec::kLEConnectionUpdateCompleteSubeventCode: {
160           return StatusCodeFromView<
161               pw::bluetooth::emboss::LEConnectionUpdateCompleteSubeventView>();
162         }
163         case hci_spec::kLEEnhancedConnectionCompleteSubeventCode: {
164           return StatusCodeFromView<
165               pw::bluetooth::emboss::
166                   LEEnhancedConnectionCompleteSubeventV1View>();
167         }
168         case hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode: {
169           return StatusCodeFromView<
170               pw::bluetooth::emboss::
171                   LEReadRemoteFeaturesCompleteSubeventView>();
172         }
173         case hci_spec::kLERequestPeerSCACompleteSubeventCode: {
174           return StatusCodeFromView<
175               pw::bluetooth::emboss::LERequestPeerSCACompleteSubeventView>();
176         }
177         case hci_spec::kLEAdvertisingSetTerminatedSubeventCode: {
178           return StatusCodeFromView<
179               pw::bluetooth::emboss::LEAdvertisingSetTerminatedSubeventView>();
180         }
181         default: {
182           BT_PANIC("Emboss LE meta subevent (%#.2x) not implemented",
183                    subevent_code);
184           break;
185         }
186       }
187 
188       break;
189     }
190 
191     default: {
192       BT_PANIC("Emboss event (%#.2x) not implemented", event_code());
193       break;
194     }
195   }
196 
197   return std::nullopt;
198 }
199 
ToResult() const200 hci::Result<> EventPacket::ToResult() const {
201   std::optional<pw::bluetooth::emboss::StatusCode> maybe_status_code =
202       StatusCode();
203   if (!maybe_status_code.has_value()) {
204     return bt::ToResult(HostError::kPacketMalformed);
205   }
206   return bt::ToResult(*maybe_status_code);
207 }
208 
209 }  // namespace bt::hci
210