1.1.0版本

This commit is contained in:
xinzhu.yin
2026-04-16 16:51:05 +08:00
commit c157e774e5
333 changed files with 70759 additions and 0 deletions

BIN
UniTAP/libs/lib_tsi/TSI.dll Normal file

Binary file not shown.

View File

@@ -0,0 +1,3 @@
from UniTAP.libs.lib_tsi.tsi_types import *
from UniTAP.libs.lib_tsi.tsi import *
from UniTAP.libs.lib_tsi.tsi_io import BaseIO, DeviceIO, PortIO

624
UniTAP/libs/lib_tsi/tsi.py Normal file
View File

@@ -0,0 +1,624 @@
import warnings
from UniTAP.libs.lib_tsi.tsi_private_types import *
from UniTAP.libs.lib_helper import OS_Requirements, lib_method_wrapper
from ctypes import c_char_p, c_uint32, c_void_p, c_int32, POINTER, create_string_buffer, byref, \
sizeof, c_uint64, c_ubyte, c_bool
from UniTAP.utils import tsi_logging as logging
CTYPES_TYPE_LIST = [c_char_p, c_uint32, c_void_p, c_int32, c_uint64, c_ubyte, c_bool]
callback = None
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class TSIWrapper(metaclass=Singleton):
_TSI_CURRENT_VERSION = 12
def __init__(self):
self._TSI_DEV_SetSearchMask = None
self._TSI_GetParsedEventData = None
self._TSI_RemoveEventParser = None
self._TSI_CreateEventParser = None
self._TSIX_STLOG_GetMessageData = None
self._TSIX_STLOG_WaitMessage = None
self._TSIX_PORT_GetTestInfo = None
self._TSIX_PORT_GetTestCount = None
self._TSIX_TS_RunTest = None
self._TSIX_TS_AbortTests = None
self._TSIX_PORT_Deselect = None
self._TSIX_PORT_Select = None
self._TSI_MISC_GetErrorDescription = None
self._TSIX_TS_GetConfigItem = None
self._TSI2_TS_GetConfigItem = None
self._TSIX_TS_SetConfigItem = None
self._TSI2_TS_SetConfigItem = None
self._TSIX_DEV_CloseDevice = None
self._TSIX_DEV_GetDeviceRoleCount = None
self._TSIX_DEV_GetDeviceRoleName = None
self._TSIX_DEV_RescanDevices = None
self._TSIX_DEV_SelectRole = None
self._TSIX_DEV_OpenDevice = None
self._TSIX_DEV_GetDeviceName = None
self._TSI_DEV_GetDeviceName = None
self._TSI_DEV_GetDeviceCount = None
self._TSI_Clean = None
self._TSIX_Init = None
self._TSI_Init = None
self.lib = OS_Requirements("TSI").get_lib()
self.__setup_callback()
def __del__(self):
self.deinitialize()
def initialize(self):
self._TSIX_Init = lib_method_wrapper(self.lib.TSIX_Init, [POINTER(TSI_INIT_CONFIGURATION)],
TSI_RESULT)
self._TSI_Init = lib_method_wrapper(self.lib.TSI_Init, [c_uint32], TSI_RESULT)
self._TSI_Clean = lib_method_wrapper(self.lib.TSI_Clean, [], TSI_RESULT)
self._TSI_DEV_GetDeviceCount = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceCount, [],
TSI_RESULT)
self._TSIX_DEV_GetDeviceName = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceName,
[TSI_DEVICE_ID, c_char_p, c_uint32],
TSI_RESULT)
self._TSIX_DEV_OpenDevice = lib_method_wrapper(self.lib.TSIX_DEV_OpenDevice,
[TSI_DEVICE_ID, POINTER(TSI_RESULT)],
TSI_HANDLE)
self._TSIX_DEV_SelectRole = lib_method_wrapper(self.lib.TSIX_DEV_SelectRole,
[TSI_HANDLE, c_int32],
TSI_RESULT)
self._TSIX_DEV_RescanDevices = lib_method_wrapper(self.lib.TSIX_DEV_RescanDevices,
[c_int32, c_int32, c_int32],
TSI_RESULT)
self._TSIX_DEV_GetDeviceRoleName = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceRoleName,
[TSI_HANDLE, c_int32, c_char_p,
c_uint32],
TSI_RESULT)
self._TSIX_DEV_GetDeviceRoleCount = lib_method_wrapper(self.lib.TSIX_DEV_GetDeviceRoleCount,
[TSI_HANDLE, ],
TSI_RESULT)
self._TSIX_DEV_CloseDevice = lib_method_wrapper(self.lib.TSIX_DEV_CloseDevice,
[TSI_HANDLE, ],
TSI_RESULT)
self._TSI2_TS_SetConfigItem = lib_method_wrapper(self.lib.TSI2_TS_SetConfigItem,
[TSI_HANDLE, TSI_LOGICAL_PORT,
TSI_CONFIG_ID,
c_void_p, c_uint32],
TSI_RESULT)
self._TSIX_TS_SetConfigItem = lib_method_wrapper(self.lib.TSIX_TS_SetConfigItem,
[TSI_HANDLE, TSI_CONFIG_ID, c_void_p,
c_uint32],
TSI_RESULT)
self._TSI2_TS_GetConfigItem = lib_method_wrapper(self.lib.TSI2_TS_GetConfigItem,
[TSI_HANDLE, TSI_LOGICAL_PORT,
TSI_CONFIG_ID,
c_void_p, c_uint32],
TSI_RESULT)
self._TSIX_TS_GetConfigItem = lib_method_wrapper(self.lib.TSIX_TS_GetConfigItem,
[TSI_HANDLE, TSI_CONFIG_ID, c_void_p,
c_uint32],
TSI_RESULT)
self._TSI_MISC_GetErrorDescription = lib_method_wrapper(
self.lib.TSI_MISC_GetErrorDescription,
[TSI_RESULT, c_char_p, c_uint32],
TSI_RESULT)
self._TSIX_PORT_Select = lib_method_wrapper(self.lib.TSIX_PORT_Select,
[TSI_HANDLE, TSI_LOGICAL_PORT],
TSI_RESULT)
self._TSIX_PORT_Deselect = lib_method_wrapper(self.lib.TSIX_PORT_Deselect,
[TSI_HANDLE, TSI_LOGICAL_PORT],
TSI_RESULT)
self._TSIX_TS_RunTest = lib_method_wrapper(self.lib.TSIX_TS_RunTest,
[TSI_HANDLE, TSI_TEST_ID],
TSI_RESULT)
self._TSIX_TS_AbortTests = lib_method_wrapper(self.lib.TSIX_TS_AbortTests,
[TSI_HANDLE],
TSI_RESULT)
self._TSIX_PORT_GetTestCount = lib_method_wrapper(self.lib.TSIX_PORT_GetTestCount,
[TSI_HANDLE, TSI_LOGICAL_PORT],
TSI_RESULT)
self._TSIX_PORT_GetTestInfo = lib_method_wrapper(self.lib.TSIX_PORT_GetTestInfo,
[TSI_HANDLE, TSI_LOGICAL_PORT, c_int32,
POINTER(TSI_TEST_ID),
POINTER(c_int32), c_char_p, c_uint32],
TSI_RESULT)
self._TSIX_STLOG_WaitMessage = lib_method_wrapper(self.lib.TSIX_STLOG_WaitMessage,
[TSI_HANDLE, c_int32],
TSI_RESULT)
self._TSIX_STLOG_GetMessageData = lib_method_wrapper(self.lib.TSIX_STLOG_GetMessageData,
[TSI_HANDLE, c_char_p, c_uint32,
POINTER(c_uint32)],
TSI_RESULT)
self._TSI_CreateEventParser = lib_method_wrapper(self.lib.TSI_CreateEventParser,
[POINTER(TSI_RESULT), c_uint32],
TSI_PARSER)
self._TSI_RemoveEventParser = lib_method_wrapper(self.lib.TSI_RemoveEventParser,
[TSI_PARSER, ],
TSI_RESULT)
self._TSI_GetParsedEventData = lib_method_wrapper(self.lib.TSI_GetParsedEventData,
[TSI_PARSER, POINTER(c_ubyte), c_int32,
POINTER(c_uint64), c_char_p, c_int32,
c_char_p,
c_int32, c_char_p, c_int32, c_char_p,
c_int32],
TSI_RESULT)
self._TSI_DEV_SetSearchMask = lib_method_wrapper(self.lib.TSI_DEV_SetSearchMask,
[TSI_DEVICE_CAPS, TSI_DEVICE_CAPS],
TSI_RESULT)
return self.__TSIX_Init() if logging.is_enabled() else self.__TSI_Init()
def deinitialize(self):
return self.__TSI_Clean()
@staticmethod
def __setup_callback():
global callback
def ofp_impl(level, message):
try:
logging.log((level + 1) * 10, message.decode())
except Exception as exc:
warnings.warn(f"[UniTAP] Logger function receive exception: {exc}")
callback = TSI_USER_LOG_FUNCTION(ofp_impl)
def __TSIX_Init(self):
global callback
config = TSI_INIT_CONFIGURATION()
config.size = sizeof(config)
config.version = self._TSI_CURRENT_VERSION
config.function = callback
return self._TSIX_Init(byref(config))
def __TSI_Init(self):
return self._TSI_Init(self._TSI_CURRENT_VERSION)
def __TSI_Clean(self):
return self._TSI_Clean()
def TSIX_DEV_GetDeviceCount(self):
return self._TSI_DEV_GetDeviceCount()
def TSIX_DEV_GetDeviceName(self, device_id: int):
_device_name = create_string_buffer(TSI_NAME_SIZE)
result = self._TSIX_DEV_GetDeviceName(device_id, _device_name, TSI_NAME_SIZE)
return result, from_cstr(_device_name)
def TSIX_DEV_OpenDevice(self, device_id: int):
result = c_int32(TSI_SUCCESS)
device = self._TSIX_DEV_OpenDevice(c_uint32(device_id), byref(result))
return device
def TSIX_DEV_SelectRole(self, device, role_id: int):
return self._TSIX_DEV_SelectRole(device, role_id)
def TSIX_DEV_RescanDevices(self, search_options=1, required_caps=0, unallowed_caps=0):
return self._TSIX_DEV_RescanDevices(search_options, required_caps, unallowed_caps)
def TSIX_DEV_GetDeviceRoleName(self, device, role_id: int):
_log_string_size = c_uint32(65536)
_log_string = create_string_buffer(_log_string_size.value)
result = self._TSIX_DEV_GetDeviceRoleName(device, role_id, _log_string, _log_string_size)
return result, from_cstr(_log_string)
def TSIX_DEV_GetDeviceRoleCount(self, device):
return self._TSIX_DEV_GetDeviceRoleCount(device)
def TSIX_DEV_CloseDevice(self, device):
return self._TSIX_DEV_CloseDevice(device)
def TSIX_TS_SetPortConfigItem(self, device_handle, port_id, config_id, data, data_type=c_uint32,
data_count=1, data_size=0):
result = 0
if data_size > 0:
if type(data) == int or type(data) == bool:
_data = data_type(data)
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
byref(_data),
data_size)
elif type(data) == str:
_data = create_string_buffer(data_count)
_data.value = str.encode(data)
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
byref(_data),
data_size)
else:
if type(data) == int or type(data) == bool or type(data) == float:
_data = data_type(data)
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
byref(_data),
sizeof(_data))
elif type(data) == list or type(data) == bytearray or type(data) == tuple:
_data = (data_type * data_count)(*data)
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
byref(_data),
sizeof(_data))
elif type(data) == str:
_data = create_string_buffer(data_count)
_data.value = str.encode(data)
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id,
byref(_data),
sizeof(_data))
elif str(type(data)).find('WINFUNCTYPE') != -1 or str(type(data)).find(
'CFUNCTYPE') != -1:
result = self._TSI2_TS_SetConfigItem(device_handle, port_id, config_id, data,
sizeof(data))
elif issubclass(type(data), IntEnum):
_data = data_type(data.value)
result = self._TSI2_TS_SetConfigItem(device_handle, config_id, byref(_data),
sizeof(_data))
else:
result = TSI_ERROR_NOT_IMPLEMENTED
return result
def TSIX_TS_SetConfigItem(self, device_handle, config_id, data, data_type=c_uint32,
data_count=1,
data_size=0):
result = 0
if data_size > 0:
if type(data) == int or type(data) == bool:
_data = data_type(data)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
data_size)
elif type(data) == str:
_data = create_string_buffer(data_count)
_data.value = str.encode(data)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
data_size)
else:
if type(data) == int or type(data) == bool or type(data) == float:
_data = data_type(data)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
sizeof(_data))
elif type(data) == list or type(data) == bytearray:
_data = (data_type * data_count)(*data)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
sizeof(_data))
elif type(data) == str:
_data = create_string_buffer(data_count)
_data.value = str.encode(data)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
sizeof(_data))
elif str(type(data)).find('WINFUNCTYPE') != -1 or str(type(data)).find(
'CFUNCTYPE') != -1:
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, data, sizeof(data))
elif issubclass(type(data), IntEnum):
_data = data_type(data.value)
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(_data),
sizeof(_data))
elif issubclass(type(data), Structure):
result = self._TSIX_TS_SetConfigItem(device_handle, config_id, byref(data),
sizeof(data))
else:
result = TSI_ERROR_NOT_IMPLEMENTED
return result
def TSIX_TS_GetPortConfigItem(self, device_handle, port_id, config_id, data_type, data_count=1):
if data_type is None:
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, data_type,
data_count)
result = rv,
elif data_count > 1:
_data = (data_type * data_count)()
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, _data,
sizeof(data_type) * data_count)
if data_type == c_ubyte:
result = rv, bytearray(_data), int(rv / sizeof(data_type))
else:
result = rv, list(_data), int(rv / sizeof(data_type))
else:
_data = data_type(0)
rv = self._TSI2_TS_GetConfigItem(device_handle, port_id, config_id, byref(_data),
sizeof(_data))
if data_type in CTYPES_TYPE_LIST:
result = rv, _data.value
else:
result = rv, _data
return result
def TSIX_TS_GetConfigItem(self, device_handle, config_id, data_type, data_count=1):
if data_type is None:
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count)
result = rv,
elif data_count > 1:
_data = (data_type * data_count)()
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, _data,
sizeof(data_type) * data_count)
result = rv, _data, data_count
else:
_data = data_type(0)
rv = self._TSIX_TS_GetConfigItem(device_handle, config_id, byref(_data), sizeof(_data))
if data_type in CTYPES_TYPE_LIST:
result = rv, _data.value
else:
result = rv, _data
return result
def TSI_MISC_GetErrorDescription(self, error):
err_msg_size = 256
err_msg = create_string_buffer(err_msg_size)
result = self._TSI_MISC_GetErrorDescription(error, err_msg, err_msg_size)
return result, from_cstr(err_msg)
def TSIX_PORT_Select(self, device: TSI_HANDLE, port):
return self._TSIX_PORT_Select(device, port)
def TSIX_PORT_Deselect(self, device: TSI_HANDLE, port):
return self._TSIX_PORT_Deselect(device, port)
def TSIX_TS_RunTest(self, device: TSI_HANDLE, test_id: int):
return self._TSIX_TS_RunTest(device, c_uint32(test_id))
def TSIX_TS_AbortTests(self, device: TSI_HANDLE):
return self._TSIX_TS_AbortTests(device)
def TSIX_PORT_GetTestCount(self, device: TSI_HANDLE, port: TSI_LOGICAL_PORT):
return self._TSIX_PORT_GetTestCount(device, port)
def TSIX_PORT_GetTestInfo(self, device: TSI_HANDLE, port: TSI_LOGICAL_PORT, test_index: int):
msg_size = c_uint32(1024)
test_id = c_uint32(0)
msg_buffer = create_string_buffer(msg_size.value)
test_flags = c_int32(0)
self._TSIX_PORT_GetTestInfo(device, port, test_index, byref(test_id), byref(test_flags),
msg_buffer, msg_size)
return test_id.value, test_flags.value, from_cstr(msg_buffer)
def TSIX_STLOG_WaitMessage(self, device: TSI_HANDLE, max_wait: int):
return self._TSIX_STLOG_WaitMessage(device, c_int32(max_wait))
def TSIX_STLOG_GetMessageData(self, device: TSI_HANDLE):
msg_size = c_uint32(1024)
out_size = c_uint32(0)
msg_buffer = create_string_buffer(msg_size.value)
result = self._TSIX_STLOG_GetMessageData(device, msg_buffer, msg_size, byref(out_size))
return result, from_cstr(msg_buffer), out_size.value
def TSI_CreateEventParser(self, timestamp_res: int = 100):
result = c_int32(TSI_SUCCESS)
return self._TSI_CreateEventParser(byref(result), c_uint32(timestamp_res))
def TSI_RemoveEventParser(self, parser):
return self._TSI_RemoveEventParser(parser)
def TSI_GetParsedEventData(self, parser, data, to_dict=False):
event_data = (c_ubyte * (len(data) - 12))(*data[12:])
type_str_max_size = 128
brief_str_max_size = 256
content_str_max_size = 4096
event_source_str_max_size = 64
typeStr = create_string_buffer(type_str_max_size)
briefStr = create_string_buffer(brief_str_max_size)
contentStr = create_string_buffer(content_str_max_size)
eventSourceStr = create_string_buffer(event_source_str_max_size)
timestamp = c_uint64(0)
result = self._TSI_GetParsedEventData(parser, event_data, c_int32(len(data) - 12),
byref(timestamp),
typeStr,
type_str_max_size, briefStr,
brief_str_max_size,
contentStr, content_str_max_size, eventSourceStr,
event_source_str_max_size)
if to_dict:
return result, \
{
'timestamp': timestamp.value,
'type': from_cstr(typeStr),
'brief': from_cstr(briefStr),
'content': from_cstr(contentStr),
'source': from_cstr(eventSourceStr),
'data': data[12:]
}
else:
return result, timestamp.value, from_cstr(typeStr), from_cstr(briefStr), from_cstr(
contentStr), from_cstr(
eventSourceStr), data[12:]
def TSI_DEV_SetSearchMask(self, required_caps, unallowed_caps):
return self._TSI_DEV_SetSearchMask(required_caps, unallowed_caps)
class TSIEventParser:
def __init__(self):
self.__parser = None
self.__parse_function = None
def __enter__(self):
self.__parser = TSIWrapper().TSI_CreateEventParser()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
TSIWrapper().TSI_RemoveEventParser(self.__parser)
def parse(self, data, to_dict=False):
return TSIWrapper().TSI_GetParsedEventData(self.__parser, data, to_dict)
class TSI_INIT_CONFIGURATION(Structure):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.size = 0
self.version = 0
self.function = TSI_USER_LOG_FUNCTION()
_fields_ = [
("size", c_uint),
("version", c_uint),
("function", TSI_USER_LOG_FUNCTION),
]
def get_config_item_name(config_item) -> str:
items = globals().items()
variable_name = [k for k, v in items if v == config_item][0]
return variable_name
def from_cstr(src_str):
try:
return src_str.value.decode('cp1252')
except BaseException:
return src_str.value.decode('utf-8')
def to_cstr(src_str):
return c_char_p(src_str.encode('utf-8'))
def show_error(error_code):
if error_code >= TSI_SUCCESS:
return False
result = TSI_MISC_GetErrorDescription(error_code)
if result[0] < TSI_SUCCESS:
val = f"Error {str(error_code)}: (No description available)\n"
else:
val = f"Error {str(error_code)}: {str(result[1])}\n"
return val
def create_c_array(data, _type, _size):
buftype = _type * _size
buf = buftype()
buf.value = data
return buf
def TSIX_Init():
return TSIWrapper().initialize()
def TSI_Clean():
return TSIWrapper().deinitialize()
def TSIX_DEV_GetDeviceCount():
return TSIWrapper().TSIX_DEV_GetDeviceCount()
def TSIX_DEV_GetDeviceName(device_id: int):
return TSIWrapper().TSIX_DEV_GetDeviceName(device_id)
def TSIX_DEV_OpenDevice(device_id: int):
return TSIWrapper().TSIX_DEV_OpenDevice(device_id)
def TSIX_DEV_SelectRole(device, role_id: int):
return TSIWrapper().TSIX_DEV_SelectRole(device, role_id)
def TSIX_DEV_RescanDevices(search_options=1, required_caps=0, unallowed_caps=0):
return TSIWrapper().TSIX_DEV_RescanDevices(search_options, required_caps, unallowed_caps)
def TSIX_DEV_GetDeviceRoleName(device, role_id: int):
return TSIWrapper().TSIX_DEV_GetDeviceRoleName(device, role_id)
def TSIX_DEV_GetDeviceRoleCount(device):
return TSIWrapper().TSIX_DEV_GetDeviceRoleCount(device)
def TSIX_DEV_CloseDevice(device):
return TSIWrapper().TSIX_DEV_CloseDevice(device)
def TSIX_TS_SetPortConfigItem(device_handle, port_id, config_id, data, data_type=c_uint32,
data_count=1, data_size=0):
return TSIWrapper().TSIX_TS_SetPortConfigItem(device_handle, port_id, config_id, data,
data_type, data_count, data_size)
def TSIX_TS_SetConfigItem(device_handle, config_id, data, data_type=c_uint32, data_count=1,
data_size=0):
return TSIWrapper().TSIX_TS_SetConfigItem(device_handle, config_id, data,
data_type, data_count, data_size)
def TSIX_TS_GetPortConfigItem(device_handle, port_id, config_id, data_type, data_count=1):
return TSIWrapper().TSIX_TS_GetPortConfigItem(device_handle, port_id, config_id, data_type,
data_count)
def TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count=1):
return TSIWrapper().TSIX_TS_GetConfigItem(device_handle, config_id, data_type, data_count)
def TSI_MISC_GetErrorDescription(error):
return TSIWrapper().TSI_MISC_GetErrorDescription(error)
def TSIX_PORT_Select(device: TSI_HANDLE, port):
return TSIWrapper().TSIX_PORT_Select(device, port)
def TSIX_PORT_Deselect(device, port):
return TSIWrapper().TSIX_PORT_Deselect(device, port)
def TSIX_TS_RunTest(device: TSI_HANDLE, test_id: int):
return TSIWrapper().TSIX_TS_RunTest(device, test_id)
def TSIX_TS_AbortTests(device: TSI_HANDLE):
return TSIWrapper().TSIX_TS_AbortTests(device)
def TSIX_PORT_GetTestCount(device: TSI_HANDLE, port: TSI_LOGICAL_PORT):
return TSIWrapper().TSIX_PORT_GetTestCount(device, port)
def TSIX_PORT_GetTestInfo(device: TSI_HANDLE, port: TSI_LOGICAL_PORT, test_index: int):
return TSIWrapper().TSIX_PORT_GetTestInfo(device, port, test_index)
def TSIX_STLOG_WaitMessage(device: TSI_HANDLE, max_wait: int):
return TSIWrapper().TSIX_STLOG_WaitMessage(device, max_wait)
def TSIX_STLOG_GetMessageData(device: TSI_HANDLE):
return TSIWrapper().TSIX_STLOG_GetMessageData(device)
def TSI_CreateEventParser(timestamp_res: int = 100):
return TSIWrapper().TSI_CreateEventParser(timestamp_res)
def TSI_RemoveEventParser(parser):
return TSIWrapper().TSI_RemoveEventParser(parser)
def TSI_GetParsedEventData(parser, data, to_dict=False):
return TSIWrapper().TSI_GetParsedEventData(parser, data, to_dict)
def TSI_DEV_SetSearchMask(required_caps, unallowed_caps):
return TSIWrapper().TSI_DEV_SetSearchMask(required_caps, unallowed_caps)

