• 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/transport/emboss_control_packets.h"
16 
17 #include <pw_bluetooth/hci_android.emb.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/packet_view.h"
20 #include "pw_bluetooth_sapphire/internal/host/hci-spec/vendor_protocol.h"
21 
22 namespace bt::hci {
23 
EmbossCommandPacket(hci_spec::OpCode opcode,size_t packet_size)24 EmbossCommandPacket::EmbossCommandPacket(hci_spec::OpCode opcode,
25                                          size_t packet_size)
26     : DynamicPacket(packet_size) {
27   BT_ASSERT_MSG(
28       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().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 EmbossCommandPacket::opcode() const {
39   return header_view().opcode().BackingStorage().ReadUInt();
40 }
41 
ogf() const42 uint8_t EmbossCommandPacket::ogf() const {
43   return header_view().opcode().ogf().Read();
44 }
45 
ocf() const46 uint16_t EmbossCommandPacket::ocf() const {
47   return header_view().opcode().ocf().Read();
48 }
49 
header_view() const50 pw::bluetooth::emboss::CommandHeaderView EmbossCommandPacket::header_view()
51     const {
52   return view<pw::bluetooth::emboss::CommandHeaderView>();
53 }
54 
EmbossEventPacket(size_t packet_size)55 EmbossEventPacket::EmbossEventPacket(size_t packet_size)
56     : DynamicPacket(packet_size) {
57   BT_ASSERT_MSG(
58       packet_size >= pw::bluetooth::emboss::EventHeader::IntrinsicSizeInBytes(),
59       "event packet size must be at least 2 bytes to accomodate header");
60 }
61 
event_code() const62 hci_spec::EventCode EmbossEventPacket::event_code() const {
63   return view<pw::bluetooth::emboss::EventHeaderView>().event_code().Read();
64 }
65 
StatusCode() const66 std::optional<pw::bluetooth::emboss::StatusCode> EmbossEventPacket::StatusCode()
67     const {
68   switch (event_code()) {
69     case hci_spec::kCommandCompleteEventCode:
70       return StatusCodeFromView<
71           pw::bluetooth::emboss::SimpleCommandCompleteEventView>();
72     case hci_spec ::kCommandStatusEventCode:
73       return StatusCodeFromView<
74           pw::bluetooth::emboss::CommandStatusEventView>();
75     case hci_spec::kConnectionCompleteEventCode:
76       return StatusCodeFromView<
77           pw::bluetooth::emboss::ConnectionCompleteEventView>();
78     case hci_spec::kDisconnectionCompleteEventCode:
79       return StatusCodeFromView<
80           pw::bluetooth::emboss::DisconnectionCompleteEventView>();
81     case hci_spec::kReadRemoteVersionInfoCompleteEventCode:
82       return StatusCodeFromView<
83           pw::bluetooth::emboss::ReadRemoteVersionInfoCompleteEventView>();
84     case hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode:
85       return StatusCodeFromView<
86           pw::bluetooth::emboss::
87               ReadRemoteSupportedFeaturesCompleteEventView>();
88     case hci_spec::kReadRemoteExtendedFeaturesCompleteEventCode:
89       return StatusCodeFromView<
90           pw::bluetooth::emboss::ReadRemoteExtendedFeaturesCompleteEventView>();
91     case hci_spec::kRemoteNameRequestCompleteEventCode: {
92       // Tests expect that a kPacketMalformed status is returned for incomplete
93       // events, even if they contain the status field.
94       pw::bluetooth::emboss::RemoteNameRequestCompleteEventView event_view(
95           data().data(), size());
96       if (!event_view.IsComplete()) {
97         return std::nullopt;
98       }
99       return event_view.status().UncheckedRead();
100     }
101     case hci_spec::kEncryptionChangeEventCode:
102       return StatusCodeFromView<
103           pw::bluetooth::emboss::EncryptionChangeEventV1View>();
104     case hci_spec::kEncryptionKeyRefreshCompleteEventCode:
105       return StatusCodeFromView<
106           pw::bluetooth::emboss::EncryptionKeyRefreshCompleteEventView>();
107     case hci_spec::kRoleChangeEventCode:
108       return StatusCodeFromView<pw::bluetooth::emboss::RoleChangeEventView>();
109     case hci_spec::kSynchronousConnectionCompleteEventCode:
110       return StatusCodeFromView<
111           pw::bluetooth::emboss::SynchronousConnectionCompleteEventView>();
112     case hci_spec::kVendorDebugEventCode: {
113       hci_spec::EventCode subevent_code =
114           view<pw::bluetooth::emboss::VendorDebugEventView>()
115               .subevent_code()
116               .Read();
117 
118       switch (subevent_code) {
119         case hci_spec::vendor::android::kLEMultiAdvtStateChangeSubeventCode: {
120           return StatusCodeFromView<pw::bluetooth::vendor::android_hci::
121                                         LEMultiAdvtStateChangeSubeventView>();
122         }
123 
124         default: {
125           BT_PANIC("Emboss vendor subevent (%#.2x) not implemented",
126                    subevent_code);
127           break;
128         }
129       }
130 
131       break;
132     }
133 
134     case hci_spec::kLEMetaEventCode: {
135       hci_spec::EventCode subevent_code =
136           view<pw::bluetooth::emboss::LEMetaEventView>().subevent_code().Read();
137 
138       switch (subevent_code) {
139         case hci_spec::kLEConnectionCompleteSubeventCode: {
140           return StatusCodeFromView<
141               pw::bluetooth::emboss::LEConnectionCompleteSubeventView>();
142         }
143 
144         case hci_spec::kLEConnectionUpdateCompleteSubeventCode: {
145           return StatusCodeFromView<
146               pw::bluetooth::emboss::LEConnectionUpdateCompleteSubeventView>();
147         }
148 
149         case hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode: {
150           return StatusCodeFromView<
151               pw::bluetooth::emboss::
152                   LEReadRemoteFeaturesCompleteSubeventView>();
153         }
154 
155         default: {
156           BT_PANIC("Emboss LE meta subevent (%#.2x) not implemented",
157                    subevent_code);
158           break;
159         }
160       }
161 
162       break;
163     }
164 
165     default: {
166       BT_PANIC("Emboss event (%#.2x) not implemented", event_code());
167       break;
168     }
169   }
170 
171   return std::nullopt;
172 }
173 
ToResult() const174 hci::Result<> EmbossEventPacket::ToResult() const {
175   std::optional<pw::bluetooth::emboss::StatusCode> maybe_status_code =
176       StatusCode();
177   if (!maybe_status_code.has_value()) {
178     return bt::ToResult(HostError::kPacketMalformed);
179   }
180   return bt::ToResult(*maybe_status_code);
181 }
182 
183 }  // namespace bt::hci
184