diff --git a/model/controller/dual_mode_controller.cc b/model/controller/dual_mode_controller.cc index 728c60e..f0ceab7 100644 --- a/model/controller/dual_mode_controller.cc +++ b/model/controller/dual_mode_controller.cc @@ -3143,8 +3143,18 @@ void DualModeController::LeApcf(CommandView command) { break; } default: - FATAL(id_, "unknown APCF opcode {}", + ERROR(id_, "unknown APCF opcode {:#x}", static_cast(command_view.GetApcfOpcode())); + + send_event_(bluetooth::hci::LeApcfCompleteBuilder::Create( + kNumCommandPackets, ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, + command_view.GetApcfOpcode(), std::vector{})); + + invalid_packet_handler_( + id_, InvalidPacketReason::kUnsupported, + fmt::format("unsupported APCF opcode {:#x}", + static_cast(command_view.GetApcfOpcode())), + command_view.bytes().bytes()); } } diff --git a/model/controller/le_advertiser.cc b/model/controller/le_advertiser.cc index c27beef..0f5cfab 100644 --- a/model/controller/le_advertiser.cc +++ b/model/controller/le_advertiser.cc @@ -1841,9 +1841,9 @@ void LinkLayerController::LeAdvertising() { advertiser.advertising_event_properties.scannable_, advertiser.advertising_event_properties.directed_, advertiser.advertising_sid, advertiser.advertising_tx_power, - static_cast( + static_cast( advertiser.primary_advertising_phy), - static_cast( + static_cast( advertiser.secondary_advertising_phy), advertiser.periodic_advertising_interval.count(), advertiser.advertising_data), diff --git a/model/controller/link_layer_controller.cc b/model/controller/link_layer_controller.cc index d0754bd..ae595b6 100644 --- a/model/controller/link_layer_controller.cc +++ b/model/controller/link_layer_controller.cc @@ -3378,9 +3378,39 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( bool scannable_advertising = pdu.GetScannable(); bool connectable_advertising = pdu.GetConnectable(); bool directed_advertising = pdu.GetDirected(); + auto primary_phy = pdu.GetPrimaryPhy(); + auto secondary_phy = pdu.GetSecondaryPhy(); + + // Check originating primary PHY, compare against active scanning PHYs. + if ((primary_phy == model::packets::PhyType::LE_1M && + !scanner_.le_1m_phy.enabled) || + (primary_phy == model::packets::PhyType::LE_CODED_S8 && + !scanner_.le_coded_phy.enabled)) { + DEBUG(id_, + "Extended adverising ignored because the scanner is not scanning on " + "the primary phy type {}", + model::packets::PhyTypeText(primary_phy)); + return; + } - // TODO: check originating PHY, compare against active scanning PHYs - // (scanner_.le_1m_phy or scanner_.le_coded_phy). + // Check originating sceondary PHY, compare against local + // supported features. The primary PHY is validated by the command + // LE Set Extended Scan Parameters. + if ((secondary_phy == model::packets::PhyType::LE_2M && + !properties_.SupportsLLFeature( + bluetooth::hci::LLFeaturesBits::LE_2M_PHY)) || + (secondary_phy == model::packets::PhyType::LE_CODED_S8 && + !properties_.SupportsLLFeature( + bluetooth::hci::LLFeaturesBits::LE_CODED_PHY)) || + (secondary_phy == model::packets::PhyType::LE_CODED_S2 && + !properties_.SupportsLLFeature( + bluetooth::hci::LLFeaturesBits::LE_CODED_PHY))) { + DEBUG(id_, + "Extended adverising ignored because the scanner does not support " + "the secondary phy type {}", + model::packets::PhyTypeText(secondary_phy)); + return; + } // When a scanner receives an advertising packet that contains a resolvable // private address for the advertiser’s device address (AdvA field) and @@ -3477,8 +3507,10 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu( static_cast( resolved_advertising_address.GetAddressType()); response.address_ = resolved_advertising_address.GetAddress(); - response.primary_phy_ = bluetooth::hci::PrimaryPhyType::LE_1M; - response.secondary_phy_ = bluetooth::hci::SecondaryPhyType::NO_PACKETS; + response.primary_phy_ = + static_cast(primary_phy); + response.secondary_phy_ = + static_cast(secondary_phy); response.advertising_sid_ = pdu.GetSid(); response.tx_power_ = pdu.GetTxPower(); response.rssi_ = rssi; diff --git a/packets/link_layer_packets.pdl b/packets/link_layer_packets.pdl index d2fcbfc..a4f763d 100644 --- a/packets/link_layer_packets.pdl +++ b/packets/link_layer_packets.pdl @@ -150,16 +150,16 @@ packet LeLegacyAdvertisingPdu : LinkLayerPacket (type = LE_LEGACY_ADVERTISING_PD advertising_data: 8[], } -enum PrimaryPhyType : 8 { - LE_1M = 0x01, - LE_CODED = 0x03, -} - -enum SecondaryPhyType : 8 { +// PHY type. Matching the primary and secondary PHY types +// from the following commands and events: +// - Vol 4, Part E § 7.7.65.13 LE Extended Advertising Report event +// - Vol 4, Part E § 7.8.53 LE Set Extended Advertising Parameters command +enum PhyType : 8 { NO_PACKETS = 0x00, LE_1M = 0x01, LE_2M = 0x02, - LE_CODED = 0x03, + LE_CODED_S8 = 0x03, + LE_CODED_S2 = 0x04, } packet LeExtendedAdvertisingPdu : LinkLayerPacket (type = LE_EXTENDED_ADVERTISING_PDU) { @@ -171,8 +171,8 @@ packet LeExtendedAdvertisingPdu : LinkLayerPacket (type = LE_EXTENDED_ADVERTISIN _reserved_: 5, sid: 8, // 0xff when not provided tx_power: 8, - primary_phy: PrimaryPhyType, - secondary_phy: SecondaryPhyType, + primary_phy: PhyType, // LE_1M | LE_CODEC_S8 + secondary_phy: PhyType, periodic_advertising_interval: 16, advertising_data: 8[], } diff --git a/test/LL/DDI/ADV/BV_26_C.py b/test/LL/DDI/ADV/BV_26_C.py index 909b08a..24bc1d1 100644 --- a/test/LL/DDI/ADV/BV_26_C.py +++ b/test/LL/DDI/ADV/BV_26_C.py @@ -188,8 +188,8 @@ async def steps_2_16(self, maximum_advertising_data_length: int, data_length: in directed=False, sid=0, tx_power=0, - primary_phy=ll.PrimaryPhyType.LE_1M, - secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + primary_phy=ll.PhyType.LE_1M, + secondary_phy=ll.PhyType.NO_PACKETS, periodic_advertising_interval=0x100, advertising_data=[]), ll.LePeriodicAdvertisingPdu(source_address=controller.address, diff --git a/test/LL/DDI/ADV/BV_47_C.py b/test/LL/DDI/ADV/BV_47_C.py index 5430f8e..64b4718 100644 --- a/test/LL/DDI/ADV/BV_47_C.py +++ b/test/LL/DDI/ADV/BV_47_C.py @@ -197,8 +197,8 @@ async def steps_2_13(self, maximum_advertising_data_length: int, advertising_eve directed=int(advertising_event_properties.directed), sid=0, tx_power=0, - primary_phy=ll.PrimaryPhyType.LE_1M, - secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + primary_phy=ll.PhyType.LE_1M, + secondary_phy=ll.PhyType.NO_PACKETS, advertising_data=advertising_data)) # 10. If the Max_Extended_Advertising_Events was set to a value different than 0, repeat steps 6–9 diff --git a/test/LL/DDI/SCN/BV_19_C.py b/test/LL/DDI/SCN/BV_19_C.py index 41c3db5..abaa0b9 100644 --- a/test/LL/DDI/SCN/BV_19_C.py +++ b/test/LL/DDI/SCN/BV_19_C.py @@ -144,8 +144,8 @@ async def steps_1_6(self, duration: int, advertising_event_properties: int, targ directed=not target_address is None, sid=0, tx_power=0x7f, - primary_phy=ll.PrimaryPhyType.LE_1M, - secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + primary_phy=ll.PhyType.LE_1M, + secondary_phy=ll.PhyType.NO_PACKETS, advertising_data=[]) # 4. For undirected advertisements or advertisements directed at the IUT, the Upper Tester receives diff --git a/test/LL/DDI/SCN/BV_20_C.py b/test/LL/DDI/SCN/BV_20_C.py index 726e35a..74a3213 100644 --- a/test/LL/DDI/SCN/BV_20_C.py +++ b/test/LL/DDI/SCN/BV_20_C.py @@ -142,8 +142,8 @@ async def steps_2_8(self, advertising_event_properties: int, target_address: Opt directed=not target_address is None, sid=0, tx_power=0x7f, - primary_phy=ll.PrimaryPhyType.LE_1M, - secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + primary_phy=ll.PhyType.LE_1M, + secondary_phy=ll.PhyType.NO_PACKETS, advertising_data=[]) # 5. For undirected advertisements or advertisements directed at the IUT, the Lower Tester receives diff --git a/test/LL/DDI/SCN/BV_79_C.py b/test/LL/DDI/SCN/BV_79_C.py index 80a6245..c58b7e9 100644 --- a/test/LL/DDI/SCN/BV_79_C.py +++ b/test/LL/DDI/SCN/BV_79_C.py @@ -85,8 +85,8 @@ async def test(self): directed=False, sid=advertising_sid, tx_power=tx_power, - primary_phy=ll.PrimaryPhyType.LE_1M, - secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + primary_phy=ll.PhyType.LE_1M, + secondary_phy=ll.PhyType.NO_PACKETS, periodic_advertising_interval=0x100, advertising_data=[]), rssi=0x10) diff --git a/test/controller/le/le_scanning_filter_duplicates_test.cc b/test/controller/le/le_scanning_filter_duplicates_test.cc index feed4ed..6ef5a2b 100644 --- a/test/controller/le/le_scanning_filter_duplicates_test.cc +++ b/test/controller/le/le_scanning_filter_duplicates_test.cc @@ -113,8 +113,8 @@ class LeScanningFilterDuplicates : public ::testing::Test { return FromBuilder(model::packets::LeExtendedAdvertisingPduBuilder::Create( Address::kEmpty, Address::kEmpty, model::packets::AddressType::PUBLIC, model::packets::AddressType::PUBLIC, 0, 1, 0, 0, 0, - model::packets::PrimaryPhyType::LE_1M, - model::packets::SecondaryPhyType::LE_1M, 0, data)); + model::packets::PhyType::LE_1M, model::packets::PhyType::LE_1M, 0, + data)); } static model::packets::LinkLayerPacketView FromBuilder(