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

Commit 7a54b5e2 authored by Henri Chataing's avatar Henri Chataing
Browse files

RootCanal: Implement additional LL tests

Implement LL tests LL/DDI/ADV/BV-02-C and LL/DDI/ADV/BV-03-C.

Bug: 253523072
Test: atest --host rootcanal_ll_test
Change-Id: Ia2cb58b5445182ba4d7d82ed1431a0d5d0eb486c
parent 4a9653c0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3171,6 +3171,12 @@ packet LeSetAdvertisingData : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetAdvertisingDataRaw : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_DATA) {
  _size_(advertising_data) : 8,
  advertising_data : 8[],
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ADVERTISING_DATA) {
  status : ErrorCode,
}
+38 −0
Original line number Diff line number Diff line
@@ -177,6 +177,41 @@ class FieldParser:
            element = f"{field.type_id}.parse_all({span})"
            self.append_(f"    {field.id}.append({element})")

    def parse_byte_array_field_(self, field: ast.ArrayField):
        """Parse the selected u8 array field."""
        array_size = core.get_array_field_size(field)
        padded_size = field.padded_size

        # Shift the span to reset the offset to 0.
        self.consume_span_()

        # Derive the array size.
        if isinstance(array_size, int):
            size = array_size
        elif isinstance(array_size, ast.SizeField):
            size = f'{field.id}_size - {field.size_modifier}' if field.size_modifier else f'{field.id}_size'
        elif isinstance(array_size, ast.CountField):
            size = f'{field.id}_count'
        else:
            size = None

        # Parse from the padded array if padding is present.
        if padded_size and size is not None:
            self.check_size_(padded_size)
            self.append_(f"if {size} > {padded_size}:")
            self.append_("    raise Exception('Array size is larger than the padding size')")
            self.append_(f"fields['{field.id}'] = list(span[:{size}])")
            self.append_(f"span = span[{padded_size}:]")

        elif size is not None:
            self.check_size_(size)
            self.append_(f"fields['{field.id}'] = list(span[:{size}])")
            self.append_(f"span = span[{size}:]")

        else:
            self.append_(f"fields['{field.id}'] = list(span)")
            self.append_(f"span = bytes()")

    def parse_array_field_(self, field: ast.ArrayField):
        """Parse the selected array field."""
        array_size = core.get_array_field_size(field)
@@ -484,6 +519,9 @@ class FieldParser:
            pass

        # Array fields.
        elif isinstance(field, ast.ArrayField) and field.width == 8:
            self.parse_byte_array_field_(field)

        elif isinstance(field, ast.ArrayField):
            self.parse_array_field_(field)

+2 −0
Original line number Diff line number Diff line
@@ -259,6 +259,8 @@ python_test_host {
        ":link_layer_packets_python3_gen",
        "test/main.py",
        "test/LL/DDI/ADV/BV_01_C.py",
        "test/LL/DDI/ADV/BV_02_C.py",
        "test/LL/DDI/ADV/BV_03_C.py",
        "test/LL/DDI/SCN/BV_13_C.py",
        "test/LL/DDI/SCN/BV_14_C.py",
        "test/LL/DDI/SCN/BV_18_C.py",
+8 −6
Original line number Diff line number Diff line
@@ -23,16 +23,18 @@ class Test(ControllerTest):
        # channel and a selected advertising interval between the minimum and maximum advertising
        # intervals.
        controller.send_cmd(
            hci.LeSetAdvertisingParameters(advertising_interval_min=LL_advertiser_advInterval_MIN,
            hci.LeSetAdvertisingParameters(
                advertising_interval_min=LL_advertiser_advInterval_MIN,
                advertising_interval_max=LL_advertiser_advInterval_MAX,
                advertising_type=hci.AdvertisingType.ADV_NONCONN_IND,
                own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS,
                                           advertising_channel_map=LL_advertiser_Adv_Channel_Map))
                advertising_channel_map=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())
        controller.send_cmd(hci.LeSetAdvertisingDataRaw())

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

+59 −0
Original line number Diff line number Diff line
import lib_rootcanal_python3 as rootcanal
import hci_packets as hci
import link_layer_packets as ll
import unittest
from hci_packets import ErrorCode
from py.bluetooth import Address
from py.controller import ControllerTest


class Test(ControllerTest):

    # LL/DDI/ADV/BV-02-C [Undirected Advertising Events]
    async def test(self):
        # Test parameters.
        LL_advertiser_advInterval_MIN = 0x200
        LL_advertiser_advInterval_MAX = 0x200
        LL_advertiser_Adv_Channel_Map = 0x7
        controller = self.controller

        # 1. Configure Lower Tester to monitor advertising packets from the IUT.

        # 2. Upper Tester enables 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=LL_advertiser_advInterval_MIN,
                advertising_interval_max=LL_advertiser_advInterval_MAX,
                advertising_type=hci.AdvertisingType.ADV_IND,
                own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS,
                advertising_channel_map=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.LeSetAdvertisingDataRaw())

        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_IND packets 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 advertising intervals (100) have been detected.
        for n in range(10):
            await self.expect_ll(ll.LeLegacyAdvertisingPdu(source_address=controller.address,
                                                           advertising_address_type=ll.AddressType.PUBLIC,
                                                           advertising_type=ll.LegacyAdvertisingType.ADV_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))
Loading