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