Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a45b26b authored by Henri Chataing's avatar Henri Chataing Committed by Automerger Merge Worker
Browse files

Merge "RootCanal: Implement additional LL tests" am: 91f7e717

parents 7d132ccb 91f7e717
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -32,7 +32,7 @@ using std::vector;


namespace rootcanal {
namespace rootcanal {
constexpr uint16_t kNumCommandPackets = 0x01;
constexpr uint16_t kNumCommandPackets = 0x01;
constexpr uint16_t kLeMaximumAdvertisingDataLength = 256;
constexpr uint16_t kLeMaximumAdvertisingDataLength = 512;
constexpr uint16_t kLeMaximumDataLength = 64;
constexpr uint16_t kLeMaximumDataLength = 64;
constexpr uint16_t kLeMaximumDataTime = 0x148;
constexpr uint16_t kLeMaximumDataTime = 0x148;


+21 −4
Original line number Original line Diff line number Diff line
@@ -1015,10 +1015,11 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable(
    // If the advertising is high duty cycle connectable directed advertising,
    // If the advertising is high duty cycle connectable directed advertising,
    // then Duration[i] shall be less than or equal to 1.28 seconds and shall
    // then Duration[i] shall be less than or equal to 1.28 seconds and shall
    // not be equal to 0.
    // not be equal to 0.
    std::chrono::milliseconds duration =
        std::chrono::milliseconds(set.duration_ * 10);
    if (connectable_advertising && directed_advertising &&
    if (connectable_advertising && directed_advertising &&
        high_duty_cycle_advertising &&
        high_duty_cycle_advertising &&
        (set.duration_ == 0 ||
        (set.duration_ == 0 || duration > adv_direct_ind_high_timeout)) {
         slots(set.duration_) > adv_direct_ind_high_timeout)) {
      LOG_INFO(
      LOG_INFO(
          "extended advertising is high duty cycle connectable directed"
          "extended advertising is high duty cycle connectable directed"
          " but the duration is either 0 or larger than 1.28 seconds");
          " but the duration is either 0 or larger than 1.28 seconds");
@@ -1141,10 +1142,19 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable(
    ExtendedAdvertiser& advertiser =
    ExtendedAdvertiser& advertiser =
        extended_advertisers_[set.advertising_handle_];
        extended_advertisers_[set.advertising_handle_];


    advertiser.max_extended_advertising_events =
        set.max_extended_advertising_events_;
    advertiser.num_completed_extended_advertising_events = 0;
    advertiser.num_completed_extended_advertising_events = 0;
    advertiser.advertising_enable = true;
    advertiser.advertising_enable = true;
    advertiser.next_event = std::chrono::steady_clock::now() +
    advertiser.next_event = std::chrono::steady_clock::now() +
                            advertiser.primary_advertising_interval;
                            advertiser.primary_advertising_interval;
    if (set.duration_ > 0) {
      std::chrono::milliseconds duration =
          std::chrono::milliseconds(set.duration_ * 10);
      advertiser.timeout = std::chrono::steady_clock::now() + duration;
    } else {
      advertiser.timeout.reset();
    }
  }
  }


  return ErrorCode::SUCCESS;
  return ErrorCode::SUCCESS;
@@ -1374,7 +1384,7 @@ void LinkLayerController::LeAdvertising() {
  for (auto& [_, advertiser] : extended_advertisers_) {
  for (auto& [_, advertiser] : extended_advertisers_) {
    // Extended Advertising Timeouts
    // Extended Advertising Timeouts


    if (advertiser.IsEnabled() && advertiser.timeout &&
    if (advertiser.IsEnabled() && advertiser.timeout.has_value() &&
        now >= advertiser.timeout.value()) {
        now >= advertiser.timeout.value()) {
      // If the Duration[i] parameter is set to a value other than 0x0000, an
      // If the Duration[i] parameter is set to a value other than 0x0000, an
      // HCI_LE_Advertising_Set_Terminated event shall be generated when the
      // HCI_LE_Advertising_Set_Terminated event shall be generated when the
@@ -1412,9 +1422,16 @@ void LinkLayerController::LeAdvertising() {
      }
      }


      if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
      if (IsLeEventUnmasked(SubeventCode::ADVERTISING_SET_TERMINATED)) {
        // The parameter Num_Completed_Extended_Advertising_Events is set
        // only when Max_Extended_Advertising_Events was configured as
        // non-zero in the advertising parameters.
        uint8_t num_completed_extended_advertising_events =
            advertiser.max_extended_advertising_events != 0
                ? advertiser.num_completed_extended_advertising_events
                : 0;
        send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
        send_event_(bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
            ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
            ErrorCode::ADVERTISING_TIMEOUT, advertiser.advertising_handle, 0,
            advertiser.num_completed_extended_advertising_events));
            num_completed_extended_advertising_events));
      }
      }
    }
    }


+16 −0
Original line number Original line Diff line number Diff line
@@ -128,6 +128,22 @@ class ControllerTest(unittest.IsolatedAsyncioTestCase):
            evt.show()
            evt.show()
            self.assertTrue(False)
            self.assertTrue(False)


