Loading tools/rootcanal/model/controller/controller_properties.cc +325 −14 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include "controller_properties.h" #include <inttypes.h> #include <json/json.h> #include <fstream> Loading Loading @@ -86,21 +87,10 @@ static constexpr uint64_t Page0LmpFeatures() { return value; } static constexpr uint64_t Page1LmpFeatures() { LMPFeaturesPage1Bits features[] = { LMPFeaturesPage1Bits::SIMULTANEOUS_LE_AND_BR_HOST, }; uint64_t value = 0; for (auto feature : features) { value |= static_cast<uint64_t>(feature); } return value; } static constexpr uint64_t Page2LmpFeatures() { LMPFeaturesPage2Bits features[] = { LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT, LMPFeaturesPage2Bits::PING, }; uint64_t value = 0; Loading Loading @@ -236,8 +226,7 @@ static void ParseHex64(Json::Value value, uint64_t* field) { } ControllerProperties::ControllerProperties(const std::string& file_name) : lmp_features( {Page0LmpFeatures(), Page1LmpFeatures(), Page2LmpFeatures()}), : lmp_features({Page0LmpFeatures(), 0, Page2LmpFeatures()}), le_features(LlFeatures()) { // Set support for all HCI commands by default. // The controller will update the mask with its implemented commands Loading @@ -251,6 +240,13 @@ ControllerProperties::ControllerProperties(const std::string& file_name) supported_commands[i] = 0x00; } if (!CheckSupportedFeatures()) { LOG_INFO( "Warning: initial LMP and/or LE are not consistent. Please make sure" " that the features are correct w.r.t. the rules described" " in Vol 2, Part C 3.5 Feature requirements"); } if (file_name.empty()) { return; } Loading Loading @@ -329,6 +325,15 @@ ControllerProperties::ControllerProperties(const std::string& file_name) this->hci_version = static_cast<HciVersion>(hci_version); this->lmp_version = static_cast<LmpVersion>(lmp_version); if (!CheckSupportedFeatures()) { LOG_INFO( "Warning: the LMP and/or LE are not consistent. Please make sure" " that the features are correct w.r.t. the rules described" " in Vol 2, Part C 3.5 Feature requirements"); } else { LOG_INFO("LMP and LE features successfully validated"); } } void ControllerProperties::SetSupportedCommands( Loading @@ -338,4 +343,310 @@ void ControllerProperties::SetSupportedCommands( } } bool ControllerProperties::CheckSupportedFeatures() const { // Vol 2, Part C § 3.3 Feature mask definition. // Check for reserved or deprecated feature bits. // // Note: the specification for v1.0 and v1.1 is no longer available for // download, the reserved feature bits are copied over from v1.2. uint64_t lmp_page_0_reserved_bits = 0; uint64_t lmp_page_2_reserved_bits = 0; switch (lmp_version) { case bluetooth::hci::LmpVersion::V_1_0B: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_1_1: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_1_2: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_2_0: lmp_page_0_reserved_bits = UINT64_C(0x7fff066401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_2_1: lmp_page_0_reserved_bits = UINT64_C(0x7c86006401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_3_0: lmp_page_0_reserved_bits = UINT64_C(0x7886006401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_4_0: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_4_1: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_4_2: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_5_0: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_5_1: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; case bluetooth::hci::LmpVersion::V_5_2: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; case bluetooth::hci::LmpVersion::V_5_3: default: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; }; if ((lmp_page_0_reserved_bits & lmp_features[0]) != 0) { LOG_INFO("The page 0 feature bits 0x%016" PRIx64 " are reserved in the specification %s", lmp_page_0_reserved_bits & lmp_features[0], LmpVersionText(lmp_version).c_str()); return false; } if ((lmp_page_2_reserved_bits & lmp_features[2]) != 0) { LOG_INFO("The page 2 feature bits 0x%016" PRIx64 " are reserved in the specification %s", lmp_page_2_reserved_bits & lmp_features[2], LmpVersionText(lmp_version).c_str()); return false; } // Vol 2, Part C § 3.5 Feature requirements. // RootCanal always support BR/EDR mode, this function implements // the feature requirements from the subsection 1. Devices supporting BR/EDR. // // Note: the feature requirements were introduced in version v5.1 of the // specification, for previous versions it is assumed that the same // requirements apply for the subset of defined feature bits. // The features listed in Table 3.5 are mandatory in this version of the // specification (see Section 3.1) and these feature bits shall be set. if (!SupportsLMPFeature(LMPFeaturesPage0Bits::ENCRYPTION) || !SupportsLMPFeature( LMPFeaturesPage0Bits::SECURE_SIMPLE_PAIRING_CONTROLLER) || !SupportsLMPFeature(LMPFeaturesPage0Bits::ENCAPSULATED_PDU)) { LOG_INFO("Table 3.5 validation failed"); return false; } // The features listed in Table 3.6 are forbidden in this version of the // specification and these feature bits shall not be set. if (SupportsLMPFeature(LMPFeaturesPage0Bits::BR_EDR_NOT_SUPPORTED)) { LOG_INFO("Table 3.6 validation failed"); return false; } // For each row of Table 3.7, either every feature named in that row shall be // supported or none of the features named in that row shall be supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_MODE) != SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_SUBRATING)) { LOG_INFO("Table 3.7 validation failed"); return false; } // For each row of Table 3.8, not more than one feature in that row shall be // supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::BROADCAST_ENCRYPTION) && SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT)) { LOG_INFO("Table 3.8 validation failed"); return false; } // For each row of Table 3.9, if the feature named in the first column is // supported then the feature named in the second column shall be supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::ROLE_SWITCH) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SLOT_OFFSET)) { LOG_INFO("Table 3.9 validation failed; expected Slot Offset"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV2_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV3_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::M_LAW_LOG_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::A_LAW_LOG_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::CVSD_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::TRANSPARENT_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_3_MB_S_MODE) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV4_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV5_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_PERIPHERAL) && !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL)) { LOG_INFO("Table 3.9 validation failed; expected AFH Capable Peripheral"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_CENTRAL) && !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL)) { LOG_INFO("Table 3.9 validation failed; expected AFH Capable Central"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_3_MB_S_MODE) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s " "mode"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_INQUIRY_RESPONSE) && !SupportsLMPFeature(LMPFeaturesPage0Bits::RSSI_WITH_INQUIRY_RESULTS)) { LOG_INFO("Table 3.9 validation failed; expected RSSI with Inquiry Results"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::SIMULTANEOUS_LE_AND_BR_CONTROLLER) && !SupportsLMPFeature(LMPFeaturesPage0Bits::LE_SUPPORTED_CONTROLLER)) { LOG_INFO("Table 3.9 validation failed; expected LE Supported (Controller)"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::ERRONEOUS_DATA_REPORTING) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::ENHANCED_POWER_CONTROL) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL_REQUESTS) || !SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL))) { LOG_INFO( "Table 3.9 validation failed; expected Power Control Request and Power " "Control"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits:: CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION) && !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN)) { LOG_INFO("Table 3.9 validation failed; expected Synchronization Train"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits:: CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION) && !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN)) { LOG_INFO("Table 3.9 validation failed; expected Synchronization Scan"); return false; } if (SupportsLMPFeature(LMPFeaturesPage2Bits::GENERALIZED_INTERLACED_SCAN) && !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_INQUIRY_SCAN) && !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_PAGE_SCAN)) { LOG_INFO( "Table 3.9 validation failed; expected Interlaced Inquiry Scan or " "Interlaced Page Scan"); return false; } if (SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL) || !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL) || !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN) || !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN))) { LOG_INFO( "Table 3.9 validation failed; expected AFH Capable Central/Peripheral " "and Synchronization Train/Scan"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::PAUSE_ENCRYPTION) || !SupportsLMPFeature(LMPFeaturesPage2Bits::PING))) { LOG_INFO("Table 3.9 validation failed; expected Pause Encryption and Ping"); return false; } return true; } } // namespace rootcanal tools/rootcanal/model/controller/controller_properties.h +11 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,9 @@ struct ControllerProperties { // file or all 1s. void SetSupportedCommands(std::array<uint8_t, 64> supported_commands); // Check if the feature masks are valid according to the specification. bool CheckSupportedFeatures() const; // Local Version Information (Vol 4, Part E § 7.4.1). HciVersion hci_version{HciVersion::V_5_3}; LmpVersion lmp_version{LmpVersion::V_5_3}; Loading Loading @@ -108,6 +111,14 @@ struct ControllerProperties { // Vendor Information. // Provide parameters returned by vendor specific commands. std::vector<uint8_t> le_vendor_capabilities{}; bool SupportsLMPFeature(bluetooth::hci::LMPFeaturesPage0Bits bit) const { return (lmp_features[0] & static_cast<uint64_t>(bit)) != 0; } bool SupportsLMPFeature(bluetooth::hci::LMPFeaturesPage2Bits bit) const { return (lmp_features[2] & static_cast<uint64_t>(bit)) != 0; } }; } // namespace rootcanal tools/rootcanal/model/controller/link_layer_controller.cc +7 −0 Original line number Diff line number Diff line Loading @@ -1274,6 +1274,9 @@ void LinkLayerController::SetSecureSimplePairingSupport(bool enable) { } void LinkLayerController::SetLeHostSupport(bool enable) { // TODO: Vol 2, Part C § 3.5 Feature requirements. // (65) LE Supported (Host) implies // (38) LE Supported (Controller) uint64_t bit = 0x2; le_host_support_ = enable; if (enable) { Loading @@ -1284,6 +1287,10 @@ void LinkLayerController::SetLeHostSupport(bool enable) { } void LinkLayerController::SetSecureConnectionsSupport(bool enable) { // TODO: Vol 2, Part C § 3.5 Feature requirements. // (67) Secure Connections (Host Support) implies // (64) Secure Simple Pairing (Host Support) and // (136) Secure Connections (Controller Support) uint64_t bit = 0x8; secure_connections_host_support_ = enable; if (enable) { Loading Loading
tools/rootcanal/model/controller/controller_properties.cc +325 −14 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include "controller_properties.h" #include <inttypes.h> #include <json/json.h> #include <fstream> Loading Loading @@ -86,21 +87,10 @@ static constexpr uint64_t Page0LmpFeatures() { return value; } static constexpr uint64_t Page1LmpFeatures() { LMPFeaturesPage1Bits features[] = { LMPFeaturesPage1Bits::SIMULTANEOUS_LE_AND_BR_HOST, }; uint64_t value = 0; for (auto feature : features) { value |= static_cast<uint64_t>(feature); } return value; } static constexpr uint64_t Page2LmpFeatures() { LMPFeaturesPage2Bits features[] = { LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT, LMPFeaturesPage2Bits::PING, }; uint64_t value = 0; Loading Loading @@ -236,8 +226,7 @@ static void ParseHex64(Json::Value value, uint64_t* field) { } ControllerProperties::ControllerProperties(const std::string& file_name) : lmp_features( {Page0LmpFeatures(), Page1LmpFeatures(), Page2LmpFeatures()}), : lmp_features({Page0LmpFeatures(), 0, Page2LmpFeatures()}), le_features(LlFeatures()) { // Set support for all HCI commands by default. // The controller will update the mask with its implemented commands Loading @@ -251,6 +240,13 @@ ControllerProperties::ControllerProperties(const std::string& file_name) supported_commands[i] = 0x00; } if (!CheckSupportedFeatures()) { LOG_INFO( "Warning: initial LMP and/or LE are not consistent. Please make sure" " that the features are correct w.r.t. the rules described" " in Vol 2, Part C 3.5 Feature requirements"); } if (file_name.empty()) { return; } Loading Loading @@ -329,6 +325,15 @@ ControllerProperties::ControllerProperties(const std::string& file_name) this->hci_version = static_cast<HciVersion>(hci_version); this->lmp_version = static_cast<LmpVersion>(lmp_version); if (!CheckSupportedFeatures()) { LOG_INFO( "Warning: the LMP and/or LE are not consistent. Please make sure" " that the features are correct w.r.t. the rules described" " in Vol 2, Part C 3.5 Feature requirements"); } else { LOG_INFO("LMP and LE features successfully validated"); } } void ControllerProperties::SetSupportedCommands( Loading @@ -338,4 +343,310 @@ void ControllerProperties::SetSupportedCommands( } } bool ControllerProperties::CheckSupportedFeatures() const { // Vol 2, Part C § 3.3 Feature mask definition. // Check for reserved or deprecated feature bits. // // Note: the specification for v1.0 and v1.1 is no longer available for // download, the reserved feature bits are copied over from v1.2. uint64_t lmp_page_0_reserved_bits = 0; uint64_t lmp_page_2_reserved_bits = 0; switch (lmp_version) { case bluetooth::hci::LmpVersion::V_1_0B: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_1_1: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_1_2: lmp_page_0_reserved_bits = UINT64_C(0x7fffe7e407000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_2_0: lmp_page_0_reserved_bits = UINT64_C(0x7fff066401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_2_1: lmp_page_0_reserved_bits = UINT64_C(0x7c86006401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_3_0: lmp_page_0_reserved_bits = UINT64_C(0x7886006401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_4_0: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xffffffffffffffff); break; case bluetooth::hci::LmpVersion::V_4_1: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_4_2: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000000); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_5_0: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff480); break; case bluetooth::hci::LmpVersion::V_5_1: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; case bluetooth::hci::LmpVersion::V_5_2: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; case bluetooth::hci::LmpVersion::V_5_3: default: lmp_page_0_reserved_bits = UINT64_C(0x7884000401000100); lmp_page_2_reserved_bits = UINT64_C(0xfffffffffffff080); break; }; if ((lmp_page_0_reserved_bits & lmp_features[0]) != 0) { LOG_INFO("The page 0 feature bits 0x%016" PRIx64 " are reserved in the specification %s", lmp_page_0_reserved_bits & lmp_features[0], LmpVersionText(lmp_version).c_str()); return false; } if ((lmp_page_2_reserved_bits & lmp_features[2]) != 0) { LOG_INFO("The page 2 feature bits 0x%016" PRIx64 " are reserved in the specification %s", lmp_page_2_reserved_bits & lmp_features[2], LmpVersionText(lmp_version).c_str()); return false; } // Vol 2, Part C § 3.5 Feature requirements. // RootCanal always support BR/EDR mode, this function implements // the feature requirements from the subsection 1. Devices supporting BR/EDR. // // Note: the feature requirements were introduced in version v5.1 of the // specification, for previous versions it is assumed that the same // requirements apply for the subset of defined feature bits. // The features listed in Table 3.5 are mandatory in this version of the // specification (see Section 3.1) and these feature bits shall be set. if (!SupportsLMPFeature(LMPFeaturesPage0Bits::ENCRYPTION) || !SupportsLMPFeature( LMPFeaturesPage0Bits::SECURE_SIMPLE_PAIRING_CONTROLLER) || !SupportsLMPFeature(LMPFeaturesPage0Bits::ENCAPSULATED_PDU)) { LOG_INFO("Table 3.5 validation failed"); return false; } // The features listed in Table 3.6 are forbidden in this version of the // specification and these feature bits shall not be set. if (SupportsLMPFeature(LMPFeaturesPage0Bits::BR_EDR_NOT_SUPPORTED)) { LOG_INFO("Table 3.6 validation failed"); return false; } // For each row of Table 3.7, either every feature named in that row shall be // supported or none of the features named in that row shall be supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_MODE) != SupportsLMPFeature(LMPFeaturesPage0Bits::SNIFF_SUBRATING)) { LOG_INFO("Table 3.7 validation failed"); return false; } // For each row of Table 3.8, not more than one feature in that row shall be // supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::BROADCAST_ENCRYPTION) && SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT)) { LOG_INFO("Table 3.8 validation failed"); return false; } // For each row of Table 3.9, if the feature named in the first column is // supported then the feature named in the second column shall be supported. if (SupportsLMPFeature(LMPFeaturesPage0Bits::ROLE_SWITCH) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SLOT_OFFSET)) { LOG_INFO("Table 3.9 validation failed; expected Slot Offset"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV2_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::HV3_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::M_LAW_LOG_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::A_LAW_LOG_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::CVSD_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::TRANSPARENT_SYNCHRONOUS_DATA) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_3_MB_S_MODE) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV4_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EV5_PACKETS) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_PERIPHERAL) && !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL)) { LOG_INFO("Table 3.9 validation failed; expected AFH Capable Peripheral"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_5_SLOT_ENHANCED_DATA_RATE_ACL_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ACL_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate ACL 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CLASSIFICATION_CENTRAL) && !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL)) { LOG_INFO("Table 3.9 validation failed; expected AFH Capable Central"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO("Table 3.9 validation failed; expected Extended Sco Link"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_3_MB_S_MODE) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s " "mode"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::LMP_3_SLOT_ENHANCED_DATA_RATE_ESCO_PACKETS) && !SupportsLMPFeature( LMPFeaturesPage0Bits::ENHANCED_DATA_RATE_ESCO_2_MB_S_MODE)) { LOG_INFO( "Table 3.9 validation failed; expected Enhanced Data Rate eSCO 2Mb/s " "mode"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_INQUIRY_RESPONSE) && !SupportsLMPFeature(LMPFeaturesPage0Bits::RSSI_WITH_INQUIRY_RESULTS)) { LOG_INFO("Table 3.9 validation failed; expected RSSI with Inquiry Results"); return false; } if (SupportsLMPFeature( LMPFeaturesPage0Bits::SIMULTANEOUS_LE_AND_BR_CONTROLLER) && !SupportsLMPFeature(LMPFeaturesPage0Bits::LE_SUPPORTED_CONTROLLER)) { LOG_INFO("Table 3.9 validation failed; expected LE Supported (Controller)"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::ERRONEOUS_DATA_REPORTING) && !SupportsLMPFeature(LMPFeaturesPage0Bits::SCO_LINK) && !SupportsLMPFeature(LMPFeaturesPage0Bits::EXTENDED_SCO_LINK)) { LOG_INFO( "Table 3.9 validation failed; expected Sco Link or Extended Sco Link"); return false; } if (SupportsLMPFeature(LMPFeaturesPage0Bits::ENHANCED_POWER_CONTROL) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL_REQUESTS) || !SupportsLMPFeature(LMPFeaturesPage0Bits::POWER_CONTROL))) { LOG_INFO( "Table 3.9 validation failed; expected Power Control Request and Power " "Control"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits:: CONNECTIONLESS_PERIPHERAL_BROADCAST_TRANSMITTER_OPERATION) && !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN)) { LOG_INFO("Table 3.9 validation failed; expected Synchronization Train"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits:: CONNECTIONLESS_PERIPHERAL_BROADCAST_RECEIVER_OPERATION) && !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN)) { LOG_INFO("Table 3.9 validation failed; expected Synchronization Scan"); return false; } if (SupportsLMPFeature(LMPFeaturesPage2Bits::GENERALIZED_INTERLACED_SCAN) && !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_INQUIRY_SCAN) && !SupportsLMPFeature(LMPFeaturesPage0Bits::INTERLACED_PAGE_SCAN)) { LOG_INFO( "Table 3.9 validation failed; expected Interlaced Inquiry Scan or " "Interlaced Page Scan"); return false; } if (SupportsLMPFeature(LMPFeaturesPage2Bits::COARSE_CLOCK_ADJUSTMENT) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_PERIPHERAL) || !SupportsLMPFeature(LMPFeaturesPage0Bits::AFH_CAPABLE_CENTRAL) || !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_TRAIN) || !SupportsLMPFeature(LMPFeaturesPage2Bits::SYNCHRONIZATION_SCAN))) { LOG_INFO( "Table 3.9 validation failed; expected AFH Capable Central/Peripheral " "and Synchronization Train/Scan"); return false; } if (SupportsLMPFeature( LMPFeaturesPage2Bits::SECURE_CONNECTIONS_CONTROLLER_SUPPORT) && (!SupportsLMPFeature(LMPFeaturesPage0Bits::PAUSE_ENCRYPTION) || !SupportsLMPFeature(LMPFeaturesPage2Bits::PING))) { LOG_INFO("Table 3.9 validation failed; expected Pause Encryption and Ping"); return false; } return true; } } // namespace rootcanal
tools/rootcanal/model/controller/controller_properties.h +11 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,9 @@ struct ControllerProperties { // file or all 1s. void SetSupportedCommands(std::array<uint8_t, 64> supported_commands); // Check if the feature masks are valid according to the specification. bool CheckSupportedFeatures() const; // Local Version Information (Vol 4, Part E § 7.4.1). HciVersion hci_version{HciVersion::V_5_3}; LmpVersion lmp_version{LmpVersion::V_5_3}; Loading Loading @@ -108,6 +111,14 @@ struct ControllerProperties { // Vendor Information. // Provide parameters returned by vendor specific commands. std::vector<uint8_t> le_vendor_capabilities{}; bool SupportsLMPFeature(bluetooth::hci::LMPFeaturesPage0Bits bit) const { return (lmp_features[0] & static_cast<uint64_t>(bit)) != 0; } bool SupportsLMPFeature(bluetooth::hci::LMPFeaturesPage2Bits bit) const { return (lmp_features[2] & static_cast<uint64_t>(bit)) != 0; } }; } // namespace rootcanal
tools/rootcanal/model/controller/link_layer_controller.cc +7 −0 Original line number Diff line number Diff line Loading @@ -1274,6 +1274,9 @@ void LinkLayerController::SetSecureSimplePairingSupport(bool enable) { } void LinkLayerController::SetLeHostSupport(bool enable) { // TODO: Vol 2, Part C § 3.5 Feature requirements. // (65) LE Supported (Host) implies // (38) LE Supported (Controller) uint64_t bit = 0x2; le_host_support_ = enable; if (enable) { Loading @@ -1284,6 +1287,10 @@ void LinkLayerController::SetLeHostSupport(bool enable) { } void LinkLayerController::SetSecureConnectionsSupport(bool enable) { // TODO: Vol 2, Part C § 3.5 Feature requirements. // (67) Secure Connections (Host Support) implies // (64) Secure Simple Pairing (Host Support) and // (136) Secure Connections (Controller Support) uint64_t bit = 0x8; secure_connections_host_support_ = enable; if (enable) { Loading