View File

@@ -0,0 +1,253 @@
import weakref
from ctypes import c_uint32, c_char
from typing import Callable, Tuple, List
from enum import IntEnum
from .tsi import (TSI_HANDLE, TSI_LOGICAL_PORT, TSI_SUCCESS, \
TSIX_TS_SetConfigItem, TSIX_TS_GetConfigItem, TSIX_TS_SetPortConfigItem, \
TSIX_TS_GetPortConfigItem, TSIX_Init, TSI_Clean, TSIX_DEV_RescanDevices, \
TSIX_DEV_OpenDevice, TSIX_DEV_GetDeviceName, TSIX_DEV_GetDeviceCount,
TSIX_DEV_CloseDevice, \
TSIX_DEV_GetDeviceRoleCount, TSIX_DEV_SelectRole, TSIX_DEV_GetDeviceRoleName,
TSIX_PORT_Select, \
get_config_item_name, TSIX_TS_RunTest, TSIX_STLOG_WaitMessage,
TSIX_STLOG_GetMessageData, \
TSIX_PORT_GetTestCount, TSIX_PORT_GetTestInfo, TSI_TS_OF_MODE, \
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE, TSI_TS_OF_REQ_ID, TSI_TS_OF_CALLBACK,
TSI_FW_VERSION_TEXT,
Structure, TSI_TEST_STATUS, TSI_DEVICE_INFO_R, TSI_BUNDLE_VERSION_TEXT, \
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE_AND_RESULT, TSI_DEV_SetSearchMask,
DeviceMaskInternal, \
TSI_TEST_LOG_CONFIGURATION, TSI_TEST_ERROR_CODE_R, TSI_TEST_PASSED, TSI_TEST_FAILED,
TSI_TEST_NOT_STARTED, TSI_TEST_ABORTED, TSIX_TS_AbortTests, TSI_TEST_DLG_CONFIG)
from UniTAP.utils import tsi_logging as logging
class PortProtocol(IntEnum):
DisplayPort = 0
HDMI = 1
DisplayPortThrowUSBC = 2
class TestStatus(Structure):
_fields_ = [
("status", c_uint32, 8),
("result", c_uint32, 7),
("oper_rq", c_uint32, 1),
("error", c_uint32, 7),
("log_ovf", c_uint32, 1),
("progress", c_uint32, 8),
]
class TestDialogConfig(Structure):
_fields_ = [
("disable_auto_precessing", c_uint32, 1),
("reserved", c_uint32, 31)
]
def __init__(self, disable_auto_precessing: bool):
super().__init__()
self.disable_auto_precessing = disable_auto_precessing
class PortIO:
def __init__(self, device: TSI_HANDLE, index: TSI_LOGICAL_PORT, protocol: PortProtocol):
logging.info(f"[UniTAP] PortIO.init: {self}")
self.__device = device
self.__index = index
self.__protocol = protocol
self.active()
def __del__(self):
logging.info(f"[UniTAP] PortIO.del: {self}")
def set(self, config_id, data, data_type=c_uint32, data_count=1, data_size=0):
result = TSIX_TS_SetPortConfigItem(self.__device, self.__index, config_id, data, data_type,
data_count,
data_size)
if isinstance(data, bytearray):
logging.debug(f"[UniTAP] PortIO.set {self} {get_config_item_name(config_id)} "
f"with data: {data[:(10 if len(data) > 10 else len(data))]}[{len(data)}] "
f"({type(data)}); result: {result}")
else:
logging.debug(f"[UniTAP] PortIO.set {self} {get_config_item_name(config_id)} "
f"with data: {data} ({type(data)}); result: {result}")
return result
def get(self, config_id, data_type=c_uint32, data_count=1):
result = TSIX_TS_GetPortConfigItem(self.__device, self.__index, config_id, data_type,
data_count)
logging.debug(
f"PortIO.get {self} {get_config_item_name(config_id)} "
f"with type: {data_type}[{data_count}]; result: {result}")
return result
def active(self):
TSIX_PORT_Select(self.__device, self.__index)
def get_test_list(self) -> List[Tuple[int, int, str]]:
test_list = []
for test_id in range(self.__get_test_count()):
test_list.append(self.__get_test_info(test_id))
return test_list
def protocol(self) -> PortProtocol:
return self.__protocol
def index(self):
return self.__index
def __get_test_count(self) -> int:
return TSIX_PORT_GetTestCount(self.__device, self.__index)
def __get_test_info(self, test_id: int):
return TSIX_PORT_GetTestInfo(self.__device, self.__index, test_id)
class DeviceIO:
MAX_FW_VERSION_STR_SIZE = 65535
def __init__(self, index: int):
logging.info(f"[UniTAP] DeviceIO.init: {self}")
self.__device = TSIX_DEV_OpenDevice(index)
self.__port_io_list = [] # type: list[PortIO]
self.__current_role = None
def __del__(self):
self.__port_io_list.clear()
TSIX_DEV_CloseDevice(self.__device)
logging.info(f"[UniTAP] DeviceIO.del: {self}")
@property
def device_handle(self):
return self.__device
def set(self, config_id, data, data_type=c_uint32, data_count=1, data_size=0):
return TSIX_TS_SetConfigItem(self.__device, config_id, data, data_type, data_count,
data_size)
def get(self, config_id, data_type=c_uint32, data_count=1):
return TSIX_TS_GetConfigItem(self.__device, config_id, data_type, data_count)
def get_device_role_count(self) -> int:
return TSIX_DEV_GetDeviceRoleCount(self.__device)
def get_device_role_name(self, index) -> str:
return TSIX_DEV_GetDeviceRoleName(self.__device, index)[1]
def select_role(self, index):
logging.info(
f"[UniTAP] DeviceIO.select_role: {index}")
return TSIX_DEV_SelectRole(self.__device, index)
def create_port_io(self, index, protocol: PortProtocol) -> PortIO:
self.__port_io_list.append(PortIO(self.__device, index, protocol))
return weakref.proxy(self.__port_io_list[-1])
def set_opf_callback(self, callback: Callable):
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_MODE,
TSI_OFMODE_RUN_CALL_STRUCT_PROCEDURE_AND_RESULT)
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_REQ_ID, -1)
TSIX_TS_SetConfigItem(self.__device, TSI_TS_OF_CALLBACK, callback)
def set_opf_config(self, config: TestDialogConfig):
self.set(TSI_TEST_DLG_CONFIG, config)
def get_test_list(self) -> List[Tuple[int, int, str]]:
test_list = []
for port in self.__port_io_list:
test_list.extend(port.get_test_list())
return test_list
def run_test(self, test_id: int):
logging.info(
f"[UniTAP] DeviceIO.run_test with id: {hex(test_id)} "
f"(group={test_id >> 16 & 0xffff}; test={test_id & 0xffff})")
result = TSIX_TS_RunTest(self.__device, test_id)
if result not in [TSI_TEST_PASSED, TSI_TEST_FAILED, TSI_TEST_NOT_STARTED, TSI_TEST_ABORTED]:
result = TSI_TEST_FAILED
return result
def abort_test(self):
logging.info(f"[UniTAP] DeviceIO.abort_test")
return TSIX_TS_AbortTests(self.__device)
def set_test_config(self, config: int):
if config > 0xffffffff or config < 0:
raise ValueError("Test config value must be more than 0 and less than 0xffffffff")
TSIX_TS_SetConfigItem(self.__device, TSI_TEST_LOG_CONFIGURATION, config)
def is_log_message_available(self, max_wait_timeout=5000) -> int:
return int(TSIX_STLOG_WaitMessage(self.__device, max_wait_timeout))
def get_test_log_message(self) -> str:
return TSIX_STLOG_GetMessageData(self.__device)
def get_test_status(self) -> TestStatus:
return TSIX_TS_GetConfigItem(self.__device, TSI_TEST_STATUS, TestStatus, 1)[1]
def get_test_error_code(self) -> int:
return TSIX_TS_GetConfigItem(self.__device, TSI_TEST_ERROR_CODE_R, c_uint32, 1)[1]
def get_fw_version_string(self):
return TSIX_TS_GetConfigItem(self.__device, TSI_FW_VERSION_TEXT, c_char,
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
def get_prepared_fw_info(self):
return TSIX_TS_GetConfigItem(self.__device, TSI_DEVICE_INFO_R, c_char,
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
def get_bundle_version(self):
ver = TSIX_TS_GetConfigItem(self.__device, TSI_BUNDLE_VERSION_TEXT, c_char,
self.MAX_FW_VERSION_STR_SIZE)[1].value.decode('utf-8')
if ver == '':
ver = 'not specified (NOT FOR SHARING)'
return ver
def set_role(self, role):
self.__current_role = role
def get_role(self):
if self.__current_role is not None:
return weakref.proxy(self.__current_role)
return None
class BaseIO:
def __init__(self):
self.__ref_count = TSIX_Init()
logging.info(f"[UniTAP] BaseIO.init: {self}; Ref count: {self.__ref_count}")
TSIX_DEV_RescanDevices()
def cleanup(self):
self.__ref_count = TSI_Clean()
logging.info(f"[UniTAP] BaseIO.del: {self}; Ref count: {self.__ref_count}")
def get_device_count(self) -> int:
if self.__ref_count > 0:
return TSIX_DEV_GetDeviceCount()
logging.error("[UniTAP] BaseIO.get_device_count call without TSI_Init")
def get_device_name(self, index) -> str:
if self.__ref_count > 0:
return TSIX_DEV_GetDeviceName(index)[1]
logging.error("[UniTAP] BaseIO.get_device_name call without TSI_Init")
def get_devices_by_mask(self, require_caps: DeviceMaskInternal,
unallowed_caps: DeviceMaskInternal):
if self.__ref_count > 0:
return TSI_DEV_SetSearchMask(require_caps.value, unallowed_caps.value)
logging.error("[UniTAP] BaseIO.get_devices_by_mask call without TSI_Init")
def create_device_io(self, index: int) -> DeviceIO:
if self.__ref_count > 0:
return DeviceIO(index)
logging.error("[UniTAP] BaseIO.create_device_io call without TSI_Init")

View File

@@ -0,0 +1,140 @@
from UniTAP.libs.lib_tsi.tsi_types import *
TSI_CAP_OWNER_UNKNOWN = 0x0
TSI_CAP_OWNER_NONE = 0x1
TSI_CAP_OWNER_TEST_SYSTEM = 0x2
TSI_CAP_OWNER_PREVIEW = 0x3
TSI_CAP_OWNER = TSI_BASE_LEGACY_CAP(0x1f)
TSI_SEARCHOPTIONS_FIX_500_IN_UCDCONFIG = 0x80000000
TSI_VIDCAP_AVAILABLE_FRAME_COUNT_R = TSI_BASE_LEGACY_VIDCAP(0x1d)
TSI_VIDCAP_CAPTURE_STATUS_R = TSI_BASE_LEGACY_VIDCAP(0x1e)
TSI_VIDCAP_AVAILABLE_FRAME_COUNT = TSI_VIDCAP_AVAILABLE_FRAME_COUNT_R
TSI_CRC_MEASUREMENT_DATA_R = TSI_BASE_R_CRC_VIDEO(0x3)
TSI_AUDCAP_PACKET_HEADER_R = TSI_BASE_LEGACY_AUDCAP(0xe)
TSI_PG_ADAPTIVE_SYNC_CTRL = 0x733
TSI_PG_ADAPTIVE_SYNC_CAPS = 0x734
TSI_PG_ADAPTIVE_SYNC_STS = 0x735
TSI_PG_CAPS_R = 0x736
TSI_PG_PR_CAPS_R = 0x737
TSI_PG_PR_CTRL_W = 0x738
TSI_PG_PR_STATUS_R = 0x738
TSI_PG_PR_CFG = 0x739
TSI_DPTX_EVENTS = TSI_BASE_DPTX(0x0e)
TSI_DPTX_POST_LT_FEATURES = TSI_BASE_DPTX(0x68)
TSI_DPTX_SDP_CTRL = TSI_BASE_DPTX(0x74)
TSI_TEST_STATUS = 0x80000019 # Used for reading test status.
TSI_DEVICE_INFO_R = 0x80000020 # Used for reading FW version
TSI_TEST_ERROR_CODE_R = 0x80000021 # Used for reading test error code
TSI_PDC_DPAM_CONFIG_R = TSI_BASE_PDC(0x33)
TSI_PDC_HW_CAPS_R = TSI_BASE_PDC(0x00)
TSI_PDC_CONTRACT_DATA = TSI_BASE_PDC(0x09)
TSI_PDC_TX_ID_VDO_CNT = TSI_BASE_PDC(0x14)
TSI_PDC_TX_ID_VDO = TSI_BASE_PDC(0x15)
TSI_DPTX_OUT_LC = TSI_BASE_DPTX(0x52)
TSI_DPTX_OUT_BR = TSI_BASE_DPTX(0x53)
TSI_DPTX_OUT_LINK_MODE = TSI_BASE_DPTX(0x54)
TSI_DP2TX_OUT_BR = TSI_BASE_DPTX(0x55)
TSI_DP2TX_OUT_LC = TSI_BASE_DPTX(0x5A)
TSI_DP2TX_OUT_TEST_PATTERN = TSI_BASE_DPTX(0x5B)
TSI_MLEG_CONTROL = TSI_BASE_MLEG(0x00)
TSI_MLEG_SYMBOL_REPLACE_A = TSI_BASE_MLEG(0x01)
TSI_MLEG_SYMBOL_REPLACE_MASK_A = TSI_BASE_MLEG(0x02)
TSI_MLEG_SYMBOL_REPLACE_B = TSI_BASE_MLEG(0x03)
TSI_MLEG_SYMBOL_REPLACE_MASK_B = TSI_BASE_MLEG(0x04)
TSI_MLEG_DELAY_COUNTER = TSI_BASE_MLEG(0x0A)
TSI_MLEG_LANE0_REPLACE_COUNTERS = TSI_BASE_MLEG(0x05)
TSI_MLEG_LANE1_REPLACE_COUNTERS = TSI_BASE_MLEG(0x06)
TSI_MLEG_LANE2_REPLACE_COUNTERS = TSI_BASE_MLEG(0x07)
TSI_MLEG_LANE3_REPLACE_COUNTERS = TSI_BASE_MLEG(0x08)
TSI_HDCP_2X_CFG = TSI_BASE_LEGACY_HDCP2(0x2)
TSI_W_PDC_EPR_MODE_CONTROL = TSI_BASE_PDC(0x04)
TSI_EVCAP_TIMESTAMP = TSI_BASE_LEGACY_EVCAP(0x8)
TSI_DPRX_INF_VALID_EX = TSI_BASE_DPRX(0x29)
TSI_DPRX_SDP_CRC16_CTRL = TSI_BASE_DPRX(0x98)
TSI_DPRX_SDP_CRC16_COUNTERS = TSI_BASE_DPRX(0x99)
TSI_HDRX_INF_STATUS = TSI_BASE_HDRX(0x0C)
TSI_HDRX_INF_VALID = TSI_BASE_HDRX(0x0D)
TSI_HDRX_INF_SELECT = TSI_BASE_HDRX(0x0E)
TSI_HDRX_INF_DATA = TSI_BASE_HDRX(0x0F)
MAX_EDID_SIZE = 4096
TSI_DPRX_DSC_TEST_CRC = TSI_BASE_DPRX(0x43)
TSI_DPRX_CRD_FEATURES = TSI_BASE_DPRX(0x63)
TSI_DPRX_ALPM_LT_INFO_R = TSI_BASE_DPRX(0x38)
TSI_DPRX_MSA_INFO_R = TSI_BASE_DPRX(0x48)
TSI_DPRX_MST_STATUS_R = TSI_BASE_DPRX(0x49)
TSI_GENERIC_STATUS = 0x210 # TSI State flags. NOTE: Access mode changes to R+W
TSI_VIDCAP_HDCP_PROTECTED_R = 0x8000f000
TSI_VIDCAP_HDCP_DECRYPTED_R = 0x8000f001
TSI_HDCP_COMPLIANT_R = 0x8000f002
TSI_DSC_BLOCK_NO = 0x80000009 # Used for stating start & end address to DSC PG. Changed 20191202 because not properly reserved.
TSI_CRC_DEFINITIONS = TSI_BASE_CRC_VIDEO(14) # CRC definitions. Default setting is 0
TSI_CRC_WINDOW_0_0 = TSI_BASE_CRC_VIDEO(15) # Left border/window pixel for first window 15..0. Top border/window line for first window 31..16. Default setting is 0
TSI_CRC_WINDOW_0_1 = TSI_BASE_CRC_VIDEO(16) # Right border pixel/ window width for first window. 15..0. Bottom border line / window height for first window 31..16. Default setting is 0
TSI_CRC_WINDOW_1_0 = TSI_BASE_CRC_VIDEO(17) # Left border/window pixel for second window 15..0. Top border/window line for second window 31..16. Default setting is 0
TSI_CRC_WINDOW_1_1 = TSI_BASE_CRC_VIDEO(18) # Right border pixel/ window width for second window. 15..0. Bottom border line / window height for second window 31..16. Default setting is 0
TSI_CRC_WINDOW_2_0 = TSI_BASE_CRC_VIDEO(19) # Left border/window pixel for third window 15..0. Top border/window line for third window 31..16. Default setting is 0
TSI_CRC_WINDOW_2_1 = TSI_BASE_CRC_VIDEO(20) # Right border pixel/ window width for third window. 15..0. Bottom border line / window height for third window 31..16. Default setting is 0
TSI_CRC_WINDOW_3_0 = TSI_BASE_CRC_VIDEO(21) # Left border/window pixel for fourth window 15..0. Top border/window line for fourth window 31..16. Default setting is 0
TSI_CRC_WINDOW_3_1 = TSI_BASE_CRC_VIDEO(22) # Right border pixel/ window width for fourth window. 15..0. Bottom border line / window height for fourth window 31..16. Default setting is 0
TSI_R_LC_COUNT = 0x80000010 # Number of licenses available.
TSI_W_LC_SELECT = 0x80000011 # Index from 0 to LC_Count-1: Select which license to access through the CI's below
TSI_R_LC_CODE = 0x80000012 # License ID (To identify type of license: "Basic" / "Advanced" / etc...)
TSI_R_LC_NAME = 0x80000013 # Human readable name for license.
TSI_R_LC_GET_KEY = 0x80000014 # Key string (40 characters, including the terminating NULL)
TSI_W_LC_ADD_KEY = 0x80000015 # -> Write license key string. Matching key is validated and added.
TSI_W_LC_REMOVE_KEY = 0x80000016 # -> Write license key string. Matching key is deleted.
TSI_W_LC_HAS_CODE = 0x80000017 # Check if specified code is available on device.
TSI_R_LC_SHA_TYPE = 0x80000018 # Check SHA type used in device.
TSI_DEVICE_DESCRIPTOR = 0x81000000
TSI_DEBUG_INFORMATION = 0x82000000
TSI_SELECT_SUITE = TSI_BASE_TEST(0x04)
TSI_TEST_DLG_CONFIG = TSI_BASE_TEST(0x22)
TSI_LOGICAL_PORT = c_uint
TSI_PORT_FLAGS = c_uint
TSI_DPRX_ALPM_STATS_CONTROL_W = TSI_BASE_DPRX(0x60)
TSI_DPRX_ALPM_STATS_STATUS_R = TSI_BASE_DPRX(0x60)
TSI_DPRX_ALPM_STATS_VB_R = TSI_BASE_DPRX(0x61)
TSI_DPRX_ALPM_STATS_IFP_R = TSI_BASE_DPRX(0x62)
TSI_DPRX_ALPM_STATS_CTRL_W = TSI_DPRX_ALPM_STATS_CONTROL_W
TSI_DSC_TX_CRC = TSI_BASE_DSC(0x01)
TSI_DSC_MEMORY_BLOCK = TSI_BASE_DSC(0x05)
TSI_DSC_DATA_SIZE = TSI_BASE_DSC(0x06)
TSI_TERMINAL_RW = 0xFFFFFFFE
TSI_DPTX_CABLE_ATTRIBUTES_R = TSI_BASE_DPTX(0x6E)
TSI_DPRX_CABLE_ATTRIBUTES_R = TSI_BASE_DPRX(0x6E)
TSI_DPRX_LT_INTERNAL_USE = 0x50000000 + 0xFFFFF
TSI_DPRX_LT_ROUTE_CREATE = TSI_BASE_LEGACY_DPRX(0x1A + TSI_DPRX_LT_INTERNAL_USE)
class DeviceMaskInternal(IntEnum):
Sink = TSI_DEVCAP_SINK
Source = TSI_DEVCAP_SOURCE
All = TSI_DEVCAP_ALL_CAPS
Nothing = 0

File diff suppressed because it is too large Load Diff