1 /*
2 * Copyright 2015 The Android Open Source Project
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://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,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "controller_properties.h"
17
18 #include <inttypes.h>
19 #include <json/json.h>
20
21 #include <fstream>
22 #include <limits>
23 #include <memory>
24
25 #include "log.h"
26
27 namespace rootcanal {
28 using namespace bluetooth::hci;
29
Page0LmpFeatures()30 static constexpr uint64_t Page0LmpFeatures() {
31 LMPFeaturesPage0Bits features[] = {
32 LMPFeaturesPage0Bits::LMP_3_SLOT_PACKETS,
33 LMPFeaturesPage0Bits::LMP_5_SLOT_PACKETS,
34 LMPFeaturesPage0Bits::ENCRYPTION,
35 LMPFeaturesPage0Bits::SLOT_OFFSET,
36 LMPFeaturesPage0Bits::TIMING_ACCURACY,
37 LMPFeaturesPage0Bits::ROLE_SWITCH,
38 LMPFeaturesPage0Bits::HOLD_MODE,
39 LMPFeaturesPage0Bits::SNIFF_MODE,
40 LMPFeaturesPage0Bits::POWER_CONTROL_REQUESTS,
41 LMPFeaturesPage0Bits::CHANNEL_QUALITY_DRIVEN_DATA_RATE,
42 LMPFeaturesPage0Bits::SCO_LINK,
43 LMPFeaturesPage0Bits::HV2_PACKETS,
44 LMPFeaturesPage0Bits::HV3_PACKETS,
45 LMPFeaturesPage0Bits::M_LAW_LOG_SYNCHRONOUS_DATA,
46 LMPFeaturesPage0Bits::A_LAW_LOG_SYNCHRONOUS_DATA,
47 LMPFeaturesPage0Bits::CVSD_SYNCHRONOUS_DATA,
48 LMPFeaturesPage0Bits::PAGING_PARAMETER_NEGOTIATION,
49 LMPFeaturesPage0Bits::POWER_CONTROL,
50 LMPFeaturesPage0Bits::TRANSPARENT_SYNCHRONOUS_DATA,
51 LMPFeaturesPage0Bits::BROADCAST_ENCRYPTION,
52 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE,
53 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_3_MB_S_MODE,
54 LMPFeaturesPage0Bits::ENHANCED_INQUIRY_SCAN,
55 LMPFeaturesPage0Bits::INTERLACED_INQUIRY_SCAN,
56 LMPFeaturesPage0Bits::INTERLACED_PAGE_SCAN,
57 LMPFeaturesPage0Bits::RSSI_WITH_INQUIRY_RESULTS,
58 LMPFeaturesPage0Bits::EXTENDED_SCO_LINK,
59 LMPFeaturesPage0Bits::EV4_PACKETS,
60 LMPFeaturesPage0Bits::EV5_PACKETS,
61 LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL,
62 LMPFeaturesPage0Bits::AFH_CLASSIFICATION_PERIPHERAL,
63 LMPFeaturesPage0Bits::LE_SUPPORTED_CONTROLLER,
64 LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS,
65 LMPFeaturesPage0Bits::LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS,
66 LMPFeaturesPage0Bits::SNIFF_SUBRATING,
67 LMPFeaturesPage0Bits::PAUSE_ENCRYPTION,
68 LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL,
69 LMPFeaturesPage0Bits::AFH_CLASSIFICATION_CENTRAL,
70 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE,
71 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_3_MB_S_MODE,
72 LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS,
73 LMPFeaturesPage0Bits::EXTENDED_INQUIRY_RESPONSE,
74 LMPFeaturesPage0Bits::SIMULTANEOUS_LE_AND_BR_CONTROLLER,
75 LMPFeaturesPage0Bits::SECURE_SIMPLE_PAIRING_CONTROLLER,
76 LMPFeaturesPage0Bits::ENCAPSULATED_PDU,
77 LMPFeaturesPage0Bits::HCI_LINK_SUPERVISION_TIMEOUT_CHANGED_EVENT,
78 LMPFeaturesPage0Bits::VARIABLE_INQUIRY_TX_POWER_LEVEL,
79 LMPFeaturesPage0Bits::ENHANCED_POWER_CONTROL,
80 LMPFeaturesPage0Bits::EXTENDED_FEATURES};
81
82 uint64_t value = 0;
83 for (auto feature : features) {
84 value |= static_cast<uint64_t>(feature);
85 }
86 return value;
87 }
88
Page2LmpFeatures()89 static constexpr uint64_t Page2LmpFeatures() {
90 LMPFeaturesPage2Bits features[] = {
91 LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT,
92 LMPFeaturesPage2Bits::PING,
93 };
94
95 uint64_t value = 0;
96 for (auto feature : features) {
97 value |= static_cast<uint64_t>(feature);
98 }
99 return value;
100 }
101
LlFeatures()102 static constexpr uint64_t LlFeatures() {
103 LLFeaturesBits features[] = {
104 LLFeaturesBits::LE_ENCRYPTION,
105 LLFeaturesBits::CONNECTION_PARAMETERS_REQUEST_PROCEDURE,
106 LLFeaturesBits::EXTENDED_REJECT_INDICATION,
107 LLFeaturesBits::PERIPHERAL_INITIATED_FEATURES_EXCHANGE,
108 LLFeaturesBits::LE_PING,
109
110 LLFeaturesBits::EXTENDED_SCANNER_FILTER_POLICIES,
111 LLFeaturesBits::LE_EXTENDED_ADVERTISING,
112
113 // TODO: breaks AVD boot tests with LE audio
114 // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_CENTRAL,
115 // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL,
116 };
117
118 uint64_t value = 0;
119 for (auto feature : features) {
120 value |= static_cast<uint64_t>(feature);
121 }
122 return value;
123 }
124
125 template <typename T>
ParseUint(Json::Value root,std::string field_name,T & output_value)126 static bool ParseUint(Json::Value root, std::string field_name,
127 T& output_value) {
128 T max_value = std::numeric_limits<T>::max();
129 Json::Value value = root[field_name];
130
131 if (value.isString()) {
132 unsigned long long parsed_value = std::stoull(value.asString(), nullptr, 0);
133 if (parsed_value > max_value) {
134 LOG_INFO("invalid value for %s is discarded: %llu > %llu",
135 field_name.c_str(), parsed_value,
136 static_cast<unsigned long long>(max_value));
137 return false;
138 } else {
139 output_value = static_cast<T>(parsed_value);
140 return true;
141 }
142 }
143
144 return false;
145 }
146
147 template <typename T, std::size_t N>
ParseUintArray(Json::Value root,std::string field_name,std::array<T,N> & output_value)148 static bool ParseUintArray(Json::Value root, std::string field_name,
149 std::array<T, N>& output_value) {
150 T max_value = std::numeric_limits<T>::max();
151 Json::Value value = root[field_name];
152
153 if (value.empty()) {
154 return false;
155 }
156
157 if (!value.isArray()) {
158 LOG_INFO("invalid value for %s is discarded: not an array",
159 field_name.c_str());
160 return false;
161 }
162
163 if (value.size() != N) {
164 LOG_INFO(
165 "invalid value for %s is discarded: incorrect size %u, expected %zu",
166 field_name.c_str(), value.size(), N);
167 return false;
168 }
169
170 for (size_t n = 0; n < N; n++) {
171 unsigned long long parsed_value =
172 std::stoull(value[static_cast<int>(n)].asString(), nullptr, 0);
173 if (parsed_value > max_value) {
174 LOG_INFO("invalid value for %s[%zu] is discarded: %llu > %llu",
175 field_name.c_str(), n, parsed_value,
176 static_cast<unsigned long long>(max_value));
177 } else {
178 output_value[n] = parsed_value;
179 }
180 }
181
182 return false;
183 }
184
185 template <typename T>
ParseUintVector(Json::Value root,std::string field_name,std::vector<T> & output_value)186 static bool ParseUintVector(Json::Value root, std::string field_name,
187 std::vector<T>& output_value) {
188 T max_value = std::numeric_limits<T>::max();
189 Json::Value value = root[field_name];
190
191 if (value.empty()) {
192 return false;
193 }
194
195 if (!value.isArray()) {
196 LOG_INFO("invalid value for %s is discarded: not an array",
197 field_name.c_str());
198 return false;
199 }
200
201 output_value.clear();
202 for (size_t n = 0; n < value.size(); n++) {
203 unsigned long long parsed_value =
204 std::stoull(value[static_cast<int>(n)].asString(), nullptr, 0);
205 if (parsed_value > max_value) {
206 LOG_INFO("invalid value for %s[%zu] is discarded: %llu > %llu",
207 field_name.c_str(), n, parsed_value,
208 static_cast<unsigned long long>(max_value));
209 } else {
210 output_value.push_back(parsed_value);
211 }
212 }
213
214 return false;
215 }
216
ParseHex64(Json::Value value,uint64_t * field)217 static void ParseHex64(Json::Value value, uint64_t* field) {
218 if (value.isString()) {
219 size_t end_char = 0;
220 uint64_t parsed = std::stoll(value.asString(), &end_char, 16);
221 if (end_char > 0) {
222 *field = parsed;
223 }
224 }
225 }
226
ControllerProperties(const std::string & file_name)227 ControllerProperties::ControllerProperties(const std::string& file_name)
228 : lmp_features({Page0LmpFeatures(), 0, Page2LmpFeatures()}),
229 le_features(LlFeatures()) {
230 // Set support for all HCI commands by default.
231 // The controller will update the mask with its implemented commands
232 // after the creation of the properties.
233 for (int i = 0; i < 47; i++) {
234 supported_commands[i] = 0xff;
235 }
236
237 // Mark reserved commands as unsupported.
238 for (int i = 47; i < 64; i++) {
239 supported_commands[i] = 0x00;
240 }
241
242 if (!CheckSupportedFeatures()) {
243 LOG_INFO(
244 "Warning: initial LMP and/or LE are not consistent. Please make sure"
245 " that the features are correct w.r.t. the rules described"
246 " in Vol 2, Part C 3.5 Feature requirements");
247 }
248
249 if (file_name.empty()) {
250 return;
251 }
252
253 LOG_INFO("Reading controller properties from %s.", file_name.c_str());
254
255 std::ifstream file(file_name);
256
257 Json::Value root;
258 Json::CharReaderBuilder builder;
259
260 std::string errs;
261 if (!Json::parseFromStream(builder, file, &root, &errs)) {
262 LOG_ERROR("Error reading controller properties from file: %s error: %s",
263 file_name.c_str(), errs.c_str());
264 return;
265 }
266
267 // Legacy configuration options.
268
269 ParseUint(root, "AclDataPacketSize", acl_data_packet_length);
270 ParseUint(root, "ScoDataPacketSize", sco_data_packet_length);
271 ParseUint(root, "NumAclDataPackets", total_num_acl_data_packets);
272 ParseUint(root, "NumScoDataPackets", total_num_sco_data_packets);
273
274 uint8_t hci_version = static_cast<uint8_t>(this->hci_version);
275 uint8_t lmp_version = static_cast<uint8_t>(this->lmp_version);
276 ParseUint(root, "Version", hci_version);
277 ParseUint(root, "Revision", hci_subversion);
278 ParseUint(root, "LmpPalVersion", lmp_version);
279 ParseUint(root, "LmpPalSubversion", lmp_subversion);
280 ParseUint(root, "ManufacturerName", company_identifier);
281
282 ParseHex64(root["LeSupportedFeatures"], &le_features);
283
284 // Configuration options.
285
286 ParseUint(root, "hci_version", hci_version);
287 ParseUint(root, "lmp_version", lmp_version);
288 ParseUint(root, "hci_subversion", hci_subversion);
289 ParseUint(root, "lmp_subversion", lmp_subversion);
290 ParseUint(root, "company_identifier", company_identifier);
291
292 ParseUintArray(root, "supported_commands", supported_commands);
293 ParseUintArray(root, "lmp_features", lmp_features);
294 ParseUint(root, "le_features", le_features);
295
296 ParseUint(root, "acl_data_packet_length", acl_data_packet_length);
297 ParseUint(root, "sco_data_packet_length ", sco_data_packet_length);
298 ParseUint(root, "total_num_acl_data_packets ", total_num_acl_data_packets);
299 ParseUint(root, "total_num_sco_data_packets ", total_num_sco_data_packets);
300 ParseUint(root, "le_acl_data_packet_length ", le_acl_data_packet_length);
301 ParseUint(root, "iso_data_packet_length ", iso_data_packet_length);
302 ParseUint(root, "total_num_le_acl_data_packets ",
303 total_num_le_acl_data_packets);
304 ParseUint(root, "total_num_iso_data_packets ", total_num_iso_data_packets);
305 ParseUint(root, "num_supported_iac", num_supported_iac);
306 ParseUint(root, "le_advertising_physical_channel_tx_power",
307 le_advertising_physical_channel_tx_power);
308
309 ParseUintArray(root, "lmp_features", lmp_features);
310 ParseUintVector(root, "supported_standard_codecs", supported_standard_codecs);
311 ParseUintVector(root, "supported_vendor_specific_codecs",
312 supported_vendor_specific_codecs);
313
314 ParseUint(root, "le_filter_accept_list_size", le_filter_accept_list_size);
315 ParseUint(root, "le_resolving_list_size", le_resolving_list_size);
316 ParseUint(root, "le_supported_states", le_supported_states);
317
318 ParseUint(root, "le_max_advertising_data_length",
319 le_max_advertising_data_length);
320 ParseUint(root, "le_num_supported_advertising_sets",
321 le_num_supported_advertising_sets);
322
323 ParseUintVector(root, "le_vendor_capabilities", le_vendor_capabilities);
324
325 this->hci_version = static_cast<HciVersion>(hci_version);
326 this->lmp_version = static_cast<LmpVersion>(lmp_version);
327
328 if (!CheckSupportedFeatures()) {
329 LOG_INFO(
330 "Warning: the LMP and/or LE are not consistent. Please make sure"
331 " that the features are correct w.r.t. the rules described"
332 " in Vol 2, Part C 3.5 Feature requirements");
333 } else {
334 LOG_INFO("LMP and LE features successfully validated");
335 }
336 }
337
SetSupportedCommands(std::array<uint8_t,64> supported_commands)338 void ControllerProperties::SetSupportedCommands(
339 std::array<uint8_t, 64> supported_commands) {
340 for (size_t i = 0; i < this->supported_commands.size(); i++) {
341 this->supported_commands[i] &= supported_commands[i];
342 }
343 }
344
CheckSupportedFeatures() const345 bool ControllerProperties::CheckSupportedFeatures() const {
346 // Vol 2, Part C § 3.3 Feature mask definition.
347 // Check for reserved or deprecated feature bits.
348 //
349 // Note: the specification for v1.0 and v1.1 is no longer available for
350 // download, the reserved feature bits are copied over from v1.2.
351 uint64_t lmp_page_0_reserved_bits = 0;
352 uint64_t lmp_page_2_reserved_bits = 0;
353 switch (lmp_version) {
354 case bluetooth::hci::LmpVersion::V_1_0B:
355 lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000);
356 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
357 break;
358 case bluetooth::hci::LmpVersion::V_1_1:
359 lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000);
360 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
361 break;
362 case bluetooth::hci::LmpVersion::V_1_2:
363 lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000);
364 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
365 break;
366 case bluetooth::hci::LmpVersion::V_2_0:
367 lmp_page_0_reserved_bits = UINT64_C(0x7fff066401000000);
368 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
369 break;
370 case bluetooth::hci::LmpVersion::V_2_1:
371 lmp_page_0_reserved_bits = UINT64_C(0x7c86006401000000);
372 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
373 break;
374 case bluetooth::hci::LmpVersion::V_3_0:
375 lmp_page_0_reserved_bits = UINT64_C(0x7886006401000000);
376 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
377 break;
378 case bluetooth::hci::LmpVersion::V_4_0:
379 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000);
380 lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff);
381 break;
382 case bluetooth::hci::LmpVersion::V_4_1:
383 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000);
384 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480);
385 break;
386 case bluetooth::hci::LmpVersion::V_4_2:
387 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000);
388 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480);
389 break;
390 case bluetooth::hci::LmpVersion::V_5_0:
391 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100);
392 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480);
393 break;
394 case bluetooth::hci::LmpVersion::V_5_1:
395 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100);
396 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080);
397 break;
398 case bluetooth::hci::LmpVersion::V_5_2:
399 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100);
400 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080);
401 break;
402 case bluetooth::hci::LmpVersion::V_5_3:
403 default:
404 lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100);
405 lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080);
406 break;
407 };
408
409 if ((lmp_page_0_reserved_bits & lmp_features[0]) != 0) {
410 LOG_INFO("The page 0 feature bits 0x%016" PRIx64
411 " are reserved in the specification %s",
412 lmp_page_0_reserved_bits & lmp_features[0],
413 LmpVersionText(lmp_version).c_str());
414 return false;
415 }
416
417 if ((lmp_page_2_reserved_bits & lmp_features[2]) != 0) {
418 LOG_INFO("The page 2 feature bits 0x%016" PRIx64
419 " are reserved in the specification %s",
420 lmp_page_2_reserved_bits & lmp_features[2],
421 LmpVersionText(lmp_version).c_str());
422 return false;
423 }
424
425 // Vol 2, Part C § 3.5 Feature requirements.
426 // RootCanal always support BR/EDR mode, this function implements
427 // the feature requirements from the subsection 1. Devices supporting BR/EDR.
428 //
429 // Note: the feature requirements were introduced in version v5.1 of the
430 // specification, for previous versions it is assumed that the same
431 // requirements apply for the subset of defined feature bits.
432
433 // The features listed in Table 3.5 are mandatory in this version of the
434 // specification (see Section 3.1) and these feature bits shall be set.
435 if (!SupportsLMPFeature(LMPFeaturesPage0Bits::ENCRYPTION) ||
436 !SupportsLMPFeature(
437 LMPFeaturesPage0Bits::SECURE_SIMPLE_PAIRING_CONTROLLER) ||
438 !SupportsLMPFeature(LMPFeaturesPage0Bits::ENCAPSULATED_PDU)) {
439 LOG_INFO("Table 3.5 validation failed");
440 return false;
441 }
442
443 // The features listed in Table 3.6 are forbidden in this version of the
444 // specification and these feature bits shall not be set.
445 if (SupportsLMPFeature(LMPFeaturesPage0Bits::BR_EDR_NOT_SUPPORTED)) {
446 LOG_INFO("Table 3.6 validation failed");
447 return false;
448 }
449
450 // For each row of Table 3.7, either every feature named in that row shall be
451 // supported or none of the features named in that row shall be supported.
452 if (SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_MODE) !=
453 SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_SUBRATING)) {
454 LOG_INFO("Table 3.7 validation failed");
455 return false;
456 }
457
458 // For each row of Table 3.8, not more than one feature in that row shall be
459 // supported.
460 if (SupportsLMPFeature(LMPFeaturesPage0Bits::BROADCAST_ENCRYPTION) &&
461 SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT)) {
462 LOG_INFO("Table 3.8 validation failed");
463 return false;
464 }
465
466 // For each row of Table 3.9, if the feature named in the first column is
467 // supported then the feature named in the second column shall be supported.
468 if (SupportsLMPFeature(LMPFeaturesPage0Bits::ROLE_SWITCH) &&
469 !SupportsLMPFeature(LMPFeaturesPage0Bits::SLOT_OFFSET)) {
470 LOG_INFO("Table 3.9 validation failed; expected Slot Offset");
471 return false;
472 }
473 if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV2_PACKETS) &&
474 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) {
475 LOG_INFO("Table 3.9 validation failed; expected Sco Link");
476 return false;
477 }
478 if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV3_PACKETS) &&
479 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) {
480 LOG_INFO("Table 3.9 validation failed; expected Sco Link");
481 return false;
482 }
483 if (SupportsLMPFeature(LMPFeaturesPage0Bits::M_LAW_LOG_SYNCHRONOUS_DATA) &&
484 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) &&
485 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
486 LOG_INFO(
487 "Table 3.9 validation failed; expected Sco Link or Extended Sco Link");
488 return false;
489 }
490 if (SupportsLMPFeature(LMPFeaturesPage0Bits::A_LAW_LOG_SYNCHRONOUS_DATA) &&
491 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) &&
492 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
493 LOG_INFO(
494 "Table 3.9 validation failed; expected Sco Link or Extended Sco Link");
495 return false;
496 }
497 if (SupportsLMPFeature(LMPFeaturesPage0Bits::CVSD_SYNCHRONOUS_DATA) &&
498 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) &&
499 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
500 LOG_INFO(
501 "Table 3.9 validation failed; expected Sco Link or Extended Sco Link");
502 return false;
503 }
504 if (SupportsLMPFeature(LMPFeaturesPage0Bits::TRANSPARENT_SYNCHRONOUS_DATA) &&
505 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) &&
506 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
507 LOG_INFO(
508 "Table 3.9 validation failed; expected Sco Link or Extended Sco Link");
509 return false;
510 }
511 if (SupportsLMPFeature(
512 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_3_MB_S_MODE) &&
513 !SupportsLMPFeature(
514 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) {
515 LOG_INFO(
516 "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s "
517 "mode");
518 return false;
519 }
520 if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV4_PACKETS) &&
521 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
522 LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link");
523 return false;
524 }
525 if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV5_PACKETS) &&
526 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
527 LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link");
528 return false;
529 }
530 if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_PERIPHERAL) &&
531 !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL)) {
532 LOG_INFO("Table 3.9 validation failed; expected AFH Capable Peripheral");
533 return false;
534 }
535 if (SupportsLMPFeature(
536 LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) &&
537 !SupportsLMPFeature(
538 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) {
539 LOG_INFO(
540 "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s "
541 "mode");
542 return false;
543 }
544 if (SupportsLMPFeature(
545 LMPFeaturesPage0Bits::LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) &&
546 !SupportsLMPFeature(
547 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) {
548 LOG_INFO(
549 "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s "
550 "mode");
551 return false;
552 }
553 if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_CENTRAL) &&
554 !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL)) {
555 LOG_INFO("Table 3.9 validation failed; expected AFH Capable Central");
556 return false;
557 }
558 if (SupportsLMPFeature(
559 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE) &&
560 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
561 LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link");
562 return false;
563 }
564 if (SupportsLMPFeature(
565 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_3_MB_S_MODE) &&
566 !SupportsLMPFeature(
567 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) {
568 LOG_INFO(
569 "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s "
570 "mode");
571 return false;
572 }
573 if (SupportsLMPFeature(
574 LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS) &&
575 !SupportsLMPFeature(
576 LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) {
577 LOG_INFO(
578 "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s "
579 "mode");
580 return false;
581 }
582 if (SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_INQUIRY_RESPONSE) &&
583 !SupportsLMPFeature(LMPFeaturesPage0Bits::RSSI_WITH_INQUIRY_RESULTS)) {
584 LOG_INFO("Table 3.9 validation failed; expected RSSI with Inquiry Results");
585 return false;
586 }
587 if (SupportsLMPFeature(
588 LMPFeaturesPage0Bits::SIMULTANEOUS_LE_AND_BR_CONTROLLER) &&
589 !SupportsLMPFeature(LMPFeaturesPage0Bits::LE_SUPPORTED_CONTROLLER)) {
590 LOG_INFO("Table 3.9 validation failed; expected LE Supported (Controller)");
591 return false;
592 }
593 if (SupportsLMPFeature(LMPFeaturesPage0Bits::ERRONEOUS_DATA_REPORTING) &&
594 !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) &&
595 !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) {
596 LOG_INFO(
597 "Table 3.9 validation failed; expected Sco Link or Extended Sco Link");
598 return false;
599 }
600 if (SupportsLMPFeature(LMPFeaturesPage0Bits::ENHANCED_POWER_CONTROL) &&
601 (!SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL_REQUESTS) ||
602 !SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL))) {
603 LOG_INFO(
604 "Table 3.9 validation failed; expected Power Control Request and Power "
605 "Control");
606 return false;
607 }
608 if (SupportsLMPFeature(
609 LMPFeaturesPage2Bits::
610 CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION) &&
611 !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN)) {
612 LOG_INFO("Table 3.9 validation failed; expected Synchronization Train");
613 return false;
614 }
615 if (SupportsLMPFeature(
616 LMPFeaturesPage2Bits::
617 CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION) &&
618 !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN)) {
619 LOG_INFO("Table 3.9 validation failed; expected Synchronization Scan");
620 return false;
621 }
622 if (SupportsLMPFeature(LMPFeaturesPage2Bits::GENERALIZED_INTERLACED_SCAN) &&
623 !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_INQUIRY_SCAN) &&
624 !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_PAGE_SCAN)) {
625 LOG_INFO(
626 "Table 3.9 validation failed; expected Interlaced Inquiry Scan or "
627 "Interlaced Page Scan");
628 return false;
629 }
630 if (SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT) &&
631 (!SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL) ||
632 !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL) ||
633 !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN) ||
634 !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN))) {
635 LOG_INFO(
636 "Table 3.9 validation failed; expected AFH Capable Central/Peripheral "
637 "and Synchronization Train/Scan");
638 return false;
639 }
640 if (SupportsLMPFeature(
641 LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT) &&
642 (!SupportsLMPFeature(LMPFeaturesPage0Bits::PAUSE_ENCRYPTION) ||
643 !SupportsLMPFeature(LMPFeaturesPage2Bits::PING))) {
644 LOG_INFO("Table 3.9 validation failed; expected Pause Encryption and Ping");
645 return false;
646 }
647
648 return true;
649 }
650
651 } // namespace rootcanal
652