    async def expect_cmd_complete(self, expected_evt: type, timeout: int = 3) -> hci.Event:
        packet = await asyncio.wait_for(self.controller.receive_evt(), timeout=timeout)
        evt = hci.Event.parse_all(packet)

        if not isinstance(evt, expected_evt):
            print("received unexpected event")
            print("expected event:")
            print(expected_evt)
            print("received event:")
            evt.show()
            self.assertTrue(False)

        assert evt.status == ErrorCode.SUCCESS
        assert evt.num_hci_command_packets == 1
        return evt

    async def expect_ll(self, expected_pdu: ll.LinkLayerPacket, timeout: int = 3):
    async def expect_ll(self, expected_pdu: ll.LinkLayerPacket, timeout: int = 3):
        packet = await asyncio.wait_for(self.controller.receive_ll(), timeout=timeout)
        packet = await asyncio.wait_for(self.controller.receive_ll(), timeout=timeout)
        pdu = ll.LinkLayerPacket.parse_all(packet)
        pdu = ll.LinkLayerPacket.parse_all(packet)
+1 −4
Original line number Original line Diff line number Diff line
import lib_rootcanal_python3 as rootcanal
import hci_packets as hci
import hci_packets as hci
import link_layer_packets as ll
import link_layer_packets as ll
import unittest
import unittest
@@ -17,8 +16,6 @@ class Test(ControllerTest):
    # LL/DDI/ADV/BV-21-C [Extended Advertising, Legacy PDUs, Non-Connectable]
    # LL/DDI/ADV/BV-21-C [Extended Advertising, Legacy PDUs, Non-Connectable]
    async def test(self):
    async def test(self):
        controller = self.controller
        controller = self.controller
        public_peer_address = Address('aa:bb:cc:dd:ee:ff')
        connection_handle = 0xefe


