diff --git a/autopts/bot/iut_config/zephyr.py b/autopts/bot/iut_config/zephyr.py index 2d512ac738..6878f98d4a 100644 --- a/autopts/bot/iut_config/zephyr.py +++ b/autopts/bot/iut_config/zephyr.py @@ -296,7 +296,55 @@ "test_cases": [ 'MBTM/CL/BT' ] - } + }, + + "br_sec_sc_only.conf": { + "overlay": { + 'CONFIG_BT_CLASSIC': 'y', + 'CONFIG_BT_CENTRAL': 'y', + 'CONFIG_BT_PERIPHERAL': 'y', + 'CONFIG_BT_SMP': 'y', + 'CONFIG_BT_L2CAP_DYNAMIC_CHANNEL': 'y', + 'CONFIG_BT_PAGE_TIMEOUT': '0xFFFF', + 'CONFIG_BT_SMP_SC_ONLY': 'y', + 'CONFIG_BT_SMP_SC_PAIR_ONLY': 'y', + }, + "test_cases": [ + 'GAP/SEC/SEM/BV-11-C', + 'GAP/SEC/SEM/BV-12-C', + 'GAP/SEC/SEM/BV-13-C', + 'GAP/SEC/SEM/BV-47-C', + 'GAP/SEC/SEM/BV-16-C', + 'GAP/SEC/SEM/BV-17-C', + 'GAP/SEC/SEM/BV-18-C', + 'GAP/SEC/SEM/BV-54-C', + 'GAP/SEC/SEM/BI-32-C', + 'GAP/SEC/SEM/BV-25-C', + 'GAP/SEC/SEM/BV-30-C', + ] + }, + + "br_sec_ks_128.conf": { + "overlay": { + 'CONFIG_BT_CLASSIC': 'y', + 'CONFIG_BT_CENTRAL': 'y', + 'CONFIG_BT_PERIPHERAL': 'y', + 'CONFIG_BT_SMP': 'y', + 'CONFIG_BT_L2CAP_DYNAMIC_CHANNEL': 'y', + 'CONFIG_BT_PAGE_TIMEOUT': '0xFFFF', + 'CONFIG_BT_SMP_MIN_ENC_KEY_SIZE': '16', + }, + "test_cases": [ + 'GAP/SEC/SEM/BI-14-C', + 'GAP/SEC/SEM/BI-15-C', + 'GAP/SEC/SEM/BI-16-C', + 'GAP/SEC/SEM/BI-04-C', + 'GAP/SEC/SEM/BI-17-C', + 'GAP/SEC/SEM/BI-18-C', + 'GAP/SEC/SEM/BI-19-C', + 'GAP/SEC/SEM/BI-08-C', + ] + }, } retry_config = { diff --git a/autopts/ptsprojects/boards/nrf53.py b/autopts/ptsprojects/boards/nrf53.py index a200111260..bc26594ade 100644 --- a/autopts/ptsprojects/boards/nrf53.py +++ b/autopts/ptsprojects/boards/nrf53.py @@ -12,13 +12,15 @@ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # +import logging +import os from .nrf5x import * from autopts.bot.common import check_call +from subprocess import CalledProcessError board_type = 'nrf5340dk/nrf5340/cpuapp' - def build_and_flash(zephyr_wd, board, debugger_snr, conf_file=None, *args): """Build and flash Zephyr binary :param zephyr_wd: Zephyr source path @@ -30,22 +32,17 @@ def build_and_flash(zephyr_wd, board, debugger_snr, conf_file=None, *args): board, conf_file) tester_dir = os.path.join(zephyr_wd, 'tests', 'bluetooth', 'tester') - controller_dir = os.path.join(zephyr_wd, 'samples', 'bluetooth', 'hci_ipc') check_call('rm -rf build/'.split(), cwd=tester_dir) - check_call('rm -rf build/'.split(), cwd=controller_dir) bttester_overlay = 'hci_ipc.conf' if conf_file and conf_file != 'default' and conf_file != 'prj.conf': bttester_overlay += f';{conf_file}' - cmd = ['west', 'build', '--no-sysbuild', '-b', board, '--', f'-DEXTRA_CONF_FILE=\'{bttester_overlay}\''] + cmd = ['west', 'build', '--sysbuild', '-b', board, '--', f'-DEXTRA_CONF_FILE=\'{bttester_overlay}\''] check_call(cmd, cwd=tester_dir) - check_call(['west', 'flash', '--skip-rebuild', '--recover', '-i', debugger_snr], cwd=tester_dir) - - cmd = ['west', 'build', '--no-sysbuild', '-b', 'nrf5340dk/nrf5340/cpunet', '--', - f'-DEXTRA_CONF_FILE=\'nrf5340_cpunet_iso-bt_ll_sw_split.conf;' - f'../../../tests/bluetooth/tester/hci_ipc_cpunet.conf\''] - check_call(cmd, cwd=controller_dir) - check_call(['west', 'flash', '--skip-rebuild', '-i', debugger_snr], cwd=controller_dir) + try: + check_call(['west', 'flash', '--skip-rebuild', '-i', debugger_snr], cwd=tester_dir) + except CalledProcessError: + check_call(['west', 'flash', '--skip-rebuild', '--recover', '-i', debugger_snr], cwd=tester_dir) diff --git a/autopts/ptsprojects/mynewt/l2cap.py b/autopts/ptsprojects/mynewt/l2cap.py index 627eee97d0..d95a38e0be 100644 --- a/autopts/ptsprojects/mynewt/l2cap.py +++ b/autopts/ptsprojects/mynewt/l2cap.py @@ -170,6 +170,10 @@ def test_cases(ptses): TestFunc(btp.l2cap_le_listen, le_psm, le_initial_mtu, L2cap.unacceptable_parameters) ] + pre_conditions_gatt = common + [ + TestFunc(btp.core_reg_svc_gatt), + ] + custom_test_cases = [ # Connection Parameter Update ZTestCase("L2CAP", "L2CAP/LE/CFC/BV-04-C", @@ -229,6 +233,10 @@ def test_cases(ptses): [TestFunc(lambda: pts.update_pixit_param( "L2CAP", "TSPX_l2ca_cbmps_min", "0040"))], generic_wid_hdl=l2cap_wid_hdl), + # Collision mitigation handling + ZTestCase("L2CAP", "L2CAP/TIM/BV-03-C", + pre_conditions_gatt, + generic_wid_hdl=l2cap_wid_hdl), ] test_case_name_list = pts.get_test_case_list('L2CAP') diff --git a/autopts/ptsprojects/stack/layers/gap.py b/autopts/ptsprojects/stack/layers/gap.py index cc606dfb16..6314a2db66 100644 --- a/autopts/ptsprojects/stack/layers/gap.py +++ b/autopts/ptsprojects/stack/layers/gap.py @@ -95,6 +95,7 @@ def __init__(self, name, manufacturer_data, appearance, svc_data, flags, self.passkey = Property(None) self.conn_params = Property(None) self.pairing_failed_rcvd = Property(None) + self.encryption_change_rcvd = Property(None) # bond_lost data (addr_type, addr) self.bond_lost_ev_data = Property(None) @@ -224,6 +225,26 @@ def gap_wait_for_pairing_fail(self, timeout=5): return self.pairing_failed_rcvd.data + def gap_wait_for_encryption_change(self, timeout=5): + if self.encryption_change_rcvd.data is None: + wait_for_event(timeout, lambda: self.encryption_change_rcvd.data) + + return self.encryption_change_rcvd.data + + def gap_wait_for_encrypted(self, timeout=5): + if self.encryption_change_rcvd.data is None: + wait_for_event(timeout, lambda: self.encryption_change_rcvd.data) + + if self.encryption_change_rcvd.data is None: + return False + + (_, _, enabled, _) = self.encryption_change_rcvd.data + + if enabled == 0: + return False + else: + return True + def gap_wait_for_lost_bond(self, timeout=5): if self.bond_lost_ev_data.data is None: wait_for_event(timeout, lambda: self.bond_lost_ev_data.data) diff --git a/autopts/ptsprojects/stack/stack.py b/autopts/ptsprojects/stack/stack.py index b49aea84a1..00e0b060a5 100644 --- a/autopts/ptsprojects/stack/stack.py +++ b/autopts/ptsprojects/stack/stack.py @@ -16,50 +16,16 @@ import logging from autopts.ptsprojects.stack.layers import * from autopts.ptsprojects.stack.synch import Synch -from autopts.pybtp import defs +from autopts.pybtp import common STACK = None log = logging.debug -# these are in little endian -services = { - "CORE": 1 << defs.BTP_SERVICE_ID_CORE, - "GAP": 1 << defs.BTP_SERVICE_ID_GAP, - "GATT": 1 << defs.BTP_SERVICE_ID_GATT, - "L2CAP": 1 << defs.BTP_SERVICE_ID_L2CAP, - "MESH": 1 << defs.BTP_SERVICE_ID_MESH, - "MESH_MMDL": 1 << defs.BTP_SERVICE_ID_MMDL, - "GATT_CL": 1 << defs.BTP_SERVICE_ID_GATTC, - "VCS": 1 << defs.BTP_SERVICE_ID_VCS, - "IAS": 1 << defs.BTP_SERVICE_ID_IAS, - "AICS": 1 << defs.BTP_SERVICE_ID_AICS, - "VOCS": 1 << defs.BTP_SERVICE_ID_VOCS, - "PACS": 1 << defs.BTP_SERVICE_ID_PACS, - "ASCS": 1 << defs.BTP_SERVICE_ID_ASCS, - "BAP": 1 << defs.BTP_SERVICE_ID_BAP, - "MICP": 1 << defs.BTP_SERVICE_ID_MICP, - "HAS": 1 << defs.BTP_SERVICE_ID_HAS, - "CSIS": 1 << defs.BTP_SERVICE_ID_CSIS, - "MICS": 1 << defs.BTP_SERVICE_ID_MICS, - "CCP": 1 << defs.BTP_SERVICE_ID_CCP, - "VCP": 1 << defs.BTP_SERVICE_ID_VCP, - "MCP": 1 << defs.BTP_SERVICE_ID_MCP, - "GMCS": 1 << defs.BTP_SERVICE_ID_GMCS, - "HAP": 1 << defs.BTP_SERVICE_ID_HAP, - "CAP": 1 << defs.BTP_SERVICE_ID_CAP, - "CSIP": 1 << defs.BTP_SERVICE_ID_CSIP, - "TBS": 1 << defs.BTP_SERVICE_ID_TBS, - "TMAP": 1 << defs.BTP_SERVICE_ID_TMAP, - "OTS": 1 << defs.BTP_SERVICE_ID_OTS, - "PBP": 1 << defs.BTP_SERVICE_ID_PBP, - # GENERATOR append 1 -} - - class Stack: def __init__(self): self.supported_svcs = 0 + self.supported_cmds = 0 self.synch = None self.gap = None @@ -90,9 +56,11 @@ def __init__(self): self.ots = None self.pbp = None # GENERATOR append 2 + self.supported_svcs_cmds = common.supported_svcs_cmds def is_svc_supported(self, svc): - return self.supported_svcs & services[svc] > 0 + svc_value = self.supported_svcs_cmds.get(svc, {}).get("service", 0) + return (self.supported_svcs & svc_value) > 0 def gap_init(self, name=None, manufacturer_data=None, appearance=None, svc_data=None, flags=None, svcs=None, uri=None, periodic_data=None, diff --git a/autopts/ptsprojects/zephyr/gap.py b/autopts/ptsprojects/zephyr/gap.py index a525b88108..809809a183 100644 --- a/autopts/ptsprojects/zephyr/gap.py +++ b/autopts/ptsprojects/zephyr/gap.py @@ -18,6 +18,7 @@ from autopts.pybtp import btp from autopts.pybtp.types import Addr, IOCap, AdType, AdFlags, Prop, Perm, UUID, UriScheme +from autopts.pybtp.types import L2CAPConnectionResponse from autopts.client import get_unique_name from autopts.ptsprojects.stack import get_stack from autopts.ptsprojects.testcase import TestFunc @@ -69,6 +70,10 @@ class CHAR: iut_uri = UriScheme.https + 'github.com/auto-pts'.encode() iut_le_supp_feat = 'FF' +br_psm = 0x1001 +br_psm_2 = 0x2001 +br_initial_mtu = 120 + # Ad data for periodic advertising in format (type, data) # Value: shortened name periodic_data = (0x08, "PADV_Tester") @@ -219,10 +224,376 @@ def test_cases(ptses): # TODO: Get PTS address type TestFunc(btp.set_pts_addr, pts_bd_addr, Addr.le_public)] + br_pre_cond = pre_conditions + [ + TestFunc(lambda: pts.update_pixit_param( + "GAP", "TSPX_psm", format(br_psm, '04x'))), + TestFunc(lambda: pts.update_pixit_param( + "GAP", "TSPX_psm_2", format(br_psm_2, '04x'))), + TestFunc(lambda: pts.update_pixit_param( + "GAP", "TSPX_delete_link_key", "FALSE")), + TestFunc(lambda: pts.update_pixit_param( + "GAP", "TSPX_delete_ltk", "FALSE")), + TestFunc(btp.gap_set_io_cap, IOCap.no_input_output), + ] + + br_l2cap = br_pre_cond + [ + TestFunc(btp.core_reg_svc_l2cap), + TestFunc(stack.l2cap_init, br_psm, br_initial_mtu), + ] + + br_l2cap_success = br_l2cap + [ + TestFunc(btp.l2cap_br_listen, br_psm, br_initial_mtu, + L2CAPConnectionResponse.insufficient_encryption), + ] + + br_l2cap_authen = br_l2cap + [ + TestFunc(btp.l2cap_br_listen, br_psm, br_initial_mtu, + L2CAPConnectionResponse.insufficient_authentication), + ] + + br_l2cap_secure_authen = br_l2cap + [ + TestFunc(btp.l2cap_br_listen, br_psm, br_initial_mtu, + L2CAPConnectionResponse.insufficient_secure_authentication), + ] + + br_l2cap_keysize = br_l2cap + [ + TestFunc(btp.l2cap_br_listen, br_psm, br_initial_mtu, + L2CAPConnectionResponse.insufficient_encryption_key_size), + ] + + br_l2cap_author = br_l2cap + [ + TestFunc(btp.l2cap_br_listen, br_psm, br_initial_mtu, + L2CAPConnectionResponse.insufficient_authorization), + ] + custom_test_cases = [ ZTestCase("GAP", "GAP/SEC/CSIGN/BI-04-C", cmds=pre_conditions + init_gatt_db2, generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/MOD/NBON/BV-03-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-02-C", + cmds=br_l2cap_success, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/IDLE/BON/BV-03-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/IDLE/BON/BV-04-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/IDLE/BON/BV-05-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/IDLE/BON/BV-06-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/EST/LIE/BV-02-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-04-C", + cmds=br_l2cap_success + [ + TestFunc(btp.gap_set_gendiscov), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-08-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-05-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-50-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-06-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-07-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-51-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-52-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-09-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-53-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_bondable_off), + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-10-C", + cmds=br_l2cap_success + [ + TestFunc(btp.gap_set_bondable_off), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-24-C", + cmds=br_l2cap_success + [ + TestFunc(btp.gap_set_bondable_off), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/NCON/BV-01-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/NBON/BV-01-C", + cmds=br_pre_cond + [ + TestFunc(btp.gap_set_conn), + TestFunc(btp.gap_set_gendiscov), + TestFunc(btp.gap_set_bondable_off), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/BON/BV-01-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-11-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-12-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-13-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-14-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-15-C", + cmds=br_l2cap_secure_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-47-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-48-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-49-C", + cmds=br_l2cap_secure_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-16-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-17-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-18-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-19-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-20-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-54-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-55-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-11-C", + cmds=br_l2cap_success, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-12-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-02-C", + cmds=br_l2cap_success, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-06-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-03-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-07-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-31-C", + cmds=br_l2cap_secure_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-14-C", + cmds=br_l2cap_success, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-15-C", + cmds=br_l2cap_success, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-16-C", + cmds=br_l2cap_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-04-C", + cmds=br_l2cap_secure_authen + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-17-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-18-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-19-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-08-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-08-C", + cmds=br_pre_cond + [ + TestFunc(btp.gap_set_gendiscov), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-09-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-10-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-11-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-12-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-15-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-20-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-14-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-16-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-21-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-17-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BI-01-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-22-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-19-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BI-02-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-23-C", + cmds=br_pre_cond, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-18-C", + cmds=br_pre_cond + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/DM/LEP/BV-13-C", + cmds=br_pre_cond + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-27-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-32-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-26-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BI-25-C", + cmds=br_l2cap, + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-25-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), + ZTestCase("GAP", "GAP/SEC/SEM/BV-30-C", + cmds=br_l2cap + [ + TestFunc(btp.gap_set_io_cap, IOCap.display_yesno), + ], + generic_wid_hdl=gap_wid_hdl), ] test_case_name_list = pts.get_test_case_list('GAP') diff --git a/autopts/pybtp/btp/btp.py b/autopts/pybtp/btp/btp.py index ce4228b702..fafaa6ba80 100644 --- a/autopts/pybtp/btp/btp.py +++ b/autopts/pybtp/btp/btp.py @@ -20,7 +20,9 @@ import logging import re import struct +import math +from autopts.pybtp.common import supported_svcs_cmds, reg_unreg_service from autopts.ptsprojects.stack import get_stack from autopts.ptsprojects.testcase import MMI from .. import defs @@ -29,6 +31,9 @@ # get IUT global method from iutctl get_iut = None +#loading as CORE to maintain backward compatibility with older code snippet +CORE = reg_unreg_service + # Address LeAddress = namedtuple('LeAddress', 'addr_type addr') PTS_BD_ADDR = LeAddress(addr_type=0, addr='000000000000') @@ -59,88 +64,65 @@ def read_supp_svcs(): stack.supported_svcs = int.from_bytes(tuple_data[0], 'little') +def read_supported_commands(service): + iutctl = get_iut() + stack = get_stack() + svc_key = service.upper() + + entry = supported_svcs_cmds.get(svc_key) + if entry is None: + logging.warning("Service %s is not registered", svc_key) + return + + if "supported_commands" not in entry: + logging.warning("No READ_SUPPORTED_COMMANDS for %s", svc_key) + return + + service_bitmask = entry.get("service") + if service_bitmask is None: + logging.warning("No service bitmask for %s", svc_key) + return + + try: + service_id = int(math.log2(service_bitmask)) + except Exception as err: + logging.error("Invalid mask for %s: %s", svc_key, err) + return + + opcode_supp_cmd = entry["supported_commands"] + + cmd_tuple = (service_id, opcode_supp_cmd, defs.BTP_INDEX_NONE, "") + iutctl.btp_socket.send(*cmd_tuple) + tuple_hdr, tuple_data = iutctl.btp_socket.read() + + btp_hdr_check(tuple_hdr, exp_svc_id=service_id, exp_op=opcode_supp_cmd) + + data_bytes = tuple_data[0] if isinstance(tuple_data, tuple) and tuple_data else tuple_data + supported_cmds_value = int.from_bytes(data_bytes, 'little') + + if not isinstance(stack.supported_cmds, dict): + stack.supported_cmds = {} + stack.supported_cmds[svc_key] = supported_cmds_value + + +def core_reg_svc_univ(service_key: str, service_name: str): + """ + Universal service registration. + Registers a BTP service via CORE and reads supported commands if service_name is set. + Usage: + TestFunc(lambda: core_reg_svc_univ("gap_reg", "GAP")) + TestFunc(lambda: core_reg_svc_univ("ias_reg", "")) # skip reading commands + """ + logging.debug("core_reg_svc_univ: %s (%s)", service_key, service_name) + iutctl = get_iut() -CORE = { - "gap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GAP), - "gap_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GAP), - "gatt_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GATT), - "gatt_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GATT), - "l2cap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_L2CAP), - "l2cap_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_L2CAP), - "mesh_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MESH), - "mesh_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MESH), - "mmdl_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MMDL), - "mmdl_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MMDL), - "gatt_cl_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GATTC), - "gatt_cl_unreg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_UNREGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GATTC), - "vcs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_VCS), - "vocs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_VOCS), - "aics_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_AICS), - "ias_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_IAS), - "pacs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_PACS), - "ascs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_ASCS), - "bap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_BAP), - "has_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_HAS), - "csis_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_CSIS), - "micp_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MICP), - "mics_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MICS), - "ccp_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_CCP), - "vcp_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_VCP), - "cas_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_CAS), - "mcp_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_MCP), - "gmcs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_GMCS), - "hap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_HAP), - "cap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_CAP), - "csip_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_CSIP), - "tbs_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_TBS), - "tmap_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_TMAP), - "ots_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_OTS), - "pbp_reg": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE, - defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_PBP), - # GENERATOR append 4 - "read_supp_cmds": (defs.BTP_SERVICE_ID_CORE, - defs.BTP_CORE_CMD_READ_SUPPORTED_COMMANDS, - defs.BTP_INDEX_NONE, ""), - "read_supp_svcs": (defs.BTP_SERVICE_ID_CORE, - defs.BTP_CORE_CMD_READ_SUPPORTED_SERVICES, - defs.BTP_INDEX_NONE, ""), - "log_message": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_LOG_MESSAGE, - defs.BTP_INDEX_NONE), -} + try: + iutctl.btp_socket.send(*CORE[service_key]) + except KeyError: + logging.error("CORE key %s not found", service_key) + return + + core_reg_svc_rsp_succ(service_name) def clear_verify_values(): @@ -460,12 +442,7 @@ def set_lt3_addr(addr, addr_type): def core_reg_svc_gap(): - logging.debug("%s", core_reg_svc_gap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['gap_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("gap_reg", "GAP") def core_unreg_svc_gap(): @@ -478,12 +455,7 @@ def core_unreg_svc_gap(): def core_reg_svc_gatt(): - logging.debug("%s", core_reg_svc_gatt.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['gatt_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("gatt_reg", "GATT") def core_unreg_svc_gatt(): @@ -494,12 +466,7 @@ def core_unreg_svc_gatt(): def core_reg_svc_l2cap(): - logging.debug("%s", core_reg_svc_l2cap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['l2cap_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("l2cap_reg", "L2CAP") def core_unreg_svc_l2cap(): @@ -510,12 +477,7 @@ def core_unreg_svc_l2cap(): def core_reg_svc_mesh(): - logging.debug("%s", core_reg_svc_mesh.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['mesh_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("mesh_reg", "MESH") def core_unreg_svc_mesh(): @@ -526,12 +488,7 @@ def core_unreg_svc_mesh(): def core_reg_svc_mmdl(): - logging.debug("%s", core_reg_svc_mmdl.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['mmdl_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("mmdl_reg", "MESH_MMDL") def core_unreg_svc_mmdl(): @@ -542,12 +499,7 @@ def core_unreg_svc_mmdl(): def core_reg_svc_gatt_cl(): - logging.debug("%s", core_reg_svc_gatt_cl.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send(*CORE['gatt_cl_reg']) - - core_reg_svc_rsp_succ() + core_reg_svc_univ("gatt_cl_reg", "GATT_CL") def core_unreg_svc_gatt_cl(): @@ -558,164 +510,99 @@ def core_unreg_svc_gatt_cl(): def core_reg_svc_vcs(): - logging.debug("%s", core_reg_svc_vcs.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['vcs_reg']) + core_reg_svc_univ("vcs_reg", "VCS") def core_reg_svc_vocs(): - logging.debug("%s", core_reg_svc_vocs.__name__) + core_reg_svc_univ("vocs_reg", "VOCS") - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['vocs_reg']) def core_reg_svc_aics(): - logging.debug("%s", core_reg_svc_aics.__name__) + core_reg_svc_univ("aics_reg", "AICS") - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['aics_reg']) def core_reg_svc_ias(): - logging.debug("%s", core_reg_svc_ias.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['ias_reg']) + core_reg_svc_univ("ias_reg", "") def core_reg_svc_pacs(): - logging.debug("%s", core_reg_svc_pacs.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['pacs_reg']) + core_reg_svc_univ("pacs_reg", "PACS") def core_reg_svc_ascs(): - logging.debug("%s", core_reg_svc_ascs.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['ascs_reg']) + core_reg_svc_univ("ascs_reg", "ASCS") def core_reg_svc_has(): - logging.debug("%s", core_reg_svc_has.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['has_reg']) + core_reg_svc_univ("has_reg", "HAS") def core_reg_svc_bap(): - logging.debug("%s", core_reg_svc_bap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['bap_reg']) + core_reg_svc_univ("bap_reg", "BAP") def core_reg_svc_csis(): - logging.debug("%s", core_reg_svc_csis.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['csis_reg']) + core_reg_svc_univ("csis_reg", "CSIS") def core_reg_svc_micp(): - logging.debug("%s", core_reg_svc_micp.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['micp_reg']) + core_reg_svc_univ("micp_reg", "MICP") def core_reg_svc_mics(): - logging.debug("%s", core_reg_svc_mics.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['mics_reg']) + core_reg_svc_univ("mics_reg", "MICS") def core_reg_svc_ccp(): - logging.debug("%s", core_reg_svc_ccp.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['ccp_reg']) + core_reg_svc_univ("ccp_reg", "CCP") def core_reg_svc_cas(): - logging.debug("%s", core_reg_svc_cas.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['cas_reg']) + core_reg_svc_univ("cas_reg", "CAS") def core_reg_svc_vcp(): - logging.debug("%s", core_reg_svc_vcp.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['vcp_reg']) + core_reg_svc_univ("vcp_reg", "VCP") def core_reg_svc_mcp(): - logging.debug("%s", core_reg_svc_mcp.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['mcp_reg']) + core_reg_svc_univ("mcp_reg", "MCP") def core_reg_svc_gmcs(): - logging.debug("%s", core_reg_svc_gmcs.__name__) + core_reg_svc_univ("gmcs_reg", "GMCS") - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['gmcs_reg']) def core_reg_svc_hap(): - logging.debug("%s", core_reg_svc_hap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['hap_reg']) + core_reg_svc_univ("hap_reg", "HAP") def core_reg_svc_cap(): - logging.debug("%s", core_reg_svc_cap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['cap_reg']) + core_reg_svc_univ("cap_reg", "CAP") def core_reg_svc_csip(): - logging.debug("%s", core_reg_svc_csip.__name__) + core_reg_svc_univ("csip_reg", "CSIP") - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['csip_reg']) def core_reg_svc_tmap(): - logging.debug("%s", core_reg_svc_tmap.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['tmap_reg']) + core_reg_svc_univ("tmap_reg", "TMAP") def core_reg_svc_tbs(): - logging.debug("%s", core_reg_svc_tbs.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['tbs_reg']) + core_reg_svc_univ("tbs_reg", "TBS") def core_reg_svc_ots(): - logging.debug("%s", core_reg_svc_ots.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['ots_reg']) + core_reg_svc_univ("ots_reg", "OTS") def core_reg_svc_pbp(): - logging.debug("%s", core_reg_svc_pbp.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['pbp_reg']) + core_reg_svc_univ("pbp_reg", "PBP") # GENERATOR append 1 -def core_reg_svc_rsp_succ(): +def core_reg_svc_rsp_succ(service_name): logging.debug("%s", core_reg_svc_rsp_succ.__name__) iutctl = get_iut() @@ -734,6 +621,13 @@ def core_reg_svc_rsp_succ(): logging.error("frames mismatch") raise BTPError("Unexpected response received!") logging.debug("response is valid") + service_name = service_name.strip() + if service_name: + logging.debug("Reading supported commands for service: %s", service_name) + try: + read_supported_commands(service_name) + except Exception as e: + logging.warning("No read supported commands for %s: %s", service_name, e) def core_unreg_svc_rsp_succ(): diff --git a/autopts/pybtp/btp/gap.py b/autopts/pybtp/btp/gap.py index 909c2a2360..2ecd037998 100644 --- a/autopts/pybtp/btp/gap.py +++ b/autopts/pybtp/btp/gap.py @@ -35,6 +35,7 @@ CONTROLLER_INDEX, ""), "conn": (defs.BTP_SERVICE_ID_GAP, defs.BTP_GAP_CMD_CONNECT, CONTROLLER_INDEX), "pair": (defs.BTP_SERVICE_ID_GAP, defs.BTP_GAP_CMD_PAIR, CONTROLLER_INDEX), + "pair_v2": (defs.BTP_SERVICE_ID_GAP, defs.BTP_GAP_CMD_PAIR_V2, CONTROLLER_INDEX), "unpair": (defs.BTP_SERVICE_ID_GAP, defs.BTP_GAP_CMD_UNPAIR, CONTROLLER_INDEX), "disconn": (defs.BTP_SERVICE_ID_GAP, defs.BTP_GAP_CMD_DISCONNECT, CONTROLLER_INDEX), @@ -375,6 +376,24 @@ def gap_passkey_entry_req_ev_(gap, data, data_len): gap.passkey.data = randint(0, 999999) +def gap_encryption_change_ev_(gap, data, data_len): + stack = get_stack() + logging.debug("%s", gap_encryption_change_ev_.__name__) + + logging.debug("enc change received %r", data) + + fmt = ' 47: # This ensures clean text indentation for longer raw data, with 16 bytes per line hex_data = '\n' + indent + re.sub(r'(.{48})', r'\1\n' + indent, hex_data) @@ -215,14 +217,14 @@ def __init__(self, log_dir=None): super().__init__(log_dir) self.sock = None - def open(self, addres=BTP_ADDRESS): + def open(self, addres=BTP_ADDRESS, port=0): """Open BTP socket for IUT""" if os.path.exists(addres): os.remove(addres) if sys.platform == "win32": self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.bind((socket.gethostname(), 0)) + self.sock.bind((socket.gethostname(), port)) else: self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.bind(addres) diff --git a/autopts/pybtp/types.py b/autopts/pybtp/types.py index 17f07064b7..a0ce314c5f 100644 --- a/autopts/pybtp/types.py +++ b/autopts/pybtp/types.py @@ -89,7 +89,7 @@ class AdType: uri = 0x24 le_supp_feat = 0x27 rsi = 0x2e - + class AdFlags: le_limit_discov_mode = 0x01 @@ -284,6 +284,7 @@ class L2CAPConnectionResponse: insufficient_authorization = 2 insufficient_encryption_key_size = 3 insufficient_encryption = 4 + insufficient_secure_authentication = 5 class WIDParams(NamedTuple): diff --git a/autopts/wid/cap.py b/autopts/wid/cap.py index 3c37fda815..8797feb93e 100644 --- a/autopts/wid/cap.py +++ b/autopts/wid/cap.py @@ -972,6 +972,14 @@ def hdl_wid_419(params: WIDParams): """ return hdl_wid_400(params) +def hdl_wid_420(params: WIDParams): + """ + Please put the IUT in Non-Bondable mode. + """ + btp.gap_set_bondable_off(); + + return True + def hdl_wid_421(params: WIDParams): """ Please make sure the IUT is a BAP Unicast Server that is in an Idle state diff --git a/autopts/wid/csip.py b/autopts/wid/csip.py index 59e7bd0c14..d4a212f4bc 100644 --- a/autopts/wid/csip.py +++ b/autopts/wid/csip.py @@ -178,6 +178,8 @@ def hdl_wid_20100(params: WIDParams): btp.gap_conn(addr, addr_type) stack.gap.wait_for_connection(timeout=10, addr=addr) sec_lvl = stack.gap.gap_wait_for_sec_lvl_change(level=2, timeout=10, addr=addr) + + # Workaround for issue described by PTS Request ID 170874 if sec_lvl != 2: btp.gap_pair(addr, addr_type) stack.gap.gap_wait_for_sec_lvl_change(level=2, timeout=30, addr=addr) diff --git a/autopts/wid/gap.py b/autopts/wid/gap.py index 459566d6a5..2b7aa6124c 100644 --- a/autopts/wid/gap.py +++ b/autopts/wid/gap.py @@ -18,10 +18,12 @@ import re import struct from time import sleep +import binascii from autopts.ptsprojects.stack import get_stack, ConnParams from autopts.pybtp import types from autopts.pybtp import btp +from autopts.pybtp import defs from autopts.pybtp.types import Prop, Perm, UUID, AdType, bdaddr_reverse, WIDParams, IOCap, OwnAddrType from autopts.wid import generic_wid_hdl @@ -386,19 +388,50 @@ def hdl_wid_76(_: WIDParams): return True +GAP_DISCONN_ROUND = 0 + + def hdl_wid_77(params: WIDParams): + global GAP_DISCONN_ROUND + if params.test_case_name.startswith("GAP/BOND/BON/BV-04-C"): # PTS sends WID before IUT finishes encryption # This is a temporary workaround. Ultimately # we should wait for an event here or submit a PTS Issue. sleep(10) try: - btp.gap_wait_for_connection(5) - btp.gap_disconn() + if params.test_case_name in ['GAP/DM/LEP/BV-09-C']: + get_stack().gap.wait_for_connection(timeout=5, conn_count=2) + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + else: + btp.gap_wait_for_connection(5) + + if params.test_case_name in ['GAP/SEC/SEM/BV-05-C', 'GAP/SEC/SEM/BV-50-C', + 'GAP/SEC/SEM/BV-07-C', 'GAP/SEC/SEM/BV-51-C', + 'GAP/SEC/SEM/BV-52-C', 'GAP/SEC/SEM/BV-09-C', + 'GAP/SEC/SEM/BV-53-C', 'GAP/DM/BON/BV-01-C', + 'GAP/SEC/SEM/BV-54-C', 'GAP/SEC/SEM/BV-55-C', + 'GAP/DM/LEP/BV-17-C', 'GAP/SEC/SEM/BV-06-C']: + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + elif params.test_case_name in ['GAP/DM/LEP/BV-20-C', 'GAP/DM/LEP/BV-13-C']: + if GAP_DISCONN_ROUND == 1: + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + else: + btp.gap_disconn() + elif params.test_case_name in ['GAP/DM/LEP/BV-22-C', 'GAP/DM/LEP/BV-18-C']: + if GAP_DISCONN_ROUND == 1: + btp.gap_disconn() + else: + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + else: + btp.gap_disconn() except types.BTPError: logging.debug("Ignoring expected error on disconnect") else: btp.gap_wait_for_disconnection(30) + + GAP_DISCONN_ROUND = GAP_DISCONN_ROUND + 1 + return True @@ -518,7 +551,18 @@ def hdl_wid_108(params: WIDParams): hdl_wid_227(params, 7) stack.gap.delay_mmi = True - btp.gap_pair() + if params.test_case_name in ['GAP/SEC/SEM/BV-50-C', 'GAP/SEC/SEM/BV-51-C', + 'GAP/SEC/SEM/BV-52-C', 'GAP/SEC/SEM/BV-53-C', + 'GAP/SEC/SEM/BV-54-C', 'GAP/SEC/SEM/BV-55-C']: + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + else: + btp.gap_pair() + + if params.test_case_name in ['GAP/SEC/SEM/BV-52-C', 'GAP/SEC/SEM/BV-53-C']: + passkey = stack.gap.get_passkey() + if passkey != None: + btp.gap_passkey_confirm_rsp(btp.pts_addr_get(), defs.BTP_BR_ADDRESS_TYPE, passkey) + return True @@ -1293,9 +1337,19 @@ def hdl_wid_243(_: WIDParams): return True -def hdl_wid_265(_: WIDParams): +def hdl_wid_265(params: WIDParams): # Please initiate a link encryption with the Lower Tester. - btp.gap_pair() + if params.test_case_name in ['GAP/SEC/SEM/BI-12-C', 'GAP/SEC/SEM/BI-06-C', + 'GAP/SEC/SEM/BI-17-C', 'GAP/SEC/SEM/BI-18-C']: + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + elif params.test_case_name in ['GAP/SEC/SEM/BI-07-C', 'GAP/SEC/SEM/BI-19-C']: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, + level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_3) + elif params.test_case_name in ['GAP/SEC/SEM/BI-08-C']: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, + level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_4) + else: + btp.gap_pair() return True @@ -1480,6 +1534,7 @@ def hdl_wid_2000(_: WIDParams): def hdl_wid_2001(params: WIDParams): """ The secureId is [passkey] + Or, Please verify the passKey is correct: [passkey] """ pattern = r'[\d]{6}' passkey = re.search(pattern, params.description)[0] @@ -1487,10 +1542,32 @@ def hdl_wid_2001(params: WIDParams): bd_addr = btp.pts_addr_get() bd_addr_type = btp.pts_addr_type_get() + if params.test_case_name in ['GAP/IDLE/BON/BV-04-C', 'GAP/IDLE/BON/BV-06-C', + 'GAP/SEC/SEM/BV-06-C', 'GAP/SEC/SEM/BV-07-C', + 'GAP/SEC/SEM/BV-51-C', 'GAP/SEC/SEM/BV-09-C', + 'GAP/SEC/SEM/BV-53-C', 'GAP/SEC/SEM/BV-11-C', + 'GAP/SEC/SEM/BV-12-C', 'GAP/SEC/SEM/BV-13-C', + 'GAP/SEC/SEM/BV-14-C', 'GAP/SEC/SEM/BV-15-C', + 'GAP/SEC/SEM/BV-47-C', 'GAP/SEC/SEM/BV-48-C', + 'GAP/SEC/SEM/BV-49-C', 'GAP/SEC/SEM/BV-16-C', + 'GAP/SEC/SEM/BV-17-C', 'GAP/SEC/SEM/BV-18-C', + 'GAP/SEC/SEM/BV-54-C', 'GAP/SEC/SEM/BV-19-C', + 'GAP/SEC/SEM/BV-20-C', 'GAP/SEC/SEM/BV-55-C', + 'GAP/SEC/SEM/BI-03-C', 'GAP/SEC/SEM/BI-07-C', + 'GAP/SEC/SEM/BI-31-C', 'GAP/SEC/SEM/BI-16-C', + 'GAP/SEC/SEM/BI-04-C', 'GAP/SEC/SEM/BI-19-C', + 'GAP/SEC/SEM/BI-08-C', 'GAP/SEC/SEM/BI-27-C', + 'GAP/SEC/SEM/BI-32-C', 'GAP/SEC/SEM/BI-26-C', + 'GAP/DM/LEP/BV-13-C']: + bd_addr_type = defs.BTP_BR_ADDRESS_TYPE + if stack.gap.get_passkey() is None: return False - btp.gap_passkey_entry_rsp(bd_addr, bd_addr_type, passkey) + if 'Please verify the passKey is correct' in params.description: + btp.gap_passkey_confirm_rsp(bd_addr, bd_addr_type, passkey) + else: + btp.gap_passkey_entry_rsp(bd_addr, bd_addr_type, passkey) return True @@ -1529,16 +1606,562 @@ def hdl_wid_20001(_: WIDParams): return True -def hdl_wid_20115(_: WIDParams): +def hdl_wid_20115(params: WIDParams): + if params.test_case_name in ['GAP/DM/LEP/BI-01-C', 'GAP/SEC/SEM/BI-32-C']: + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + return True + btp.gap_disconn() return True -def hdl_wid_20100(_: WIDParams): +def hdl_wid_20100(params: WIDParams): btp.gap_conn() + if params.test_case_name in ['GAP/DM/LEP/BV-20-C', 'GAP/DM/LEP/BV-17-C', + 'GAP/DM/LEP/BV-18-C', 'GAP/DM/LEP/BV-13-C']: + btp.gap_pair() return True def hdl_wid_2142(_: WIDParams): btp.gap_conn() return True + + +def hdl_wid_31(_: WIDParams): + ''' + Please make IUT not discoverable. Press OK to continue. + ''' + btp.gap_set_nondiscov() + return True + + +def hdl_wid_32(_: WIDParams): + ''' + Please make IUT limited discoverable. Press OK to continue. + ''' + btp.gap_set_limdiscov() + return True + + +def hdl_wid_160(_: WIDParams): + ''' + Please set IUT to limited discovery mode. Lower tester is continue using + GIAC to Inquiry and waiting for Inquiry result. + ''' + btp.gap_set_limdiscov() + return True + + +def hdl_wid_145(_: WIDParams): + ''' + Waiting for limited discovery to time out so it is not able to discover IUT. + ''' + return True + + +GAP_TEST_WID_33_ROUND = 0 + + +def hdl_wid_33(params: WIDParams): + ''' + Please make IUT general discoverable. + ''' + global GAP_TEST_WID_33_ROUND + + btp.gap_set_nondiscov() + btp.gap_set_gendiscov() + + if (params.test_case_name in ['GAP/SEC/SEM/BV-10-C']) or (params.test_case_name in ['GAP/SEC/SEM/BI-24-C'] and GAP_TEST_WID_33_ROUND == 1): + # ALT1 - Responder the test results in pass when the IUT initiates the Secure Simple + # Pairing procedure autonomously before the Lower Tester initiates the L2CAP connection. + btp.gap_wait_for_connection() + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + btp.gap_wait_for_sec_lvl_change(2) + + GAP_TEST_WID_33_ROUND = GAP_TEST_WID_33_ROUND + 1 + + return True + + +def hdl_wid_34(_: WIDParams): + ''' + Please make IUT not connectable. Press OK to continue. + ''' + btp.gap_set_nonconn() + return True + + +def hdl_wid_105(_: WIDParams): + ''' + Please make IUT connectable. Press OK to continue. + ''' + btp.gap_set_conn() + btp.gap_set_gendiscov() + return True + + +def hdl_wid_222(_: WIDParams): + ''' + Please initiate a BR/EDR security authentication and pairing with interaction of HCI commands. + ''' + return True + + +def hdl_wid_146(_: WIDParams): + ''' + Please start general inquiry. Click 'Yes' If IUT does discovers PTS and ready for PTS to + initiate a create connection otherwise click 'No'. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='general') + sleep(10) + btp.gap_stop_discov() + return btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE) + + +def hdl_wid_147(_: WIDParams): + ''' + Please start limited inquiry. Click 'Yes' If IUT does discovers PTS otherwise click 'No'. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='limited') + sleep(10) + btp.gap_stop_discov() + return btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE) + + +def hdl_wid_164(_: WIDParams): + ''' + Please confirm that IUT is in Idle mode with security mode 4. Press OK when IUT is ready to + start device discovery. + ''' + return True + + +def hdl_wid_165(params: WIDParams): + ''' + Please confirm that IUT has discovered PTS and retrieved its name 'PTS-GAP-E449'. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='general') + sleep(10) + btp.gap_stop_discov() + + pattern = re.compile(r"'(.*)'") + macthed = pattern.findall(params.description) + if not macthed: + logging.error("parsing error") + return False + + name = macthed[0] + name = binascii.hexlify(name.encode()).decode() + + return btp.check_scan_rep_and_rsp(name, name) + + +GAP_TEST_WID_102_ROUND = 0 + +def hdl_wid_102(params: WIDParams): + ''' + Please send an HCI connect request to establish a basic rate connection after the IUT + discovers the Lower Tester over BR and LE. + ''' + + global GAP_TEST_WID_102_ROUND + + if params.test_case_name in ['GAP/SEC/SEM/BI-11-C', 'GAP/SEC/SEM/BI-02-C', + 'GAP/SEC/SEM/BI-03-C', 'GAP/SEC/SEM/BI-14-C', + 'GAP/SEC/SEM/BI-15-C', 'GAP/SEC/SEM/BI-16-C', + 'GAP/SEC/SEM/BI-04-C']: + return True + + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='general') + sleep(10) + btp.gap_stop_discov() + + if not btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE): + return False + + btp.gap_conn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + if params.test_case_name in ['GAP/DM/LEP/BV-09-C']: + get_stack().gap.wait_for_connection(timeout=30, conn_count=2) + else: + btp.gap_wait_for_connection() + + GAP_TEST_WID_102_ROUND = GAP_TEST_WID_102_ROUND + 1 + + if GAP_TEST_WID_102_ROUND > 1 and params.test_case_name in ['GAP/SEC/SEM/BI-32-C']: + return True + + if params.test_case_name in ['GAP/IDLE/BON/BV-05-C', 'GAP/IDLE/BON/BV-06-C', + 'GAP/SEC/SEM/BV-50-C', 'GAP/SEC/SEM/BV-06-C', + 'GAP/SEC/SEM/BV-07-C', 'GAP/SEC/SEM/BV-51-C', + 'GAP/SEC/SEM/BV-52-C', 'GAP/SEC/SEM/BV-09-C', + 'GAP/SEC/SEM/BV-53-C', 'GAP/DM/BON/BV-01-C', + 'GAP/SEC/SEM/BV-18-C', 'GAP/SEC/SEM/BV-54-C', + 'GAP/SEC/SEM/BV-19-C', 'GAP/SEC/SEM/BV-55-C', + 'GAP/SEC/SEM/BI-12-C', 'GAP/SEC/SEM/BI-06-C', + 'GAP/SEC/SEM/BI-07-C', 'GAP/SEC/SEM/BI-17-C', + 'GAP/SEC/SEM/BI-18-C', 'GAP/SEC/SEM/BI-19-C', + 'GAP/SEC/SEM/BI-08-C', 'GAP/DM/LEP/BV-09-C', + 'GAP/DM/LEP/BV-10-C', 'GAP/DM/LEP/BV-12-C', + 'GAP/DM/LEP/BV-15-C', 'GAP/DM/LEP/BV-17-C', + 'GAP/DM/LEP/BV-22-C', 'GAP/DM/LEP/BV-18-C', + 'GAP/SEC/SEM/BI-27-C', 'GAP/SEC/SEM/BI-26-C', + 'GAP/SEC/SEM/BI-25-C', 'GAP/DM/LEP/BV-13-C']: + return True + + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + + if params.test_case_name in ['GAP/SEC/SEM/BV-25-C', 'GAP/SEC/SEM/BV-30-C']: + passkey = get_stack().gap.get_passkey() + if passkey != None: + btp.gap_passkey_confirm_rsp(btp.pts_addr_get(), defs.BTP_BR_ADDRESS_TYPE, passkey) + + return True + + +def hdl_wid_264(_: WIDParams): + ''' + Please send L2CAP Connection Request to PTS. + ''' + stack = get_stack() + l2cap = stack.l2cap + btp.l2cap_conn(None, defs.BTP_BR_ADDRESS_TYPE, l2cap.psm, l2cap.initial_mtu) + return True + + +def hdl_wid_166(_: WIDParams): + ''' + Please order the IUT to go in connectable mode and in security mode 4. Press OK to continue. + ''' + return True + + +def hdl_wid_251(_: WIDParams): + ''' + Please send L2CAP Connection Response to PTS. + ''' + return True + + +def hdl_wid_231(_: WIDParams): + ''' + Please start the Bonding Procedure in bondable mode. + After Bonding Procedure is completed, please send a disconnect request to terminate connection. + ''' + btp.gap_wait_for_sec_lvl_change(level=2) + btp.gap_disconn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + return True + + +GAP_TEST_WID_103_ROUND = 0 + + +def hdl_wid_103(params: WIDParams): + ''' + Please initiate BR/EDR security authentication and pairing to establish a service level + enforced security! + After that, please create the service channel using L2CAP Connection Request. + ''' + global GAP_TEST_WID_103_ROUND + + stack = get_stack() + br_psm = 0x1001 + br_psm_2 = 0x2001 + + stack.gap.set_passkey(None) + + if not stack.gap.is_connected(): + btp.gap_conn(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + btp.gap_wait_for_connection() + + if params.test_case_name in ['GAP/SEC/SEM/BV-09-C', 'GAP/SEC/SEM/BV-53-C']: + if GAP_TEST_WID_103_ROUND == 0: + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + else: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, + mode=defs.BTP_GAP_CMD_PAIR_V2_MODE_4, + level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_3) + + if GAP_TEST_WID_103_ROUND == 0: + passkey = stack.gap.get_passkey() + if passkey != None: + btp.gap_passkey_confirm_rsp(btp.pts_addr_get(), defs.BTP_BR_ADDRESS_TYPE, passkey) + stack.l2cap_init(br_psm_2, stack.l2cap.initial_mtu) + btp.l2cap_conn(None, defs.BTP_BR_ADDRESS_TYPE, stack.l2cap.psm, stack.l2cap.initial_mtu) + else: + stack.l2cap_init(br_psm, stack.l2cap.initial_mtu) + btp.l2cap_conn(None, defs.BTP_BR_ADDRESS_TYPE, stack.l2cap.psm, stack.l2cap.initial_mtu) + else: + if params.test_case_name in ['GAP/SEC/SEM/BV-07-C', 'GAP/SEC/SEM/BV-52-C']: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, + mode=defs.BTP_GAP_CMD_PAIR_V2_MODE_4, + level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_3) + else: + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + + if params.test_case_name in ['GAP/SEC/SEM/BV-52-C']: + passkey = stack.gap.get_passkey() + if passkey != None: + btp.gap_passkey_confirm_rsp(btp.pts_addr_get(), defs.BTP_BR_ADDRESS_TYPE, passkey) + + l2cap = stack.l2cap + btp.l2cap_conn(None, defs.BTP_BR_ADDRESS_TYPE, l2cap.psm, l2cap.initial_mtu) + + GAP_TEST_WID_103_ROUND = GAP_TEST_WID_103_ROUND + 1 + return True + + +def hdl_wid_167(_: WIDParams): + ''' + Please start simple pairing procedure. + ''' + return True + + +def hdl_wid_151(_: WIDParams): + ''' + Please set IUT into bondable mode. Press OK to continue. + ''' + btp.gap_set_bondable_on() + return True + + +def hdl_wid_20117(params: WIDParams): + ''' + Please start encryption. Use previously distributed key if available. + Description: Verify that the Implementation Under Test (IUT) can + successfully start and complete encryption. + ''' + btp.gap_pair(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE) + if params.test_case_name in ['GAP/DM/LEP/BV-18-C']: + passkey = get_stack().gap.get_passkey() + if passkey != None: + btp.gap_passkey_confirm_rsp(btp.pts_addr_get(), defs.BTP_BR_ADDRESS_TYPE, passkey) + return True + + +def hdl_wid_36(_: WIDParams): + ''' + Please start general discovery over BR/EDR and over LE. If IUT discovers PTS + with both BR/EDR and LE method, press OK. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='general') + btp.gap_start_discov(transport='le', discov_type='passive', mode='general') + sleep(10) + btp.gap_stop_discov() + + if not btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE): + return False + + if not btp.check_discov_results(): + return False + + get_stack().gap.reset_discovery() + return True + + +def hdl_wid_7(_: WIDParams): + ''' + Please start limited discovery over BR/EDR and over LE. If IUT discovers PTS + with both BR/EDR and LE method, press OK. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='limited') + btp.gap_start_discov(transport='le', discov_type='passive', mode='limited') + sleep(10) + btp.gap_stop_discov() + + if not btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE): + return False + + if not btp.check_discov_results(): + return False + + get_stack().gap.reset_discovery() + return True + + +def hdl_wid_123(_: WIDParams): + ''' + Please start limited discovery over BR/EDR and over LE. If IUT does not discovers PTS + with both BR/EDR and LE method, press OK. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='limited') + btp.gap_start_discov(transport='le', discov_type='passive', mode='limited') + sleep(10) + btp.gap_stop_discov() + + if btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE): + return False + + if btp.check_discov_results(): + return False + + get_stack().gap.reset_discovery() + return True + + +def hdl_wid_86(_: WIDParams): + ''' + Please start device name discovery over BR/EDR . If IUT discovers PTS, press OK to continue. + ''' + btp.gap_start_discov(transport='bredr', discov_type='passive', mode='general') + sleep(10) + btp.gap_stop_discov() + + if not btp.check_discov_results(addr_type=defs.BTP_BR_ADDRESS_TYPE): + return False + get_stack().gap.reset_discovery() + return True + + +def hdl_wid_252(_: WIDParams): + ''' + Please send L2CAP Connection Response with Security Blocked to PTS. + ''' + return True + + +def hdl_wid_220(_: WIDParams): + ''' + Please confirm IUT rejects the Upper Tester's request to establish a channel to access the + service on the Lower Tester + Click Yes, if rejected + Click No, if not rejected. + ''' + stack = get_stack() + if stack.gap.wait_for_disconnection(timeout=3): + # ACL connection has been disconnect due to the AUTH failed + return True + l2cap = stack.l2cap + btp.l2cap_conn(None, defs.BTP_BR_ADDRESS_TYPE, l2cap.psm, l2cap.initial_mtu) + if stack.l2cap.wait_for_connection(chan_id=2, timeout=30): + return False + return True + + +def hdl_wid_255(_: WIDParams): + ''' + Please bring IUT to Security Mode 2. Press OK to continue. + ''' + return True + + +def hdl_wid_266(params: WIDParams): + ''' + Please confirm that the IUT signals to the Upper Tester that the channel establishment + failure after link encryption. + Click 'Yes' If there is channel establishment failure otherwise click 'No'. + ''' + if params.test_case_name in ['GAP/SEC/SEM/BI-27-C']: + return not get_stack().gap.gap_wait_for_encrypted() + + btp.gap_wait_for_disconnection() + return True + + +def hdl_wid_256(_: WIDParams): + ''' + Please bring IUT to Mode 4 level 1 security and make IUT general discoverable. + Press OK to continue. + ''' + return True + + +def hdl_wid_260(_: WIDParams): + ''' + Please bring IUT to Security Mode 4 level 1. Press OK to continue. + ''' + return True + + +def hdl_wid_257(_: WIDParams): + ''' + Please bring IUT to Mode 4 level 2 security and make IUT general discoverable. + Press OK to continue. + ''' + return True + + +def hdl_wid_261(_: WIDParams): + ''' + Please bring IUT to Security Mode 4 level 2. Press OK to continue. + ''' + return True + + +def hdl_wid_258(_: WIDParams): + ''' + Please bring IUT to Mode 4 level 3 security and make IUT general discoverable. + Press OK to continue. + ''' + return True + + +def hdl_wid_262(_: WIDParams): + ''' + Please bring IUT to Security Mode 4 level 3. Press OK to continue. + ''' + return True + + +def hdl_wid_259(_: WIDParams): + ''' + Please bring IUT to Mode 4 level 4 security and make IUT general discoverable. + Press OK to continue. + ''' + return True + + +def hdl_wid_263(_: WIDParams): + ''' + Please bring IUT to Security Mode 4 level 4. Press OK to continue. + ''' + return True + + +def hdl_wid_213(_: WIDParams): + ''' + Please make sure the IUT does initiate the BR secure connection pairing proccess. + Click OK when ready. + ''' + return True + + +def hdl_wid_221(_: WIDParams): + ''' + Please initiate BR/EDR Secure Simple Pairing then LE Secure Connections pairing for + this test case. + ''' + return True + + +def hdl_wid_217(_: WIDParams): + ''' + Please initiate security after upgrade the LTK to authenticated. Click OK when ready. + ''' + btp.gap_pair_v2(level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_4) + return True + + +def hdl_wid_216(_: WIDParams): + ''' + Please initiate security after upgrade the BR/EDR link key to authenticated. + Click OK when ready. + ''' + return True + + +def hdl_wid_273(params: WIDParams): + ''' + Please trigger channel creation. Expect to perform link encryption before channel creation. + ''' + if params.test_case_name in ['GAP/SEC/SEM/BI-25-C']: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_2) + return True + + if params.test_case_name in ['GAP/SEC/SEM/BI-26-C']: + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_3) + return True + + btp.gap_pair_v2(bd_addr_type=defs.BTP_BR_ADDRESS_TYPE, level=defs.BTP_GAP_CMD_PAIR_V2_LEVEL_4) + return True diff --git a/autopts/wid/gatt.py b/autopts/wid/gatt.py index 4a14402363..ce183603a1 100644 --- a/autopts/wid/gatt.py +++ b/autopts/wid/gatt.py @@ -704,15 +704,15 @@ def hdl_wid_52(params: WIDParams): if attr.uuid == UUID.CEP: (value_read,) = struct.unpack(" + Command parameters: Address_Type (1 octet) + Address (6 octets) + Mode (1 octet) + Level (1 octet) + Flags (1 octet) + Return Parameters: + + This command is used to initiate security with remote. If + peer is already paired IUT is expected to enable security + (encryption) with peer. If peer is not paired IUT shall + start pairing process. + + Valid Mode: + 0x01 = Security Mode 1 + 0x02 = Security Mode 2 + 0x03 = Security Mode 3 + 0x04 = Security Mode 4 + 0xFF = Any Mode + + Valid Level: + 0x00 = Security Level 0 + 0x01 = Security Level 1 + 0x02 = Security Level 2 + 0x03 = Security Level 3 + 0x04 = Security Level 4 + 0xFF = Any Level + + Possible values for the Flags parameter are a bit-wise OR + of the following bits: + 0 = Force pairing procedure + + In case of an error, the error response will be returned. + Events: Opcode 0x80 - New Settings event @@ -842,3 +881,14 @@ Events: This event can be sent after IUT received Periodic Advertising Sync Transfer was received. + + Opcode 0x91 - Encryption Change Received event + + Controller Index: + Event parameters: Address_Type (1 octet) + Address (6 octets) + Enabled (1 octet) + Key_Size (1 octet) + + This event can be sent after IUT received encryption change event was received. + The parameter `Enabled` is the flag whether the link is encrypted. diff --git a/doc/btp_l2cap.txt b/doc/btp_l2cap.txt index 4468b9f33d..fdf01dbf02 100644 --- a/doc/btp_l2cap.txt +++ b/doc/btp_l2cap.txt @@ -115,6 +115,7 @@ Commands and responses: 0x02 = Insufficient authorization 0x03 = Insufficient encryption key size 0x04 = Insufficient encryption + 0x05 = Insufficient secure authentication In case of an error, the error response will be returned. diff --git a/doc/btp_mesh_node.txt b/doc/btp_mesh_node.txt index 0e00f786fc..436e81b882 100644 --- a/doc/btp_mesh_node.txt +++ b/doc/btp_mesh_node.txt @@ -1317,10 +1317,10 @@ Commands and responses: Opcode 0x72 - IUT Proxy Private Identity Enable Controller Index: - Command parameters: + Command parameters: Enabled (1 octet) Response parameters: - This command is used to enable Proxy Private Identity of the IUT + This command is used to enable or to disable Proxy Private Identity of the IUT Opcode 0x73 - On-Demand Private Proxy Get diff --git a/doc/overview.txt b/doc/overview.txt index 8587081cdb..67daf9dd37 100644 --- a/doc/overview.txt +++ b/doc/overview.txt @@ -56,6 +56,10 @@ response. Or the opcode 0x00 for an error is returned. Events opcodes start from 0x80. +For BR support, if the field "Address_Type" of the command is "0xe0", it means +that the address is a BR address and the command should be transmitted on the +BR transport. + All fields are in little-endian byte order (least significant byte first). Controller Index can have a special value to indicate that diff --git a/doc/tutorials/create_workspace.md b/doc/tutorials/create_workspace.md index 272e72e101..1f840f83b4 100644 --- a/doc/tutorials/create_workspace.md +++ b/doc/tutorials/create_workspace.md @@ -2,50 +2,76 @@ To create a PTS workspace (.pqw6 file) follow below steps: -[1. Create Launch Studio project](#create-launch-studio-project) +[1. Qualification Workspace - Getting Started](#create-launch-studio-project) [2. Generate PTS workspace from ICSes](#generate-pts-workspace-from-icses) -## Create Launch Studio project +## Qualification Workspace - Getting Started -Log in to the https://www.bluetooth.com. Go to the My Blue -> My Test Plans. -The page will redirect you to Launch Studio. https://launchstudio.bluetooth.com. -In Getting Started tab, create a new project by clicking "Start the Bluetooth -Qualification Process with Required Testing". At Project Basics tab, fill the -required fields e.g.: +Log in to the https://www.bluetooth.com. Go to the My Blue -> Qualification Workspace. +The page will redirect you to Bluetooth Qualification Process. https://qualification.bluetooth.com/. +In Getting Started tab, create a new product by clicking "Start the Bluetooth +Qualification Process". -![](images/launch_studio_new_project_basics.png) +![](images/bluetooth_getting_started.png) -Save and continue to Layer Selection. Select as many layers/profiles as you know -that will be tested. If you are not sure, do not worry. The mandatory ones will -be marked by Consistency Checker, and the project can always be edited later -to add or remove profiles. +On Product Details screen, the user defines a new Bluetooth project (Design) +that will be part of the qualified product. +In this step, it is possible to define the product name, description, +model number, and publication date (either current or future). +Additionally, a product website can be provided, and the visibility settings for +other users can be configured. -![](images/launch_studio_layer_selection_core.png) +It is possible to import several products by selecting the appropriate option "Import multiple Products" +or add individual Product. +To proceed to the next step you need to confirm the stage by selecting the "Save and go to Specify Design" button. -Save and continue to ICS Selection. On the left panel there are all the selected -profiles. Each profile has its own set of ICSes. The Consistency Checker has -selected automatically some of the mandatory ICSes. But some still have to be -selected manually, because of the multiple variants of some features. +![](images/bluetooth_qualification_process_new_product.png) -![](images/launch_studio_ics_selection.png) +On Specify the Design screen is option of include any existing Design in Product. +![](images/bluetooth_specify_the_design.png) -Check which of the mandatory ICSes remain by clicking the Consistency Check: +By selecting the "Yes, I do" option you can specify which DN or QDID can be used. +![](images/bluetooth_specify_the_design_yes.png) -![](images/launch_studio_ics_selection_consistency_checker.png) +While by selecting the "No, I do not" option it is possible to choose the recommended TCRL +and advanced settings. +in the lower part of the view there is an option to import ICS +"Import from a file" by indicating the appropriate file, or selecting the option +"No, I'II do that myself" which gives the user the option to choose what will be +included in ICS. +![](images/bluetooth_specify_the_design_no.png) -To resolve all remaining mandatory ICSes it is convenient to follow and repeat -the below steps until the Consistency Check no longer displays missing dependencies: -- resolve manually ICSes of features with multiple variants, -- click on the Consistency Check to auto-select/recalculate remaining mandatory ICSes. +Proceeding further using the "Save and go to the Layer Selection" button will open the next step -If you enable some optional ICSes, new mandatory ICSes to resolve may appear. -Remember to save the project from time to time, because any accidental tab refresh -will waste all your work. +![](images/bluetooth_layer_selection.png) -After selecting all mandatory and optional ICSes, finally save and continue to -Testing tab. Here the project ICSes can be exported to a .pts file that will be -needed to generate a valid PTS workspace file. +On Layer Selection screen, +in the first option we can determine whether we want to +specify the desired Core Configuration for the new Design. +- Option No - it only informs us about the need for further Core Configuration manual configuration. +- Option Yes - gives us the ability to automatically complete the Layer Selection by choosing the options that interest us. + +![](images/bluetooth_layer_selection_yes.png) + +"Save and go to ICS Selection" button allows us to move on to the next ICS selection view. + +depending on the options we have selected in the "Layer Selection" view, +the ICS view will allow us to add or remove the selected test +![](images/bluetooth_ics_selection.png) + +On ICS Selection screen, the user selects Bluetooth-specific Capabilities—in this case, +“802.11 Protocol Adaptation Layer”—as part of the Implementation Conformance Statement (ICS). +Each capability is assigned a status: Mandatory (M), Optional (O), or Conditional (C). +Once the appropriate options are selected, a Consistency Check can be run +and the test plan or documentation can be continued. + +To export an ICS .pts file that can be loaded into PTS, you need to expand the "Support Tools" submenu and select the "Export Draft" option. +It is also possible to export a Draft file. + +The location of the submenu is shown in the screenshot below. + +![](images/bluetooth_ics_selection_export.png) ## Generate PTS workspace from ICSes diff --git a/doc/tutorials/images/bluetooth_getting_started.png b/doc/tutorials/images/bluetooth_getting_started.png new file mode 100644 index 0000000000..90cad04d41 Binary files /dev/null and b/doc/tutorials/images/bluetooth_getting_started.png differ diff --git a/doc/tutorials/images/bluetooth_ics_selection.png b/doc/tutorials/images/bluetooth_ics_selection.png new file mode 100644 index 0000000000..e1b28110a5 Binary files /dev/null and b/doc/tutorials/images/bluetooth_ics_selection.png differ diff --git a/doc/tutorials/images/bluetooth_ics_selection_export.png b/doc/tutorials/images/bluetooth_ics_selection_export.png new file mode 100644 index 0000000000..396fa172d4 Binary files /dev/null and b/doc/tutorials/images/bluetooth_ics_selection_export.png differ diff --git a/doc/tutorials/images/bluetooth_layer_selection.png b/doc/tutorials/images/bluetooth_layer_selection.png new file mode 100644 index 0000000000..702d3cce9b Binary files /dev/null and b/doc/tutorials/images/bluetooth_layer_selection.png differ diff --git a/doc/tutorials/images/bluetooth_layer_selection_yes.png b/doc/tutorials/images/bluetooth_layer_selection_yes.png new file mode 100644 index 0000000000..62cff3afe5 Binary files /dev/null and b/doc/tutorials/images/bluetooth_layer_selection_yes.png differ diff --git a/doc/tutorials/images/bluetooth_qualification_process_new_product.png b/doc/tutorials/images/bluetooth_qualification_process_new_product.png new file mode 100644 index 0000000000..8d8cb6ee6f Binary files /dev/null and b/doc/tutorials/images/bluetooth_qualification_process_new_product.png differ diff --git a/doc/tutorials/images/bluetooth_specify_the_design.png b/doc/tutorials/images/bluetooth_specify_the_design.png new file mode 100644 index 0000000000..f32daa562f Binary files /dev/null and b/doc/tutorials/images/bluetooth_specify_the_design.png differ diff --git a/doc/tutorials/images/bluetooth_specify_the_design_no.png b/doc/tutorials/images/bluetooth_specify_the_design_no.png new file mode 100644 index 0000000000..6da21170c0 Binary files /dev/null and b/doc/tutorials/images/bluetooth_specify_the_design_no.png differ diff --git a/doc/tutorials/images/bluetooth_specify_the_design_yes.png b/doc/tutorials/images/bluetooth_specify_the_design_yes.png new file mode 100644 index 0000000000..39eff21c7b Binary files /dev/null and b/doc/tutorials/images/bluetooth_specify_the_design_yes.png differ diff --git a/doc/tutorials/images/create_or_import_design_product.png b/doc/tutorials/images/create_or_import_design_product.png new file mode 100644 index 0000000000..f3b985c7d0 Binary files /dev/null and b/doc/tutorials/images/create_or_import_design_product.png differ diff --git a/doc/tutorials/images/launch_studio_ics_selection.png b/doc/tutorials/images/launch_studio_ics_selection.png deleted file mode 100644 index 6a02b22b51..0000000000 Binary files a/doc/tutorials/images/launch_studio_ics_selection.png and /dev/null differ diff --git a/doc/tutorials/images/launch_studio_ics_selection_consistency_checker.png b/doc/tutorials/images/launch_studio_ics_selection_consistency_checker.png deleted file mode 100644 index 5101487f44..0000000000 Binary files a/doc/tutorials/images/launch_studio_ics_selection_consistency_checker.png and /dev/null differ diff --git a/doc/tutorials/images/launch_studio_layer_selection_core.png b/doc/tutorials/images/launch_studio_layer_selection_core.png deleted file mode 100644 index d2ea4c4e5d..0000000000 Binary files a/doc/tutorials/images/launch_studio_layer_selection_core.png and /dev/null differ diff --git a/doc/tutorials/images/launch_studio_layer_selection_core_2.png b/doc/tutorials/images/launch_studio_layer_selection_core_2.png deleted file mode 100644 index 9f430625d1..0000000000 Binary files a/doc/tutorials/images/launch_studio_layer_selection_core_2.png and /dev/null differ diff --git a/doc/tutorials/images/launch_studio_new_project_basics.png b/doc/tutorials/images/launch_studio_new_project_basics.png deleted file mode 100644 index eb3f831e83..0000000000 Binary files a/doc/tutorials/images/launch_studio_new_project_basics.png and /dev/null differ diff --git a/errata/common.yaml b/errata/common.yaml index 054a4b5757..2998da9358 100644 --- a/errata/common.yaml +++ b/errata/common.yaml @@ -11,3 +11,5 @@ GATT/SR/GAI/BV-01-C: ES-27410 L2CAP/COS/CED/BI-13-C: Request ID 170155 L2CAP/COS/CED/BI-16-C: Request ID 170155 L2CAP/COS/CED/BI-17-C: Request ID 170155 + +CSIP/CL/SP/BV-07-C: Request ID 170874 diff --git a/errata/zephyr.yaml b/errata/zephyr.yaml index 7cfaf31700..d622b9c0d0 100644 --- a/errata/zephyr.yaml +++ b/errata/zephyr.yaml @@ -14,7 +14,6 @@ MCP/CL/CGGIT/CHA/BV-12-C: Request ID 28478 MCP/CL/CGGIT/CHA/BV-14-C: Request ID 28478 MCP/CL/CGGIT/CHA/BV-15-C: Request ID 28478 -BASS/SR/CP/BV-21-C: https://github.com/zephyrproject-rtos/zephyr/issues/64871 No API to request the Broadcast Code without sync TBS/SR/CP/BV-10-C: https://github.com/zephyrproject-rtos/zephyr/issues/41738 Disallow Join not possible at runtime TBS/SR/SPE/BI-05-C: TSE24847 GTBS/SR/CP/BV-10-C: https://github.com/zephyrproject-rtos/zephyr/issues/41738 Disallow Join not possible at runtime diff --git a/tools/cron/autopts_cron.py b/tools/cron/autopts_cron.py index 48ff371064..eebba9616a 100644 --- a/tools/cron/autopts_cron.py +++ b/tools/cron/autopts_cron.py @@ -79,7 +79,7 @@ class AutoPTSMagicTagParser(argparse.ArgumentParser): def __init__(self, add_help=True): super().__init__(description='Github Magic Tag parser', add_help=add_help) - self.add_argument("included", nargs='+', default=None, + self.add_argument("included", nargs='*', default=[], help="abc") self.add_argument("-e", "--excluded", nargs='+', default=[], @@ -192,6 +192,8 @@ def autopts_magic_tag_cb(cron, comment_info): parser = config.get('magic_tag_parser', AutoPTSMagicTagParser)() try: parsed_args = parser.parse_args(command_args) + if len(parsed_args.included) == 0 and 'default_test_cases' in config: + parsed_args.included = config['default_test_cases'].split() except BaseException as e: log(e) continue @@ -239,12 +241,24 @@ def schedule_pr_job(cron, pr_info, job_config): test_case_count = len(test_cases) if test_case_count > 0: + skipped_test_cases = [] + if ('test_case_limit_per_comment' in job_config and + job_config['test_case_limit_per_comment'] < test_case_count): + test_case_count = job_config['test_case_limit_per_comment'] + skipped_test_cases = test_cases[test_case_count:] + test_cases = test_cases[:test_case_count] + job_config['included'] = test_cases + if job_config['test_case_limit']: job_config['included'] = test_cases estimations = f', test case count: {test_case_count}, ' \ f'estimated duration: {est_duration}' estimations += f'
Test cases to be run{"
".join(test_cases)}
\n' + + if skipped_test_cases: + estimations += (f'
Test cases skipped due to limit, count: {len(skipped_test_cases)}' + f'{"
".join(skipped_test_cases)}
\n') else: estimations = f', test case count: estimation not available' diff --git a/tools/cron/common.py b/tools/cron/common.py index da09775c6a..d9cf011773 100644 --- a/tools/cron/common.py +++ b/tools/cron/common.py @@ -590,6 +590,7 @@ def _run_test(config): test_cases_completed = False backup = config['auto_pts'].get('use_backup', False) timeguard = config['cron']['test_run_timeguard'] + startup_fail_count = config['cron'].get('startup_fail_max_count', 2) results_file_path = config['file_paths']['TC_STATS_JSON_FILE'] all_stats_file_path = config['file_paths']['ALL_STATS_JSON_FILE'] report_file_path = config['file_paths']['REPORT_TXT_FILE'] @@ -626,11 +627,17 @@ def _run_test(config): if not test_cases_completed and not os.path.exists(results_file_path): if timedelta(seconds=current_time - last_check_time) > timedelta(seconds=timeguard): + if startup_fail_count == 0: + log("Test run has not been started on time. No more retries...") + break + + startup_fail_count -= 1 log("Test run has not been started on time. Restarting processes...") srv_process, bot_process = _restart_processes(config) continue + startup_fail_count = config['cron'].get('startup_fail_max_count', 2) last_check_time = current_time if (not test_cases_completed and diff --git a/tools/cron/github_cron.py b/tools/cron/github_cron.py index 874baa24c0..3be543f391 100644 --- a/tools/cron/github_cron.py +++ b/tools/cron/github_cron.py @@ -205,7 +205,7 @@ def run(self): github_pr_number = int(re.findall(r'(?<=pull\/)\d+?(?=#)', comment['html_url'])[0]) comment_info = { 'pr_number': github_pr_number, - 'comment_body': comment['body'], + 'comment_body': comment['body'].strip(), 'magic_tag': comment['magic_tag'], 'html_url': comment['html_url'], } diff --git a/tools/generate_profile.py b/tools/generate_profile.py index deb9a497b5..f3eeb30c58 100644 --- a/tools/generate_profile.py +++ b/tools/generate_profile.py @@ -306,7 +306,6 @@ def wait_dummyevent_completed_ev(self, addr_type, addr, timeout, remove=True): }, f'{AUTOPTS_REPO}/autopts/ptsprojects/stack/layers/__init__.py': {1: f"from .{profile_name_lower} import *\n"}, f'{AUTOPTS_REPO}/autopts/ptsprojects/stack/stack.py': { - 1: f' "{profile_name_upper}": 1 << defs.BTP_SERVICE_ID_{profile_name_upper},\n', 2: f" self.{profile_name_lower} = None\n", 3: f" def {profile_name_lower}_init(self):\n self.{profile_name_lower} = {profile_name_upper}()\n\n", 4: f" if self.{profile_name_lower}:\n self.{profile_name_lower}_init()\n\n", @@ -314,20 +313,24 @@ def wait_dummyevent_completed_ev(self, addr_type, addr, timeout, remove=True): f'{AUTOPTS_REPO}/autopts/wid/__init__.py': {1: f"from .{profile_name_lower} import {profile_name_lower}_wid_hdl\n"}, f'{AUTOPTS_REPO}/autopts/pybtp/btp/btp.py': { 1: f"""def core_reg_svc_{profile_name_lower}(): - logging.debug("%s", core_reg_svc_{profile_name_lower}.__name__) - - iutctl = get_iut() - iutctl.btp_socket.send_wait_rsp(*CORE['{profile_name_lower}_reg']) + core_reg_svc_univ("{profile_name_lower}_reg", "{profile_name_upper}") """, 2: f"from .{profile_name_lower} import {profile_name_upper}_EV\n", 3: f" defs.BTP_SERVICE_ID_{profile_name_upper}: ({profile_name_upper}_EV, stack.{profile_name_lower}),\n", - 4: f" \"{profile_name_lower}_reg\": (defs.BTP_SERVICE_ID_CORE, defs.BTP_CORE_CMD_REGISTER_SERVICE,\n" - f" defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_{profile_name_upper}),\n", }, f'{AUTOPTS_REPO}/autopts/pybtp/btp/__init__.py': {1: f"from autopts.pybtp.btp.{profile_name_lower} import *\n"}, f'{AUTOPTS_REPO}/doc/overview.txt': {1: f" {profile_id} {profile_name_upper} Service\n"}, + f'{AUTOPTS_REPO}/autopts/pybtp/common.py': { + 1: f""" "{profile_name_upper}": {'{'} + "supported_commands": defs.BTP_{profile_name_upper}_CMD_READ_SUPPORTED_COMMANDS + {'}'}, +""", + 2: f""" "{profile_name_lower}_reg": (defs.BTP_SERVICE_ID_{profile_name_upper}, defs.BTP_{profile_name_upper}_CMD_REGISTER_SERVICE, + defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_{profile_name_upper}), +""", + }, }