• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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