        # 1. Configure Lower Tester to monitor advertising packets from the IUT.
        # 1. Configure Lower Tester to monitor advertising packets from the IUT.
        # 2. The Upper Tester sends an HCI_LE_Set_Extended_Advertising_Parameters command to the
        # 2. The Upper Tester sends an HCI_LE_Set_Extended_Advertising_Parameters command to the
@@ -72,7 +69,7 @@ class Test(ControllerTest):
        # first packet.
        # first packet.
        # 7. Repeat steps 5–6 until a number of advertising intervals (50) have been detected.
        # 7. Repeat steps 5–6 until a number of advertising intervals (50) have been detected.
        for n in range(3):
        for n in range(3):
            self.expect_ll(
            await self.expect_ll(
                ll.LeLegacyAdvertisingPdu(source_address=controller.address,
                ll.LeLegacyAdvertisingPdu(source_address=controller.address,
                                          advertising_address_type=ll.AddressType.PUBLIC,
                                          advertising_address_type=ll.AddressType.PUBLIC,
                                          advertising_type=ll.LegacyAdvertisingType.ADV_NONCONN_IND,
                                          advertising_type=ll.LegacyAdvertisingType.ADV_NONCONN_IND,
+83 −0
Original line number Original line Diff line number Diff line
import lib_rootcanal_python3 as rootcanal
import hci_packets as hci
import link_layer_packets as ll
import unittest
from typing import List
from hci_packets import ErrorCode
from py.bluetooth import Address
from py.controller import ControllerTest


class Test(ControllerTest):
    # Test parameters.
    LL_advertiser_advInterval_MIN = 0x200
    LL_advertiser_advInterval_MAX = 0x200
    LL_advertiser_Adv_Channel_Map = 0x7

    # LL/DDI/ADV/BV-22-C [Extended Advertising, Legacy PDUs, Undirected, CSA #2]
    async def test(self):
        controller = self.controller

        # 1. Configure Lower Tester to monitor advertising packets from the IUT.
        # 2. The Upper Tester sends an HCI_LE_Set_Extended_Advertising_Parameters command to the
        # IUT using all supported advertising channels and minimum advertising interval. The
        # Advertising_Event_Properties parameter shall be set to 00010011b (ADV_IND legacy PDU).
        controller.send_cmd(
            hci.LeSetExtendedAdvertisingParametersLegacy(
                advertising_handle=0,
                legacy_advertising_event_properties=hci.LegacyAdvertisingEventProperties.ADV_IND,
                primary_advertising_interval_min=self.LL_advertiser_advInterval_MIN,
                primary_advertising_interval_max=self.LL_advertiser_advInterval_MAX,
                primary_advertising_channel_map=self.LL_advertiser_Adv_Channel_Map,
                own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS,
                advertising_filter_policy=hci.AdvertisingFilterPolicy.ALL_DEVICES))

        await self.expect_evt(
            hci.LeSetExtendedAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))

        # 8. Repeat steps 3–7 for each Round shown in Table 4.4.
        await self.steps_3_7(advertising_data=[1])
        await self.steps_3_7(advertising_data=[])
        await self.steps_3_7(advertising_data=[0xf8] + [0] * 30)

    async def steps_3_7(self, advertising_data: List[int]):
        controller = self.controller

        # 3. Upper Tester sends an HCI_LE_Set_Extended_Advertising_Data command to the IUT with
        # values according to Table 4.4 and receives an HCI_Command_Complete in response.
        controller.send_cmd(
            hci.LeSetExtendedAdvertisingDataRaw(advertising_handle=0,
                                                operation=hci.Operation.COMPLETE_ADVERTISEMENT,
                                                advertising_data=advertising_data))

        await self.expect_evt(
            hci.LeSetExtendedAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))

        # 4. Upper Tester sends an HCI_LE_Set_Extended_Advertising_Enable command to the IUT to
        # enable advertising with Duration[0] set to 0x0000 (continue advertising until disabled), and
        # receives an HCI_Command_Complete event in response.
        controller.send_cmd(
            hci.LeSetExtendedAdvertisingEnable(
                enable=hci.Enable.ENABLED,
                enabled_sets=[hci.EnabledSet(advertising_handle=0, duration=0, max_extended_advertising_events=0)]))

        await self.expect_evt(
            hci.LeSetExtendedAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))

        # 5. Lower Tester scans on a single primary advertising channel as indicated in Table 4.4 and expects
        # the IUT to send ADV_IND packets, with ChSel set as specified in Table 4.3, including the data
        # submitted in step 3 starting an event on the applicable primary advertising channel.
        # 6. Repeat step 5 until a number of advertising intervals (50) have been detected.
        for n in range(3):
            await self.expect_ll(
                ll.LeLegacyAdvertisingPdu(source_address=controller.address,
                                          advertising_address_type=ll.AddressType.PUBLIC,
                                          advertising_type=ll.LegacyAdvertisingType.ADV_IND,
                                          advertising_data=advertising_data))

        # 7. Upper Tester sends an HCI_LE_Set_Extended_Advertising_Enable command to the IUT to
        # disable advertising function and receives an HCI_Command_Complete event in response.
        controller.send_cmd(hci.LeSetExtendedAdvertisingEnable(enable=hci.Enable.DISABLED, enabled_sets=[]))

        await self.expect_evt(
            hci.LeSetExtendedAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
Loading