From 4b69a72b14042f1e0a19bde91791befe613ef41b Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Mon, 9 Sep 2024 10:43:10 +0800 Subject: [PATCH] SDP: Enable BTP Service SDP Add Service ID `BTP_SERVICE_ID_SDP = 0x1F` for SDP. Add SDP command `SDP_SEARCH_REQ`, `SDP_ATTR_REQ`, and `SDP_SEARCH_ATTR_REQ`. Add SDP event `SDP_EV_SERVICE_RECORD_HANDLE`. Handle BTP SDP command `SDP_SEARCH_REQ` to start service search transaction. Handle the event `SDP_EV_SERVICE_RECORD_HANDLE` to get service record handle. Handle BTP SDP command `SDP_ATTR_REQ` to start service attribution transaction. Handle BTP SDP command `SDP_SEARCH_ATTR_REQ` to start service search transaction. Signed-off-by: Lyle Zhu --- autopts/ptsprojects/stack/layers/__init__.py | 1 + autopts/ptsprojects/stack/layers/sdp.py | 69 +++ autopts/ptsprojects/stack/stack.py | 9 +- autopts/ptsprojects/zephyr/__init__.py | 1 + autopts/ptsprojects/zephyr/sdp.py | 505 +++++++++++++++++++ autopts/ptsprojects/zephyr/sdp_wid.py | 72 +++ autopts/pybtp/btp/__init__.py | 1 + autopts/pybtp/btp/btp.py | 15 +- autopts/pybtp/btp/sdp.py | 99 ++++ autopts/pybtp/defs.py | 6 + 10 files changed, 775 insertions(+), 3 deletions(-) create mode 100644 autopts/ptsprojects/stack/layers/sdp.py create mode 100644 autopts/ptsprojects/zephyr/sdp.py create mode 100644 autopts/ptsprojects/zephyr/sdp_wid.py create mode 100644 autopts/pybtp/btp/sdp.py diff --git a/autopts/ptsprojects/stack/layers/__init__.py b/autopts/ptsprojects/stack/layers/__init__.py index 4e6a23e041..a6a23d4bc3 100644 --- a/autopts/ptsprojects/stack/layers/__init__.py +++ b/autopts/ptsprojects/stack/layers/__init__.py @@ -41,4 +41,5 @@ from .tmap import * from .ots import * from .pbp import * +from .sdp import * # GENERATOR append 1 diff --git a/autopts/ptsprojects/stack/layers/sdp.py b/autopts/ptsprojects/stack/layers/sdp.py new file mode 100644 index 0000000000..c6d980d87c --- /dev/null +++ b/autopts/ptsprojects/stack/layers/sdp.py @@ -0,0 +1,69 @@ +# +# auto-pts - The Bluetooth PTS Automation Framework +# +# Copyright (c) 2017, Intel Corporation. +# Copyright (c) 2024, Codecoup. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +import logging + +from autopts.ptsprojects.stack.common import Property, wait_for_event +from autopts.pybtp.types import AdType, IOCap, Addr + + +class SDP: + def __init__(self): + + self.service_record_handles = {} + + def add_service_record_handles(self, addr, handle): + handles = [] + if addr in self.service_record_handles.keys(): + handles.append(self.service_record_handles[addr]) + handles.append(handle) + self.service_record_handles[addr] = handles + + def has_service_record_handle(self, addr=None): + if addr and addr in self.service_record_handles.keys(): + if len(self.service_record_handles[addr]) > 0: + handle = self.service_record_handles[addr][0] + return handle + else: + if len(self.service_record_handles) > 0: + addr = list(self.service_record_handles.keys())[0] + if len(self.service_record_handles[addr]) > 0: + handle = self.service_record_handles[addr][0] + return handle + return 0 + + def get_service_record_handle(self, addr=None): + if addr and addr in self.service_record_handles.keys(): + if len(self.service_record_handles[addr]) > 0: + handle = self.service_record_handles[addr][0] + del self.service_record_handles[addr][0] + return handle + else: + if len(self.service_record_handles) > 0: + addr = list(self.service_record_handles.keys())[0] + if len(self.service_record_handles[addr]) > 0: + handle = self.service_record_handles[addr][0] + del self.service_record_handles[addr][0] + return handle + return 0 + + def sdp_wait_for_service_record_handle(self, timeout=5, addr=None): + handle = self.get_service_record_handle(addr) + if handle != 0: + return handle + + wait_for_event(timeout, lambda: self.has_service_record_handle(addr) > 0) + + return self.get_service_record_handle(addr) diff --git a/autopts/ptsprojects/stack/stack.py b/autopts/ptsprojects/stack/stack.py index b49aea84a1..39057e2ac6 100644 --- a/autopts/ptsprojects/stack/stack.py +++ b/autopts/ptsprojects/stack/stack.py @@ -53,6 +53,7 @@ "TMAP": 1 << defs.BTP_SERVICE_ID_TMAP, "OTS": 1 << defs.BTP_SERVICE_ID_OTS, "PBP": 1 << defs.BTP_SERVICE_ID_PBP, + "SDP": 1 << defs.BTP_SERVICE_ID_SDP, # GENERATOR append 1 } @@ -89,6 +90,7 @@ def __init__(self): self.tmap = None self.ots = None self.pbp = None + self.sdp = None # GENERATOR append 2 def is_svc_supported(self, svc): @@ -191,6 +193,8 @@ def ots_init(self): def pbp_init(self): self.pbp = PBP() + def sdp_init(self): + self.sdp = SDP() # GENERATOR append 3 def cleanup(self): @@ -223,7 +227,7 @@ def cleanup(self): if self.micp: self.micp_init() - + if self.ccp: self.ccp_init() @@ -275,6 +279,9 @@ def cleanup(self): if self.pbp: self.pbp_init() + if self.sdp: + self.sdp_init() + # GENERATOR append 4 diff --git a/autopts/ptsprojects/zephyr/__init__.py b/autopts/ptsprojects/zephyr/__init__.py index 209e3faf46..5a291da4cb 100644 --- a/autopts/ptsprojects/zephyr/__init__.py +++ b/autopts/ptsprojects/zephyr/__init__.py @@ -46,6 +46,7 @@ import autopts.ptsprojects.zephyr.tbs import autopts.ptsprojects.zephyr.tmap import autopts.ptsprojects.zephyr.ots +import autopts.ptsprojects.zephyr.sdp # GENERATOR append 1 # Constants diff --git a/autopts/ptsprojects/zephyr/sdp.py b/autopts/ptsprojects/zephyr/sdp.py new file mode 100644 index 0000000000..6650897b34 --- /dev/null +++ b/autopts/ptsprojects/zephyr/sdp.py @@ -0,0 +1,505 @@ +# +# auto-pts - The Bluetooth PTS Automation Framework +# +# Copyright (c) 2017, Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# + +"""SDP test cases""" + +from autopts.pybtp import btp +from autopts.pybtp.types import Addr, IOCap +from autopts.client import get_unique_name +from autopts.ptsprojects.stack import get_stack +from autopts.ptsprojects.testcase import TestFunc +from autopts.ptsprojects.zephyr.ztestcase import ZTestCase +from autopts.ptsprojects.zephyr.sdp_wid import sdp_wid_hdl + + +def set_pixits(ptses): + """Setup SDP profile PIXITS for workspace. Those values are used for test + case if not updated within test case. + + PIXITS always should be updated accordingly to project and newest version of + PTS. + + ptses -- list of PyPTS instances""" + + pts = ptses[0] + + # Set SDP common PIXIT values + pts.set_pixit("SDP", "TSPX_security_enabled", "FALSE") + pts.set_pixit("SDP", "TSPX_delete_link_key", "FALSE") + pts.set_pixit("SDP", "TSPX_bd_addr_iut", "DEADBEEFDEAD") + pts.set_pixit("SDP", "TSPX_class_of_device_pts", "200404") + pts.set_pixit("SDP", "TSPX_class_of_device_test_pts_initiator", "TRUE") + pts.set_pixit("SDP", "TSPX_limited_inquiry_used", "FALSE") + pts.set_pixit("SDP", "TSPX_pin_code", "0000") + pts.set_pixit("SDP", "TSPX_time_guard", "200000") + pts.set_pixit("SDP", "TSPX_device_search_time", "20") + pts.set_pixit("SDP", "TSPX_use_implicit_send", "TRUE") + pts.set_pixit("SDP", "TSPX_secure_simple_pairing_pass_key_confirmation", "FALSE") + + pts.set_pixit("SDP", "TSPX_sdp_service_search_pattern", "0100") + pts.set_pixit("SDP", "TSPX_sdp_additional_protocol_descriptor_list", "") + pts.set_pixit("SDP", "TSPX_sdp_bluetooth_profile_descriptor_list", "") + pts.set_pixit("SDP", "TSPX_sdp_browse_group_list", "") + pts.set_pixit("SDP", "TSPX_sdp_client_exe_url", "") + pts.set_pixit("SDP", "TSPX_sdp_documentation_url", "") + pts.set_pixit("SDP", "TSPX_sdp_icon_url", "") + pts.set_pixit("SDP", "TSPX_sdp_language_base_attribute_id_list", "") + pts.set_pixit("SDP", "TSPX_sdp_protocol_descriptor_list", "") + pts.set_pixit("SDP", "TSPX_sdp_provider_name", "") + pts.set_pixit("SDP", "TSPX_sdp_service_availability", "") + pts.set_pixit("SDP", "TSPX_sdp_service_data_base_state", "0100") + pts.set_pixit("SDP", "TSPX_sdp_service_description", "") + pts.set_pixit("SDP", "TSPX_sdp_service_id", "") + pts.set_pixit("SDP", "TSPX_sdp_service_info_time_to_live", "") + pts.set_pixit("SDP", "TSPX_sdp_version_number_list", "0100") + pts.set_pixit("SDP", "TSPX_sdp_service_name", "") + pts.set_pixit("SDP", "TSPX_sdp_service_record_state", "") + pts.set_pixit("SDP", "TSPX_sdp_unsupported_attribute_id", "EEEE") + + +def test_cases(ptses): + """Returns a list of SDP test cases + ptses -- list of PyPTS instances""" + + pts = ptses[0] + + pts_bd_addr = pts.q_bd_addr + + stack = get_stack() + iut_device_name = get_unique_name(pts) + stack.gap_init(name=iut_device_name) + + pre_conditions = [TestFunc(btp.core_reg_svc_gap), + TestFunc(stack.gap_init, iut_device_name), + TestFunc(btp.gap_read_ctrl_info), + TestFunc(btp.core_reg_svc_sdp), + TestFunc(stack.sdp_init), + TestFunc(lambda: pts.update_pixit_param( + "SDP", "TSPX_bd_addr_iut", + stack.gap.iut_addr_get_str())), + TestFunc(lambda: pts.update_pixit_param( + "SDP", "TSPX_delete_link_key", "TRUE")), + # FIXME Find better place to store PTS bdaddr + TestFunc(btp.set_pts_addr, pts_bd_addr, Addr.le_public)] + + custom_test_cases = [ + ZTestCase("SDP", "SDP/SR/SS/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SS/BV-03-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SS/BI-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SS/BI-02-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BI-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BI-02-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BI-03-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-20-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-03-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-04-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-05-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-06-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-07-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-08-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-09-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-10-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-11-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-12-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-13-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-14-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-15-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-16-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-17-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-18-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-19-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SA/BV-21-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-02-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-03-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-04-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-06-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-10-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-11-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-07-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-09-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-12-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-13-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-14-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-15-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-16-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-17-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-18-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-19-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-08-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-20-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-21-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-22-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BV-23-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BI-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/SSA/BI-02-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/BRW/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/SR/BRW/BV-02-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/CL/SA/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.no_input_output), + TestFunc(lambda: pts.update_pixit_param( + "SDP", "TSPX_class_of_device_test_pts_initiator", "FALSE")), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ZTestCase("SDP", "SDP/CL/SSA/BV-01-C", + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.keyboard_only), + TestFunc(lambda: pts.update_pixit_param( + "SDP", "TSPX_class_of_device_test_pts_initiator", "FALSE")), + TestFunc(lambda: btp.gap_set_conn()), + TestFunc(lambda: btp.gap_set_bondable_off()), + TestFunc(lambda: btp.gap_set_gendiscov()),], + generic_wid_hdl=sdp_wid_hdl), + ] + + test_case_name_list = pts.get_test_case_list('SDP') + tc_list = [] + + for tc_name in test_case_name_list: + instance = ZTestCase('SDP', tc_name, + pre_conditions + + [TestFunc(btp.gap_set_io_cap, IOCap.display_only)], + generic_wid_hdl=sdp_wid_hdl) + + for custom_tc in custom_test_cases: + if tc_name == custom_tc.name: + instance = custom_tc + break + + tc_list.append(instance) + + return tc_list diff --git a/autopts/ptsprojects/zephyr/sdp_wid.py b/autopts/ptsprojects/zephyr/sdp_wid.py new file mode 100644 index 0000000000..700f55cca5 --- /dev/null +++ b/autopts/ptsprojects/zephyr/sdp_wid.py @@ -0,0 +1,72 @@ +# +# auto-pts - The Bluetooth PTS Automation Framework +# +# Copyright (c) 2017, Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# + +import logging + +from autopts.wid import generic_wid_hdl +from autopts.pybtp import btp +from autopts.ptsprojects.zephyr.iutctl import get_iut +from autopts.pybtp.types import WIDParams +from autopts.ptsprojects.stack import get_stack +from time import sleep + +log = logging.debug + + +def sdp_wid_hdl(wid, description, test_case_name): + log(f'{sdp_wid_hdl.__name__}, {wid}, {description}, {test_case_name}') + return generic_wid_hdl(wid, description, test_case_name, [__name__]) + +def hdl_wid_6000(_: WIDParams): + return True + +def hdl_wid_6002(_: WIDParams): + return True + +def hdl_wid_6001(_: WIDParams): + return True + +def hdl_wid_6003(_: WIDParams): + return True + +def hdl_wid_1(_: WIDParams): + return True + +def hdl_wid_102(params: WIDParams): + btp.gap_start_discov(transport='bredr') + sleep(30) # Give some time to discover devices + if btp.check_discov_results(btp.pts_addr_type_get(), btp.pts_addr_get()): + btp.clear_discov_results() + btp.gap_conn_br() + btp.gap_wait_for_connection() + if params.test_case_name in ["SDP/CL/SSA/BV-01-C"]: + btp.sdp_search_attr_req(uuid=0x0100) + else: + # btp.sdp_search_req(uuid=0x0100) + # handle = btp.sdp_wait_for_service_record_handle() + handle = 0x10002 + if handle != 0: + btp.sdp_attr_req(service_record_handle=handle) + else: + return False + return True + +def hdl_wid_6008(_: WIDParams): + btp.sdp_search_attr_req(uuid=0x0100) + return True + +def hdl_wid_6007(_: WIDParams): + btp.sdp_search_req(uuid=0x0100) + return True diff --git a/autopts/pybtp/btp/__init__.py b/autopts/pybtp/btp/__init__.py index eee1fd0d30..2f74a4afb5 100644 --- a/autopts/pybtp/btp/__init__.py +++ b/autopts/pybtp/btp/__init__.py @@ -46,4 +46,5 @@ from autopts.pybtp.btp.tmap import * from autopts.pybtp.btp.ots import * from autopts.pybtp.btp.pbp import * +from autopts.pybtp.btp.sdp import * # GENERATOR append 1 diff --git a/autopts/pybtp/btp/btp.py b/autopts/pybtp/btp/btp.py index fa7db4d78f..03bf1130a9 100644 --- a/autopts/pybtp/btp/btp.py +++ b/autopts/pybtp/btp/btp.py @@ -131,6 +131,8 @@ def read_supp_svcs(): defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_OTS), "pbp_reg": (defs.BTP_SERVICE_ID_CORE, defs.CORE_REGISTER_SERVICE, defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_PBP), + "sdp_reg": (defs.BTP_SERVICE_ID_CORE, defs.CORE_REGISTER_SERVICE, + defs.BTP_INDEX_NONE, defs.BTP_SERVICE_ID_SDP), # GENERATOR append 4 "read_supp_cmds": (defs.BTP_SERVICE_ID_CORE, defs.CORE_READ_SUPPORTED_COMMANDS, @@ -637,7 +639,7 @@ def core_reg_svc_ccp(): iutctl = get_iut() iutctl.btp_socket.send_wait_rsp(*CORE['ccp_reg']) - + def core_reg_svc_cas(): logging.debug("%s", core_reg_svc_cas.__name__) @@ -690,7 +692,7 @@ def core_reg_svc_tmap(): iutctl = get_iut() iutctl.btp_socket.send_wait_rsp(*CORE['tmap_reg']) - + def core_reg_svc_tbs(): logging.debug("%s", core_reg_svc_tbs.__name__) @@ -713,6 +715,13 @@ def core_reg_svc_pbp(): iutctl.btp_socket.send_wait_rsp(*CORE['pbp_reg']) +def core_reg_svc_sdp(): + logging.debug("%s", core_reg_svc_sdp.__name__) + + iutctl = get_iut() + iutctl.btp_socket.send_wait_rsp(*CORE['sdp_reg']) + + # GENERATOR append 1 def core_reg_svc_rsp_succ(): @@ -815,6 +824,7 @@ def init(get_iut_method): from .tmap import TMAP_EV from .ots import OTS_EV from .pbp import PBP_EV +from .sdp import SDP_EV # GENERATOR append 2 from autopts.pybtp.iutctl_common import set_event_handler @@ -855,6 +865,7 @@ def event_handler(hdr, data): defs.BTP_SERVICE_ID_TMAP: (TMAP_EV, stack.tmap), defs.BTP_SERVICE_ID_OTS: (OTS_EV, stack.ots), defs.BTP_SERVICE_ID_PBP: (PBP_EV, stack.pbp), + defs.BTP_SERVICE_ID_SDP: (SDP_EV, stack.sdp), # GENERATOR append 3 } diff --git a/autopts/pybtp/btp/sdp.py b/autopts/pybtp/btp/sdp.py new file mode 100644 index 0000000000..b1d4c898a7 --- /dev/null +++ b/autopts/pybtp/btp/sdp.py @@ -0,0 +1,99 @@ +# +# auto-pts - The Bluetooth PTS Automation Framework +# +# Copyright (c) 2017, Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# + +"""Wrapper around btp messages. The functions are added as needed.""" + +import binascii +import logging +import re +import struct +from random import randint + +from autopts.ptsprojects.stack import get_stack, ConnParams +from autopts.pybtp import defs +from autopts.pybtp.types import BTPError, gap_settings_btp2txt, addr2btp_ba, Addr, OwnAddrType, AdDuration, AdType +from autopts.pybtp.btp.btp import pts_addr_get, pts_addr_type_get, lt2_addr_get, lt2_addr_type_get, btp_hdr_check, \ + CONTROLLER_INDEX, CONTROLLER_INDEX_NONE, set_pts_addr, set_lt2_addr, LeAdv, get_iut_method as get_iut, lt3_addr_type_get, lt3_addr_get, \ + set_lt3_addr + +SDP = { + "search_req": (defs.BTP_SERVICE_ID_SDP, defs.SDP_SEARCH_REQ, + CONTROLLER_INDEX_NONE), + "attr_req": (defs.BTP_SERVICE_ID_SDP, defs.SDP_ATTR_REQ, + CONTROLLER_INDEX_NONE), + "search_attr_req": (defs.BTP_SERVICE_ID_SDP, defs.SDP_SEARCH_ATTR_REQ, + CONTROLLER_INDEX_NONE), +} + +def sdp_search_req(bd_addr=None, uuid=0x0100): + logging.debug("%s %r %r", sdp_search_req.__name__, bd_addr, uuid) + iutctl = get_iut() + + data_ba = bytearray() + bd_addr_ba = addr2btp_ba(pts_addr_get(bd_addr)) + + data_ba.extend(bd_addr_ba) + data_ba.extend(struct.pack('H', uuid)) + + iutctl.btp_socket.send_wait_rsp(*SDP['search_req'], data=data_ba) + + +def sdp_attr_req(bd_addr=None, service_record_handle=0): + logging.debug("%s %r %r", sdp_search_attr_req.__name__, bd_addr, service_record_handle) + iutctl = get_iut() + + data_ba = bytearray() + bd_addr_ba = addr2btp_ba(pts_addr_get(bd_addr)) + + data_ba.extend(bd_addr_ba) + data_ba.extend(struct.pack('I', service_record_handle)) + + iutctl.btp_socket.send_wait_rsp(*SDP['attr_req'], data=data_ba) + +def sdp_search_attr_req(bd_addr=None, uuid=0x0100): + logging.debug("%s %r %r", sdp_search_attr_req.__name__, bd_addr, uuid) + iutctl = get_iut() + + data_ba = bytearray() + bd_addr_ba = addr2btp_ba(pts_addr_get(bd_addr)) + + data_ba.extend(bd_addr_ba) + data_ba.extend(struct.pack('H', uuid)) + + iutctl.btp_socket.send_wait_rsp(*SDP['search_attr_req'], data=data_ba) + +def sdp_wait_for_service_record_handle(timeout=30, addr=None): + stack = get_stack() + + return stack.sdp.sdp_wait_for_service_record_handle(timeout, addr) + +def sdp_service_record_handle_ev_(sdp, data, data_len): + logging.debug("%s %r", sdp_service_record_handle_ev_.__name__, data) + + data_fmt = '<6sI' + + print(data) + addr, handle, = struct.unpack_from(data_fmt, data) + addr = binascii.hexlify(addr[::-1]).decode() + + _sdp_add_service_record_handles(addr, handle) + +SDP_EV = { + defs.SDP_EV_SERVICE_RECORD_HANDLE: sdp_service_record_handle_ev_ +} + +def _sdp_add_service_record_handles(addr, handle): + stack = get_stack() + stack.sdp.add_service_record_handles(addr, handle) \ No newline at end of file diff --git a/autopts/pybtp/defs.py b/autopts/pybtp/defs.py index 536075cbd6..cd503393db 100644 --- a/autopts/pybtp/defs.py +++ b/autopts/pybtp/defs.py @@ -53,6 +53,7 @@ def BIT(bit): BTP_SERVICE_ID_TMAP = 0x1c BTP_SERVICE_ID_OTS = 0x1d BTP_SERVICE_ID_PBP = 0x1e +BTP_SERVICE_ID_SDP = 0x1f # GENERATOR append 1 BTP_STATUS_SUCCESS = 0x00 @@ -899,4 +900,9 @@ def BIT(bit): PBP_BROADCAST_SCAN_STOP = 0x05 PBP_EV_PUBLIC_BROADCAST_ANNOUNCEMENT_FOUND = 0x80 +SDP_SEARCH_REQ = 0x01 +SDP_ATTR_REQ = 0x02 +SDP_SEARCH_ATTR_REQ = 0x03 +SDP_EV_SERVICE_RECORD_HANDLE = 0x81 + # GENERATOR append 2