diff options
| author | 2023-04-10 09:09:53 -0700 | |
|---|---|---|
| committer | 2023-04-13 20:56:15 +0000 | |
| commit | ba5bbf613efdc36f342a32465a1e030445154b13 (patch) | |
| tree | d7e65d3fd6a2cce49059cec7fea86d199267e283 | |
| parent | 31285e07cc0efb67786772b0187159fdf5cd73ca (diff) | |
RootCanal: Implement LL tests for LE periodic advertising
Added tests:
- LL/DDI/ADV/BV-26-C
- LL/DDI/SCN/BV-79-C
Fixed test:
- LL/DDI/ADV/BV-06-C
(broken after HCI disconnection code fixup patch)
Enabled test:
- LL/DDI/ADV/BV-20-C
(enabled by implementation of HCI LE Set Default Phy)
Bug: 275847929
Test: atest --host rootcanal_ll_test
Change-Id: Icde224c36b2b554dc3e28e521c716dc2eef617df
| -rw-r--r-- | tools/rootcanal/py/controller.py | 40 | ||||
| -rw-r--r-- | tools/rootcanal/test/LL/DDI/ADV/BV_06_C.py | 2 | ||||
| -rw-r--r-- | tools/rootcanal/test/LL/DDI/ADV/BV_26_C.py | 224 | ||||
| -rw-r--r-- | tools/rootcanal/test/LL/DDI/SCN/BV_79_C.py | 188 | ||||
| -rw-r--r-- | tools/rootcanal/test/main.py | 5 |
5 files changed, 441 insertions, 18 deletions
diff --git a/tools/rootcanal/py/controller.py b/tools/rootcanal/py/controller.py index 99e93a4221..cc0dbe2360 100644 --- a/tools/rootcanal/py/controller.py +++ b/tools/rootcanal/py/controller.py @@ -38,6 +38,7 @@ class LeFeatures: self.mask = le_features self.ll_privacy = (le_features & hci.LLFeaturesBits.LL_PRIVACY) != 0 self.le_extended_advertising = (le_features & hci.LLFeaturesBits.LE_EXTENDED_ADVERTISING) != 0 + self.le_periodic_advertising = (le_features & hci.LLFeaturesBits.LE_PERIODIC_ADVERTISING) != 0 def generate_rpa(irk: bytes) -> hci.Address: @@ -223,24 +224,33 @@ class ControllerTest(unittest.IsolatedAsyncioTestCase): assert evt.num_hci_command_packets == 1 return evt - async def expect_ll(self, expected_pdu: typing.Union[ll.LinkLayerPacket, type], timeout: int = 3): + async def expect_ll(self, + expected_pdus: typing.Union[list, typing.Union[ll.LinkLayerPacket, type]], + timeout: int = 3) -> int: + if not isinstance(expected_pdus, list): + expected_pdus = [expected_pdus] + packet = await asyncio.wait_for(self.controller.receive_ll(), timeout=timeout) pdu = ll.LinkLayerPacket.parse_all(packet) - if isinstance(expected_pdu, type) and not isinstance(pdu, expected_pdu): - print("received pdu of unexpected type") - print(f"expected pdu: {expected_pdu.__name__}") - print("received pdu:") - pdu.show() - self.assertTrue(False) - - if isinstance(expected_pdu, ll.LinkLayerPacket) and pdu != expected_pdu: - print("received unexpected pdu") - print("expected pdu:") - expected_pdu.show() - print("received pdu:") - pdu.show() - self.assertTrue(False) + matched_index = -1 + for (index, expected_pdu) in enumerate(expected_pdus): + if isinstance(expected_pdu, type) and isinstance(pdu, expected_pdu): + return index + if isinstance(expected_pdu, ll.LinkLayerPacket) and pdu == expected_pdu: + return index + + print("received unexpected pdu:") + pdu.show() + print("expected pdus:") + for expected_pdu in expected_pdus: + if isinstance(expected_pdu, type): + print(f"- {expected_pdu.__name__}") + if isinstance(expected_pdu, ll.LinkLayerPacket): + print(f"- {expected_pdu.__class__.__name__}") + expected_pdu.show() + + self.assertTrue(False) def tearDown(self): self.controller.stop() diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_06_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_06_C.py index 6c078af77c..38acd5bea8 100644 --- a/tools/rootcanal/test/LL/DDI/ADV/BV_06_C.py +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_06_C.py @@ -104,7 +104,7 @@ class Test(ControllerTest): await self.expect_evt( hci.DisconnectionComplete(status=ErrorCode.SUCCESS, connection_handle=connection_handle, - reason=hci.DisconnectReason.REMOTE_USER_TERMINATED_CONNECTION)) + reason=hci.ErrorCode.CONNECTION_TERMINATED_BY_LOCAL_HOST)) # 9. Configure Lower Tester to use a public device address that differs from the IUT address in the # most significant octet as parameter of CONNECT_IND. diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_26_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_26_C.py new file mode 100644 index 0000000000..f3b1365ed9 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_26_C.py @@ -0,0 +1,224 @@ +import asyncio +import hci_packets as hci +import link_layer_packets as ll +import math +import random +import unittest +from dataclasses import dataclass +from hci_packets import ErrorCode, FragmentPreference +from py.bluetooth import Address +from py.controller import ControllerTest +from typing import List + + +@dataclass +class TestRound: + data_length: int + + +class Test(ControllerTest): + # Test parameters. + LL_advertiser_advInterval_MIN = 0x200 + LL_advertiser_advInterval_MAX = 0x200 + LL_advertiser_Adv_Channel_Map = 0x7 + LL_initiator_connInterval = 0x200 + LL_initiator_connPeripheralLatency = 0x200 + LL_initiator_connSupervisionTimeout = 0x200 + + # LL/DDI/ADV/BV-26-C [Extended Advertising, Periodic Advertising – LE 1M PHY] + async def test(self): + controller = self.controller + + if not controller.le_features.le_periodic_advertising: + self.skipTest("LE periodic advertising not supported") + + # 1. The Upper Tester sends an HCI_LE_Read_Maximum_Advertising_Data_Length command to the + # IUT and receives a Maximum_Advertising_Data_Length between 0x001F and 0x0672 in return. + # The Upper Tester stores the Maximum_Advertising_Data_Length for future use. + # For each round from 1–6 based on Table 4.10. + controller.send_cmd(hci.LeReadMaximumAdvertisingDataLength()) + + event = await self.expect_cmd_complete(hci.LeReadMaximumAdvertisingDataLengthComplete) + maximum_advertising_data_length = event.maximum_advertising_data_length + + # Test rounds. + test_rounds = [ + TestRound(0), + TestRound(252), + TestRound(474), + TestRound(711), + TestRound(948), + TestRound(maximum_advertising_data_length), + ] + + # 17. Repeat steps 2–16 for each Round shown in Table 4.10. + for test_round in test_rounds: + await self.steps_2_16(maximum_advertising_data_length, **vars(test_round)) + + async def steps_2_16(self, maximum_advertising_data_length: int, data_length: int): + controller = self.controller + + # 2. If the Data Length listed in Table 4.10 for the current Round is less than or equal to the + # Maximum_Advertising_Data_Length proceed to step 3, otherwise skip to step 17. + if data_length > maximum_advertising_data_length: + return + + # 3. The Upper Tester sends an HCI_LE_Set_Extended_Advertising_Parameters command to the + # IUT using all supported advertising channels and a selected advertising interval between the + # minimum and maximum advertising intervals supported. Advertising_Event_Properties parameter + # shall be set to 0x0000. The Primary_Advertising_PHY and Secondary_Advertising_PHY shall be + # set to the values specified in Table 4.9. + controller.send_cmd( + hci.LeSetExtendedAdvertisingParameters(advertising_handle=0, + advertising_event_properties=hci.AdvertisingEventProperties(), + 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, + primary_advertising_phy=hci.PrimaryPhyType.LE_1M)) + + await self.expect_evt( + hci.LeSetExtendedAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 4. The Upper Tester sends an HCI_LE_Set_Periodic_Advertising_Parameters command to the IUT + # using all supported advertising channels and selected periodic interval. + # Periodic_Advertising_Properties parameter shall be set to 0x0000. + controller.send_cmd( + hci.LeSetPeriodicAdvertisingParameters(advertising_handle=0, + periodic_advertising_interval_min=0x100, + periodic_advertising_interval_max=0x100, + include_tx_power=False)) + + await self.expect_evt( + hci.LeSetPeriodicAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 5. The Upper Tester sends one or more HCI_LE_Set_Periodic_Advertising_Data commands to the + # IUT with values according to Table 4.10 and using random octets from 1 to 254 as the payload. If + # the Data Length is greater than 252 the Upper Tester shall send multiple commands using one + # Operation 0x01 (First fragment) command, followed by zero or more Operation 0x00 + # (Intermediate Fragment) commands, and a final Operation 0x02 (Last fragment) command. + # Otherwise the Upper Tester shall send a single command using Operation 0x03 (Complete Data). + advertising_data = [random.randint(1, 254) for n in range(data_length)] + num_fragments = math.ceil(data_length / 251) or 1 # Make sure to set the advertising data if it is empty. + for n in range(num_fragments): + fragment_offset = 251 * n + fragment_length = min(251, data_length - fragment_offset) + if num_fragments == 1: + operation = hci.Operation.COMPLETE_ADVERTISEMENT + elif n == 0: + operation = hci.Operation.FIRST_FRAGMENT + elif n == num_fragments - 1: + operation = hci.Operation.LAST_FRAGMENT + else: + operation = hci.Operation.INTERMEDIATE_FRAGMENT + + controller.send_cmd( + hci.LeSetPeriodicAdvertisingDataRaw(advertising_handle=0, + operation=operation, + advertising_data=advertising_data[fragment_offset:fragment_offset + + fragment_length])) + + await self.expect_evt( + hci.LeSetPeriodicAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 6. The Upper Tester enables periodic advertising using the + # HCI_LE_Set_Periodic_Advertising_Enable command with the Enable parameter set to 0x01 + # (Periodic Advertising). + controller.send_cmd(hci.LeSetPeriodicAdvertisingEnable(enable=True, include_adi=False, advertising_handle=0)) + + await self.expect_evt( + hci.LeSetPeriodicAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # Note: no periodic advertising event is expected until extended + # advertising is also enabled for the advertising set. + + # 7. The Upper Tester enables advertising using the HCI_LE_Set_Extended_Advertising_Enable + # command. The Duration[0] parameter is set to 0x0000 (No Advertising Duration). + 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)) + + # 8. The Lower Tester receives an ADV_EXT_IND packet from the IUT with AdvMode set to 00b with + # the AuxPtr Extended Header field present. + + # 9. The Lower Tester utilizes the AuxPtr field to listen for an AUX_ADV_IND PDU on the secondary + # advertising channel with the AdvMode field set to 00b and the SyncInfo Extended Header fields + # present. + + # 10. The Lower Tester utilizes the SyncInfo field to listen for an AUX_SYNC_IND PDU on the + # secondary advertising channel using the index selected by the LE Channel Selection Algorithm + # #2 and synchronizes with the periodic advertisements. The AUX_SYNC_IND PDU shall have the + # AdvMode field set to 00b with no ADI field. If the AUX_SYNC_IND PDU AdvData field does not + # contain all the data submitted in step 5 (if any), it shall include an AuxPtr field. + + # 11. If the AUX_SYNC_IND PDU contains an AuxPtr field, the Lower Tester utilizes it to listen for an + # AUX_CHAIN_IND PDU with the AdvMode field set to 00b and containing additional data + # submitted in step 5. If the AUX_CHAIN_IND PDU contains an AuxPtr field this step is repeated + # until an AUX_CHAIN_IND PDU is received with no AuxPtr field and all data has been received. + + # 12. Repeat steps 8–11 100 times. + received = [0, 0] + for n in range(15): + index = await self.expect_ll([ + ll.LeExtendedAdvertisingPdu(source_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + target_address_type=ll.AddressType.PUBLIC, + connectable=False, + scannable=False, + directed=False, + sid=0, + tx_power=0, + primary_phy=ll.PrimaryPhyType.LE_1M, + secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + periodic_advertising_interval=0x100, + advertising_data=[]), + ll.LePeriodicAdvertisingPdu(source_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + sid=0, + tx_power=0, + advertising_interval=0x100, + advertising_data=advertising_data) + ]) + received[index] = received[index] + 1 + + # Note: the extended advertising interval is twice the periodic + # advertising interval; the number of events received of each kind is + # deterministic. + self.assertTrue(received[0] == 5) + self.assertTrue(received[1] == 10) + + # 13. The Upper Tester disables extended advertising using the + # HCI_LE_Set_Extended_Advertising_Enable command but maintains periodic advertising. + 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)) + + # 14. The Lower Tester confirms that periodic advertising continues when extended advertising is + # disabled by repeating steps 10–11 100 times. + for n in range(10): + await self.expect_ll( + ll.LePeriodicAdvertisingPdu(source_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + sid=0, + tx_power=0, + advertising_interval=0x100, + advertising_data=advertising_data)) + + # 15. The Upper Tester disables periodic advertising using the + # HCI_LE_Set_Periodic_Advertising_Enable command. + controller.send_cmd(hci.LeSetPeriodicAdvertisingEnable(enable=False, include_adi=False, advertising_handle=0)) + + await self.expect_evt( + hci.LeSetPeriodicAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 16. The Upper Tester clears the advertising configuration using the HCI_LE_Clear_Advertising_Sets + # command. + controller.send_cmd(hci.LeClearAdvertisingSets()) + + await self.expect_evt(hci.LeClearAdvertisingSetsComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/SCN/BV_79_C.py b/tools/rootcanal/test/LL/DDI/SCN/BV_79_C.py new file mode 100644 index 0000000000..ff2ccba5d7 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/SCN/BV_79_C.py @@ -0,0 +1,188 @@ +import hci_packets as hci +import link_layer_packets as ll +import math +import random +from dataclasses import dataclass +from hci_packets import ErrorCode +from py.bluetooth import Address +from py.controller import ControllerTest +from typing import Optional + +ADV_IND = 0x13 +ADV_DIRECT_IND = 0x15 +ADV_SCAN_IND = 0x12 +ADV_NONCONN_IND = 0x10 +ADV_EXT_IND = 0x0 + + +class Test(ControllerTest): + + # LL/DDI/SCN/BV-79-C [Extended Scanning, Passive, Periodic Advertising Report, + # RSSI and TX_Power – LE 1M PHY] + async def test(self): + # Test rounds. + # Note: some tests are skipped as no distinction is made between + # ADV_EXT_IND, AUX_ADV_IND, AUX_CHAIN_IND. + controller = self.controller + lower_tester_address = Address('11:22:33:44:55:66') + advertising_sid = 0x3 + tx_power = 0x0a + periodic_advertising_interval = 0x100 + + # 1. The Upper Tester sends an HCI_LE_Set_Extended_Scan_Parameters command to the IUT with + # Scanning_PHYs set as specified in Table 4.35, Scan_Type[0] set to 0x00 (Passive Scanning), + # Scan_Interval[0] set to 0x0010, Scan_Window[0] set to 0x0010, Own_Address_Type set to 0x00 + # (Public Device Address), and Scanning_Filter_Policy shall be set to 0x00 (Accept All) and + # receives a successful HCI_Command_Complete event in return. + controller.send_cmd( + hci.LeSetExtendedScanParameters(own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + scanning_filter_policy=hci.LeScanningFilterPolicy.ACCEPT_ALL, + scanning_phys=0x1, + parameters=[ + hci.PhyScanParameters(le_scan_type=hci.LeScanType.PASSIVE, + le_scan_interval=0x0010, + le_scan_window=0x0010) + ])) + + await self.expect_evt( + hci.LeSetExtendedScanParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 2. The Upper Tester sends an HCI_LE_Set_Extended_Scan_Enable command to the IUT to enable + # scanning with Filter_Duplicates, Duration, and Period are set to zero and receives a successful + # HCI_Command_Complete event in return. + controller.send_cmd( + hci.LeSetExtendedScanEnable(enable=hci.Enable.ENABLED, + filter_duplicates=hci.Enable.DISABLED, + duration=0, + period=0)) + + await self.expect_evt(hci.LeSetExtendedScanEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + for n in range(3): + # 3. The Lower Tester begins advertising using ADV_EXT_IND and AUX_ADV_IND PDUs. The + # ADV_EXT_IND PDUs include an AuxPtr that refers to the AUX_ADV_IND PDU on the secondary + # advertising channel. The AUX_ADV_IND PDUs include the AdvA field containing the Lower + # Tester address, and the SyncInfo field referring to the AUX_SYNC_IND PDU. The Lower Tester + # continues advertising until directed to stop in the test procedure. + controller.send_ll(ll.LeExtendedAdvertisingPdu(source_address=lower_tester_address, + advertising_address_type=ll.AddressType.PUBLIC, + connectable=False, + scannable=False, + directed=False, + sid=advertising_sid, + tx_power=tx_power, + primary_phy=ll.PrimaryPhyType.LE_1M, + secondary_phy=ll.SecondaryPhyType.NO_PACKETS, + periodic_advertising_interval=0x100, + advertising_data=[]), + rssi=0x10) + + # 4. The IUT sends an HCI_LE_Extended_Advertising_Report event to the Upper Tester containing a + # nonzero Periodic_Advertising_Interval, Data Status in the Event_Type[i] field set to the value + # 0b00 (Complete), and RSSI[i] set to a valid value. + await self.expect_evt( + hci.LeExtendedAdvertisingReportRaw(responses=[ + hci.LeExtendedAdvertisingResponseRaw( + connectable=False, + scannable=False, + directed=False, + scan_response=False, + legacy=False, + data_status=hci.DataStatus.COMPLETE, + address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, + address=lower_tester_address, + primary_phy=hci.PrimaryPhyType.LE_1M, + secondary_phy=hci.SecondaryPhyType.NO_PACKETS, + advertising_sid=advertising_sid, + tx_power=tx_power, + rssi=0x10, + periodic_advertising_interval=periodic_advertising_interval, + direct_address_type=hci.DirectAdvertisingAddressType.NO_ADDRESS_PROVIDED, + direct_address=Address(), + advertising_data=[]) + ])) + + # 5. The Upper Tester sends an HCI_LE_Periodic_Advertising_Create_Sync command to the IUT to + # synchronize with the Lower Tester’s periodic advertisements with Options set to 0x00 (Do not + # Use List), Advertising_SID set to the Advertising_SID from step 3, Advertiser_Address_Type set + # to 0x00 (Public Device Address), Advertiser_Address set to the Lower Tester’s address, Skip set + # to the value 0x0003, Sync_Timeout set to (Skip + 3) x Periodic_Advertising_Interval from step 4, + # and Sync_CTE_Type set to 0x00 and receives a successful HCI_Command_Complete event in + # return. + controller.send_cmd( + hci.LePeriodicAdvertisingCreateSync( + options=hci.PeriodicAdvertisingOptions(use_periodic_advertiser_list=False, + disable_reporting=False, + enable_duplicate_filtering=False), + advertising_sid=advertising_sid, + advertiser_address_type=hci.AdvertiserAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS, + advertiser_address=lower_tester_address, + skip=0x3, + sync_timeout=6 * periodic_advertising_interval, + sync_cte_type=0)) + + await self.expect_evt( + hci.LePeriodicAdvertisingCreateSyncStatus(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 6. The Lower Tester generates an AUX_SYNC_IND PDU on the secondary advertising channel with + # AuxPtr set to a value referring to the first AUX_CHAIN_IND PDU in the train, TxPower set to 10, + # and AdvData set to N octets of random data. + controller.send_ll( + ll.LePeriodicAdvertisingPdu(source_address=lower_tester_address, + advertising_address_type=ll.AddressType.PUBLIC, + sid=advertising_sid, + tx_power=tx_power, + advertising_interval=periodic_advertising_interval, + advertising_data=[])) + + # 7. The IUT sends a successful HCI_LE_Periodic_Advertising_Sync_Established event to the Upper + # Tester containing a Status of 0x00 (Success), Sync_Handle set to a valid value, and the + # Advertising_SID received in step 3. + await self.expect_evt( + hci.LePeriodicAdvertisingSyncEstablished( + status=ErrorCode.SUCCESS, + sync_handle=0, + advertising_sid=advertising_sid, + advertiser_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, + advertiser_address=lower_tester_address, + advertiser_phy=hci.SecondaryPhyType.LE_1M, + periodic_advertising_interval=periodic_advertising_interval, + advertiser_clock_accuracy=hci.ClockAccuracy.PPM_500, + )) + + for n in range(3): + advertising_data_length = 256 + advertising_data = [random.randint(1, 254) for n in range(advertising_data_length)] + + # 8. The Lower Tester sends two AUX_CHAIN_IND PDUs to the IUT with AdvData set to min(249, + # (Scan_Max_Data – N) / 2) octets of random data for each AUX_CHAIN_IND PDU and the + # TxPower value of the AUX_CHAIN_IND PDUs set to 15. The PDUs should be sent as far apart + # as practical. + controller.send_ll(ll.LePeriodicAdvertisingPdu(source_address=lower_tester_address, + advertising_address_type=ll.AddressType.PUBLIC, + sid=advertising_sid, + tx_power=tx_power, + advertising_interval=periodic_advertising_interval, + advertising_data=advertising_data), + rssi=0x10) + + # 9. The IUT sends multiple HCI_LE_Periodic_Advertising_Report events to the Upper Tester with + # Data Status in the Event_Type[i] field set to 0b01 (Incomplete, more data to come), TX_Power[i] + # set to the value of the TxPower field for the AUX_SYNC_IND received in step 6, and RSSI[i] set + # to a valid value. Subsequent reports with data and the status set to “Incomplete, more data to + # come” or “complete” can have the TX_Power field set to 0x7F. + offset = 0 + max_fragment_length = 247 + num_fragments = math.ceil(advertising_data_length / max_fragment_length) or 1 + for n in range(num_fragments): + remaining_length = advertising_data_length - offset + fragment_length = min(max_fragment_length, remaining_length) + data_status = hci.DataStatus.CONTINUING if remaining_length > max_fragment_length else hci.DataStatus.COMPLETE + await self.expect_evt( + hci.LePeriodicAdvertisingReport(sync_handle=0, + tx_power=tx_power, + rssi=0x10, + cte_type=hci.CteType.NO_CONSTANT_TONE_EXTENSION, + data_status=data_status, + data=advertising_data[offset:offset + fragment_length])) + offset += fragment_length diff --git a/tools/rootcanal/test/main.py b/tools/rootcanal/test/main.py index d3062cd136..aefd3d4972 100644 --- a/tools/rootcanal/test/main.py +++ b/tools/rootcanal/test/main.py @@ -21,15 +21,16 @@ tests = [ 'LL.DDI.ADV.BV_17_C', 'LL.DDI.ADV.BV_18_C', 'LL.DDI.ADV.BV_19_C', - # TODO: Implement HCI command Le Set Default Phy - # 'LL.DDI.ADV.BV_20_C', + 'LL.DDI.ADV.BV_20_C', 'LL.DDI.ADV.BV_21_C', 'LL.DDI.ADV.BV_22_C', + 'LL.DDI.ADV.BV_26_C', 'LL.DDI.ADV.BV_47_C', 'LL.DDI.SCN.BV_13_C', 'LL.DDI.SCN.BV_14_C', 'LL.DDI.SCN.BV_18_C', 'LL.DDI.SCN.BV_19_C', + 'LL.DDI.SCN.BV_79_C', ] if __name__ == "__main__": |