From 4f1cc97f2e0d307c2b0a455d1f47030cd2f5b9d2 Mon Sep 17 00:00:00 2001 From: Henri Chataing <henrichataing@google.com> Date: Tue, 10 Jan 2023 10:21:52 +0000 Subject: [PATCH] RootCanal: Implement additional LL advertising tests - LL/DDI/ADV/BV-15-C - LL/DDI/ADV/BV-16-C - LL/DDI/ADV/BV-17-C - LL/DDI/ADV/BV-18-C - LL/DDI/ADV/BV-19-C - LL/DDI/ADV/BV-20-C - LL/DDI/ADV/BV-21-C Bug: 253523072 Test: atest rootcanal_ll_test Change-Id: Id447dd5acf84cc2895ae2825cfa63e6db1f59e62 --- tools/rootcanal/test/LL/DDI/ADV/BV_15_C.py | 59 ++++++ tools/rootcanal/test/LL/DDI/ADV/BV_16_C.py | 139 +++++++++++++ tools/rootcanal/test/LL/DDI/ADV/BV_17_C.py | 147 ++++++++++++++ tools/rootcanal/test/LL/DDI/ADV/BV_18_C.py | 221 +++++++++++++++++++++ tools/rootcanal/test/LL/DDI/ADV/BV_19_C.py | 117 +++++++++++ tools/rootcanal/test/LL/DDI/ADV/BV_20_C.py | 70 +++++++ tools/rootcanal/test/LL/DDI/ADV/BV_21_C.py | 86 ++++++++ tools/rootcanal/test/main.py | 8 + 8 files changed, 847 insertions(+) create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_15_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_16_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_17_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_18_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_19_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_20_C.py create mode 100644 tools/rootcanal/test/LL/DDI/ADV/BV_21_C.py diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_15_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_15_C.py new file mode 100644 index 00000000000..70a7a24c45b --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_15_C.py @@ -0,0 +1,59 @@ +import lib_rootcanal_python3 as rootcanal +import hci_packets as hci +import link_layer_packets as ll +import unittest +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-15-C [Discoverable Advertising Events] + async def test(self): + controller = self.controller + + # 1. Configure Lower Tester to monitor advertising packets from the IUT. + # 2. Upper Tester enables discoverable undirected advertising in the IUT using a selected advertising + # channel and a selected advertising interval between the minimum and maximum advertising. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingData(advertising_data=[])) + + await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 3. Lower Tester expects the IUT to send ADV_SCAN_IND packets starting an event on the selected + # advertising channel. + # 4. Expect the next event to start after advertising interval time calculated from the start of the first + # packet. + # 5. Repeat steps 3–4 until a number of advertising intervals (100) 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_SCAN_IND, + advertising_data=[]), + timeout=5) + + # 6. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to disable advertising in the + # IUT and receives an HCI_Command_Complete event from the IUT. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_16_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_16_C.py new file mode 100644 index 00000000000..b444112c831 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_16_C.py @@ -0,0 +1,139 @@ +import lib_rootcanal_python3 as rootcanal +import hci_packets as hci +import link_layer_packets as ll +import unittest +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-16-C [Advertising Data: Discoverable] + async def test(self): + controller = self.controller + + # 1. Upper Tester enables discoverable undirected advertising in the IUT using a selected advertising + # channel and a selected advertising interval between the minimum and maximum advertising + # intervals. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 2. Upper Tester sends an HCI_LE_Set_Advertising_Data command to the IUT and receives an + # HCI_Command_Complete in response. The data element used in the command is a number + # indicating the length of the data. The data length is 1 byte. + advertising_data = [1] + controller.send_cmd(hci.LeSetAdvertisingDataRaw(advertising_data=advertising_data)) + + await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 3. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to the IUT to enable + # advertising and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 4. Lower Tester expects the IUT to send ADV_SCAN_IND packets including the data submitted in + # step 3 starting an event on the selected advertising channel. + # 5. Expect the following event to start after advertising interval time calculating from the start of the + # first packet. + # 6. Repeat steps 5–6 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_SCAN_IND, + advertising_data=advertising_data), + timeout=5) + + # 7. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to the IUT to disable + # advertising function and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 8. Upper Tester sends an HCI_LE_Set_Advertising_Data to configure the IUT to send advertising + # packets without advertising data and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingData(advertising_data=[])) + + await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 9. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to the IUT to enable + # advertising and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 10. Lower Tester expects the IUT to send ADV_SCAN_IND packets including no advertising data + # starting an event on the selected advertising channel. + # 11. Expect the next event to start after advertising interval time calculating from the start of the first + # packet. + # 12. Repeat steps 11–12 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_SCAN_IND, + advertising_data=[]), + timeout=5) + + # 13. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to the IUT to disable + # advertising and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 14. Upper Tester sends an HCI_LE_Set_Advertising_Data command to the IUT and receives an + # HCI_Command_Complete in response. The data element is a number indicating the length of the + # data field in the first octet encoded unsigned least significant bit first and the rest of the octets + # zeroes. The data length is 31 bytes. + advertising_data = [31] + [0] * 30 + controller.send_cmd(hci.LeSetAdvertisingDataRaw(advertising_data=advertising_data)) + + await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 15. Repeat steps 4–14. + 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_SCAN_IND, + advertising_data=advertising_data), + timeout=5) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingData(advertising_data=[])) + + await self.expect_evt(hci.LeSetAdvertisingDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + 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_SCAN_IND, + advertising_data=[]), + timeout=5) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_17_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_17_C.py new file mode 100644 index 00000000000..efdc1a2ca40 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_17_C.py @@ -0,0 +1,147 @@ +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-17-C [Scan Request: Discoverable] + async def test(self): + controller = self.controller + + # 1. Upper Tester enables discoverable undirected advertising in the IUT using all supported + # advertising channels and a selected advertising interval between the minimum and maximum + # advertising. + controller.send_cmd( + hci.LeSetAdvertisingParameters(advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.ALL_DEVICES)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 2. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT. The + # Lower Tester will send an SCAN_REQ packet on a selected supported advertising channel + # (defined as an IXIT) and using a common public device address as parameter. + peer_address = Address('aa:bb:cc:dd:ee:ff') + + # 3. Configure Scan Response Data in the IUT using device name length of 0 as response data. + scan_response_data = [] + controller.send_cmd(hci.LeSetScanResponseDataRaw(advertising_data=scan_response_data)) + + await self.expect_evt(hci.LeSetScanResponseDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 4. Lower Tester sends a SCAN_REQ packet on the selected advertising channel after receiving an + # ADV_SCAN_IND packet from IUT on the advertising channel configured in step 3. The + # SCAN_REQ is sent T_IFS after the end of an ADV_SCAN_IND packet. + # 5. Lower Tester receives a SCAN_RSP packet from the IUT addressed to the Lower Tester T_IFS + # after the end of the request packet. + # 6. Repeat steps 4–5 30 times. + await self.steps_4_6(peer_address=peer_address, scan_response_data=scan_response_data) + + # 7. Configure Scan Response Data in the IUT using device name length of 31 as response data. + scan_response_data = [31] + [0] * 31 + controller.send_cmd(hci.LeSetScanResponseDataRaw(advertising_data=scan_response_data)) + + await self.expect_evt(hci.LeSetScanResponseDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 8. Repeat steps 4–6. + await self.steps_4_6(peer_address=peer_address, scan_response_data=scan_response_data) + + # 9. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT. The + # Lower Tester will send an SCAN_REQ packet on a selected supported advertising channel + # (defined as an IXIT) and using a public device address that differs from the IUT address in the + # most significant octet as parameter. + peer_address = Address([ + controller.address.address[0] ^ 0xff, controller.address.address[1], controller.address.address[2], + controller.address.address[3], controller.address.address[4], controller.address.address[5] + ]) + + # 10. Configure Scan Response Data in the IUT using device name length of 0 as response data. + scan_response_data = [] + controller.send_cmd(hci.LeSetScanResponseDataRaw(advertising_data=scan_response_data)) + + await self.expect_evt(hci.LeSetScanResponseDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 11. Repeat steps 4–6. + await self.steps_4_6(peer_address=peer_address, scan_response_data=scan_response_data) + + # 12. Configure Scan Response Data in the IUT using device name length of 31 as response data. + scan_response_data = [31] + [0] * 31 + controller.send_cmd(hci.LeSetScanResponseDataRaw(advertising_data=scan_response_data)) + + await self.expect_evt(hci.LeSetScanResponseDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 13. Repeat steps 4–6. + await self.steps_4_6(peer_address=peer_address, scan_response_data=scan_response_data) + + # Note: this last iteration is very redundant, not implementing it + # to save on execution time. + + # 14. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT. The + # Lower Tester will send an SCAN_REQ packet on a selected supported advertising channel + # (defined as an IXIT) and using a public device address with address that differs from the IUT + # address in the most and least significant octets as parameter. + + # 15. Configure Scan Response Data in the IUT using device name length of 0 as response data. + # 16. Repeat steps 4–6. + + async def steps_4_6(self, peer_address: Address, scan_response_data: List[int]): + controller = self.controller + + # 4. Lower Tester sends a SCAN_REQ packet on the selected advertising channel after receiving an + # ADV_SCAN_IND packet from IUT on the advertising channel configured in step 3. The + # SCAN_REQ is sent T_IFS after the end of an ADV_SCAN_IND packet. + # 5. Lower Tester receives a SCAN_RSP packet from the IUT addressed to the Lower Tester T_IFS + # after the end of the request packet. + # 6. Repeat steps 4–5 30 times. + 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_SCAN_IND, + advertising_data=[]), + timeout=5) + + controller.send_ll( + ll.LeScan(source_address=peer_address, + destination_address=controller.address, + scanning_address_type=ll.AddressType.PUBLIC, + advertising_address_type=ll.AddressType.PUBLIC)) + + await self.expect_ll(ll.LeScanResponse(source_address=controller.address, + destination_address=peer_address, + advertising_address_type=ll.AddressType.PUBLIC, + scan_response_data=scan_response_data), + timeout=5) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_18_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_18_C.py new file mode 100644 index 00000000000..be17243f92e --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_18_C.py @@ -0,0 +1,221 @@ +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-18-C [Device Filtering: Discoverable] + async def test(self): + controller = self.controller + public_peer_address = Address('aa:bb:cc:dd:ee:ff') + random_peer_address = Address('00:bb:cc:dd:ee:ff') + + # Test preparation. + controller.send_cmd( + hci.LeAddDeviceToFilterAcceptList(address=public_peer_address, + address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS)) + + await self.expect_evt( + hci.LeAddDeviceToFilterAcceptListComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd( + hci.LeAddDeviceToFilterAcceptList(address=random_peer_address, + address_type=hci.AddressType.RANDOM_DEVICE_ADDRESS)) + + await self.expect_evt( + hci.LeAddDeviceToFilterAcceptListComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 1. Upper Tester enables discoverable undirected advertising in the IUT, all supported advertising + # channels, an advertising interval between the minimum and maximum advertising intervals and + # filtering policy set to ‘Allow Scan Request from Filter Accept List, Allow Connect Request from + # Filter Accept List (0x03)’. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + scan_response_data = [ord('I'), ord('U'), ord('T')] + controller.send_cmd(hci.LeSetScanResponseDataRaw(advertising_data=scan_response_data)) + + await self.expect_evt(hci.LeSetScanResponseDataComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 2. Lower Tester address type is set to Public Address Type. + await self.steps_3_12(peer_address=public_peer_address, + peer_address_type=ll.AddressType.PUBLIC, + scan_response_data=scan_response_data) + + # 13. Upper Tester enables discoverable undirected advertising in the IUT using public address type, + # all supported advertising channels, an advertising interval between the minimum and maximum + # advertising intervals and filtering policy set to ‘Allow Scan Request from Filter Accept List, Allow + # Connect Request from Filter Accept List (0x03)’. + # 14. Lower Tester address type is set to Random Address Type. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 15. Repeat steps 3–12. + await self.steps_3_12(peer_address=random_peer_address, + peer_address_type=ll.AddressType.RANDOM, + scan_response_data=scan_response_data) + + # 16. Upper Tester enables discoverable undirected advertising in the IUT using public address type, + # all supported advertising channels, an advertising interval between the minimum and maximum + # advertising intervals and filtering policy set to ‘Allow Scan Request from Filter Accept List, Allow + # Connect Request from Any (0x01)’. + controller.send_cmd( + hci.LeSetAdvertisingParameters(advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 17. Lower Tester address type is set to Public Address Type. + # 18. Repeat steps 3–12. + await self.steps_3_12(peer_address=public_peer_address, + peer_address_type=ll.AddressType.PUBLIC, + scan_response_data=scan_response_data) + + # 19. Upper Tester enables discoverable undirected advertising in the IUT using public address type, + # all supported advertising channels, an advertising interval between the minimum and maximum + # advertising intervals and filtering policy set to ‘Allow Scan Request from Filter Accept List, Allow + # Connect Request from Any (0x01)’. + controller.send_cmd( + hci.LeSetAdvertisingParameters(advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_SCAN_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 20. Lower Tester address type is set to Random Address Type. + # 21. Repeat steps 3–12. + await self.steps_3_12(peer_address=random_peer_address, + peer_address_type=ll.AddressType.RANDOM, + scan_response_data=scan_response_data) + + async def steps_3_12(self, peer_address: Address, peer_address_type: ll.AddressType, scan_response_data: List[int]): + # 3. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT and + # send an SCAN_REQ packet on the selected supported advertising channel (defined as an IXIT) + # with an address that differs from the IUT address in the least significant octet. + controller = self.controller + invalid_peer_address = Address([ + peer_address.address[0] ^ 0xff, peer_address.address[1], peer_address.address[2], peer_address.address[3], + peer_address.address[4], peer_address.address[5] + ]) + invalid_peer_address_type = (ll.AddressType.PUBLIC + if peer_address_type == ll.AddressType.RANDOM else ll.AddressType.RANDOM) + + # 4. Lower Tester receives an ADV_SCAN_IND packet from the IUT and responds with an + # SCAN_REQ packet with the selected address on the selected advertising channel T_IFS after the + # end of an advertising packet. + # 5. Lower Tester receives no response from the IUT. + # 6. Repeat steps 4–5 30 times. + 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_SCAN_IND, + advertising_data=[])) + + controller.send_ll(ll.LeScan(source_address=invalid_peer_address, + destination_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + scanning_address_type=peer_address_type), + rssi=0xf0) + + # 7. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT and + # send a SCAN_REQ packet on the selected supported advertising channel (defined as an IXIT) + # with an address in the Filter Accept List in the policy applied and an incorrect address type. + # 8. Repeat steps 4–6 30 times. + 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_SCAN_IND, + advertising_data=[])) + + controller.send_ll(ll.LeScan(source_address=peer_address, + destination_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + scanning_address_type=invalid_peer_address_type), + rssi=0xf0) + + # 9. Configure Lower Tester to monitor the advertising and scan response procedures of the IUT and + # send a SCAN_REQ packet on the selected supported advertising channel (defined as an IXIT) + # with an address in the Filter Accept List in the policy applied and correct address type. + # 10. Lower Tester receives an ADV_SCAN_IND packet from the IUT and responds with a + # SCAN_REQ packet with an address in the Filter Accept List in the policy applied using correct + # address type, on the selected advertising channel T_IFS after the end of an advertising packet. + await self.expect_ll( + ll.LeLegacyAdvertisingPdu(source_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + advertising_type=ll.LegacyAdvertisingType.ADV_SCAN_IND, + advertising_data=[])) + + controller.send_ll(ll.LeScan(source_address=peer_address, + destination_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + scanning_address_type=peer_address_type), + rssi=0xf0) + + # 11. Lower Tester receives a SCAN_RSP packet from the IUT addressed to the Lower Tester T_IFS + # after the end of the request packet. + await self.expect_ll( + ll.LeScanResponse(source_address=controller.address, + destination_address=peer_address, + advertising_address_type=ll.AddressType.PUBLIC, + scan_response_data=scan_response_data)) + + # 12. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to the IUT to disable + # advertising and receives an HCI_Command_Complete event in response. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_19_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_19_C.py new file mode 100644 index 00000000000..ba7dbeccd8e --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_19_C.py @@ -0,0 +1,117 @@ +import lib_rootcanal_python3 as rootcanal +import hci_packets as hci +import link_layer_packets as ll +import unittest +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_initiator_connInterval = 0x200 + LL_initiator_connPeripheralLatency = 0x200 + LL_initiator_connSupervisionTimeout = 0x200 + + # LL/DDI/ADV/BV-19-C [Low Duty Cycle Directed Advertising Events] + async def test(self): + controller = self.controller + public_peer_address = Address('aa:bb:cc:dd:ee:ff') + connection_handle = 0xefe + + # 1. Configure Lower Tester to start scanning and monitor advertising packets from the IUT. + # 2. Upper Tester enables low duty cycle directed advertising in the IUT using a selected advertising + # channel and a selected advertising interval between the minimum and maximum advertising. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_DIRECT_IND_LOW, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + peer_address=public_peer_address, + peer_address_type=hci.PeerAddressType.PUBLIC_DEVICE_OR_IDENTITY_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 3. Lower Tester expects the IUT to send ADV_DIRECT_IND packets starting an event on the + # selected advertising channel. + # 4. Expect the next event to start after the advertising interval time calculated from the start of the + # first packet. + # 5. Repeat steps 3–4 until the number of advertising intervals (100) have been detected. + for n in range(3): + await self.expect_ll( + ll.LeLegacyAdvertisingPdu(source_address=controller.address, + destination_address=public_peer_address, + target_address_type=ll.AddressType.PUBLIC, + advertising_address_type=ll.AddressType.PUBLIC, + advertising_type=ll.LegacyAdvertisingType.ADV_DIRECT_IND, + advertising_data=[])) + + # 6. Configure the Lower Tester to initiate a connection. + # 7. Lower Tester receives an ADV_DIRECT_IND packet from the IUT on the selected advertising + # channel (defined as an IXIT), then responds with a CONNECT_IND packet T_IFS after the end of + # the advertising packet and does not send any data packets to the IUT. + await self.expect_ll( + ll.LeLegacyAdvertisingPdu(source_address=controller.address, + destination_address=public_peer_address, + target_address_type=ll.AddressType.PUBLIC, + advertising_address_type=ll.AddressType.PUBLIC, + advertising_type=ll.LegacyAdvertisingType.ADV_DIRECT_IND, + advertising_data=[])) + + controller.send_ll(ll.LeConnect(source_address=public_peer_address, + destination_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + initiating_address_type=ll.AddressType.PUBLIC, + conn_interval=self.LL_initiator_connInterval, + conn_peripheral_latency=self.LL_initiator_connPeripheralLatency, + conn_supervision_timeout=self.LL_initiator_connSupervisionTimeout), + rssi=0xf0) + + # Note: Link layer sends LeConnectComplete here. + await self.expect_ll( + ll.LeConnectComplete(source_address=controller.address, + destination_address=public_peer_address, + initiating_address_type=ll.AddressType.PUBLIC, + advertising_address_type=ll.AddressType.PUBLIC, + conn_interval=self.LL_initiator_connInterval, + conn_peripheral_latency=self.LL_initiator_connPeripheralLatency, + conn_supervision_timeout=self.LL_initiator_connSupervisionTimeout)) + + # 8. Lower Tester receives no ADV_DIRECT_IND packets from the IUT after the advertising interval. + # 9. Repeat steps 7–8 until the IUT stops advertising. + + # 10. Upper Tester receives an HCI_LE_Connection_Complete event from the IUT including the + # parameters sent to the IUT in step 7. + await self.expect_evt( + hci.LeEnhancedConnectionComplete(status=ErrorCode.SUCCESS, + connection_handle=connection_handle, + role=hci.Role.PERIPHERAL, + peer_address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS, + peer_address=public_peer_address, + conn_interval=self.LL_initiator_connInterval, + conn_latency=self.LL_initiator_connPeripheralLatency, + supervision_timeout=self.LL_initiator_connSupervisionTimeout, + central_clock_accuracy=hci.ClockAccuracy.PPM_500)) + + # 11. Upper Tester receives an HCI_Disconnection_Complete event from the IUT once the + # Establishment Timeout has expired. + controller.send_ll( + ll.Disconnect(source_address=public_peer_address, + destination_address=controller.address, + reason=int(hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION))) + + await self.expect_evt( + hci.DisconnectionComplete(status=ErrorCode.SUCCESS, + connection_handle=connection_handle, + reason=hci.ErrorCode.REMOTE_USER_TERMINATED_CONNECTION)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_20_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_20_C.py new file mode 100644 index 00000000000..6cbf26ed5b1 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_20_C.py @@ -0,0 +1,70 @@ +import lib_rootcanal_python3 as rootcanal +import hci_packets as hci +import link_layer_packets as ll +import unittest +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-20-C [Advertising Always Using the LE 1M PHY] + async def test(self): + 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. Lower Tester will only + # accept advertising packets sent using the LE 1M PHY setting. Lower Tester will scan for at least + # 30 advertising intervals on each advertising channel (for example, scan on channel 37 for the first + # 30 intervals, then on channel 38 for another 30 intervals, then finally on channel 39 for the last 30 + # intervals). + # 2. Upper Tester sends a LE_Set_Default_PHY command to the IUT, with the ALL_PHYS field set to + # zero, and the TX_PHYS and RX_PHYS fields both set to prefer the LE 2M PHY. + controller.send_cmd( + hci.LeSetDefaultPhy(all_phys_no_transmit_preference=False, + all_phys_no_receive_preference=False, + tx_phys_bitmask=0x2, + rx_phys_bitmask=0x2)) + + await self.expect_evt(hci.LeSetDefaultPhyComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 3. Upper Tester enables undirected advertising in the IUT using all supported advertising channels + # and minimum advertising interval. + controller.send_cmd( + hci.LeSetAdvertisingParameters( + advertising_interval_min=self.LL_advertiser_advInterval_MIN, + advertising_interval_max=self.LL_advertiser_advInterval_MAX, + advertising_type=hci.AdvertisingType.ADV_IND, + own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS, + advertising_channel_map=self.LL_advertiser_Adv_Channel_Map, + advertising_filter_policy=hci.AdvertisingFilterPolicy.LISTED_SCAN_AND_CONNECT)) + + await self.expect_evt( + hci.LeSetAdvertisingParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=True)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) + + # 4. Lower Tester expects the IUT to send ADV_IND packets starting an event on an applicable + # advertising channel using the LE 1M PHY. + # 5. Repeat step 4 until at least 90 advertising packets have been detected, i.e., at least 30 packets + # on each channel. + 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=[])) + + # 6. Upper Tester sends an HCI_LE_Set_Advertising_Enable command to disable advertising in the + # IUT and receives an HCI_Command_Complete event from the IUT. + controller.send_cmd(hci.LeSetAdvertisingEnable(advertising_enable=False)) + + await self.expect_evt(hci.LeSetAdvertisingEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1)) diff --git a/tools/rootcanal/test/LL/DDI/ADV/BV_21_C.py b/tools/rootcanal/test/LL/DDI/ADV/BV_21_C.py new file mode 100644 index 00000000000..d7312d13065 --- /dev/null +++ b/tools/rootcanal/test/LL/DDI/ADV/BV_21_C.py @@ -0,0 +1,86 @@ +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-21-C [Extended Advertising, Legacy PDUs, Non-Connectable] + async def test(self): + 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. + # 2. The Upper Tester sends an HCI_LE_Set_Extended_Advertising_Parameters command to the + # IUT using a selected primary advertising channel and minimum advertising interval. The + # Advertising_Event_Properties parameter shall be set to 00010000b (ADV_NONCONN_IND + # legacy PDU). + controller.send_cmd( + hci.LeSetExtendedAdvertisingParametersLegacy( + advertising_handle=0, + legacy_advertising_event_properties=hci.LegacyAdvertisingEventProperties.ADV_NONCONN_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)) + + # For each round from 1–3 based on Table 4.2: + await self.steps_3_8(advertising_data=[1]) + await self.steps_3_8(advertising_data=[]) + await self.steps_3_8(advertising_data=[0xf8] + [0] * 30) + + async def steps_3_8(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.2 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 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 expects the IUT to send ADV_NONCONN_IND packets including the data + # submitted in step 3 starting an event on the selected primary advertising channel. + # 6. Expect the following event to start after advertising interval time calculating from the start of the + # first packet. + # 7. Repeat steps 5–6 until a number of advertising intervals (50) have been detected. + for n in range(3): + self.expect_ll( + ll.LeLegacyAdvertisingPdu(source_address=controller.address, + advertising_address_type=ll.AddressType.PUBLIC, + advertising_type=ll.LegacyAdvertisingType.ADV_NONCONN_IND, + advertising_data=advertising_data)) + + # 8. 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)) diff --git a/tools/rootcanal/test/main.py b/tools/rootcanal/test/main.py index dcf35e7cf49..3c3b6cb4a11 100644 --- a/tools/rootcanal/test/main.py +++ b/tools/rootcanal/test/main.py @@ -27,6 +27,14 @@ tests = [ 'LL.DDI.ADV.BV_08_C', 'LL.DDI.ADV.BV_09_C', 'LL.DDI.ADV.BV_11_C', + 'LL.DDI.ADV.BV_15_C', + 'LL.DDI.ADV.BV_16_C', + '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_21_C', 'LL.DDI.SCN.BV_13_C', 'LL.DDI.SCN.BV_14_C', 'LL.DDI.SCN.BV_18_C', -- GitLab