From cbe5e6d643cafbb36dc0e2019651900a0623938a Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Mon, 18 Sep 2023 23:52:57 +0200 Subject: [PATCH 1/1] First commit. --- .gitignore | 9 + Cargo.toml | 49 + IntelArc/IntelArc.h | 18 + IntelArc/IntelArc.lib | Bin 0 -> 325208 bytes IntelArc/igcl_api.h | 7175 +++++++++++++++++++++++++++++++ IntelOC/IntelOC - Backup.csproj | 22 + IntelOC/IntelOC.csproj | 22 + IntelOC/IntelOC.sln | 25 + IntelOC/IntelOCWrapper.dll | Bin 0 -> 189952 bytes IntelOC/Program.cs | 116 + TODO.md | 173 + build.rs | 89 + src/a770.rs | 74 + src/b650_e.rs | 97 + src/common.rs | 0 src/consts.rs | 5 + src/corsair_vengeance.rs | 102 + src/machine.rs | 50 + src/main.rs | 347 ++ src/main_loop.rs | 95 + src/piix4_i2c.rs | 274 ++ src/rgb.rs | 17 + src/roccat.rs | 61 + src/sensors_jiji.rs | 57 + src/settings.rs | 59 + src/timer.rs | 31 + winring0/OlsApi.h | 638 +++ winring0/WinRing0x64.dll | Bin 0 -> 29696 bytes winring0/WinRing0x64.lib | Bin 0 -> 15120 bytes winring0/WinRing0x64.sys | Bin 0 -> 11512 bytes 30 files changed, 9605 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 IntelArc/IntelArc.h create mode 100644 IntelArc/IntelArc.lib create mode 100644 IntelArc/igcl_api.h create mode 100644 IntelOC/IntelOC - Backup.csproj create mode 100644 IntelOC/IntelOC.csproj create mode 100644 IntelOC/IntelOC.sln create mode 100644 IntelOC/IntelOCWrapper.dll create mode 100644 IntelOC/Program.cs create mode 100644 TODO.md create mode 100644 build.rs create mode 100644 src/a770.rs create mode 100644 src/b650_e.rs create mode 100644 src/common.rs create mode 100644 src/consts.rs create mode 100644 src/corsair_vengeance.rs create mode 100644 src/machine.rs create mode 100644 src/main.rs create mode 100644 src/main_loop.rs create mode 100644 src/piix4_i2c.rs create mode 100644 src/rgb.rs create mode 100644 src/roccat.rs create mode 100644 src/sensors_jiji.rs create mode 100644 src/settings.rs create mode 100644 src/timer.rs create mode 100644 winring0/OlsApi.h create mode 100644 winring0/WinRing0x64.dll create mode 100644 winring0/WinRing0x64.lib create mode 100644 winring0/WinRing0x64.sys diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66b5eb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +target +**/*.rs.bk +Cargo.lock +config.ron + +.vs + +bin +obj \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0089ff5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "temp_2_rgb" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +# [build] +# target = "i686-pc-windows-msvc" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +ron = "0.8" # Rust object notation, to load configuration files. + +num = "0.4" + +windows-service = "0.6" + +hidapi = "2.4" +libc = "0.2" +wmi = "0.13" +crc = "3.0" + +libloading = "0.8" +# netcorehost = "0.15" + +[dependencies.windows] +version = "0.51" +features = [ + "Win32_Foundation", + "Win32_Security", + "Win32_Storage_FileSystem", + "Win32_System_IO", + "Win32_System_Services", + "Win32_System_LibraryLoader", + "Win32_System_Threading", + # "Devices_I2c", + # "Devices_Enumeration", + # "Foundation", + # "Foundation_Collections", +] + +[build-dependencies] +bindgen = "0.68" + +[profile.release] +strip = "debuginfo" +codegen-units = 1 +lto = true diff --git a/IntelArc/IntelArc.h b/IntelArc/IntelArc.h new file mode 100644 index 0000000..8dca457 --- /dev/null +++ b/IntelArc/IntelArc.h @@ -0,0 +1,18 @@ +#pragma once + +#include "igcl_api.h" + +int __stdcall arc_test(); + +struct Devices { + ctl_api_handle_t hAPIHandle; + ctl_device_adapter_handle_t* handles; + uint32_t nb_devices; +}; + +Devices __stdcall GetDevices(); +bool __stdcall FreeDevices(Devices devices); + +double __stdcall GetTemperature(Devices devices, uint32_t n); + +//void __stdcall SetRGB(Devices devices, uint32_t n, unsigned char r, unsigned char g, unsigned char b); diff --git a/IntelArc/IntelArc.lib b/IntelArc/IntelArc.lib new file mode 100644 index 0000000000000000000000000000000000000000..9af4c5bb15ff15b21c5247ffd8aef5171ecc359c GIT binary patch literal 325208 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 owRiY^He=WTv&dC?<+Na+rXoh($ literal 0 HcmV?d00001 diff --git a/IntelArc/igcl_api.h b/IntelArc/igcl_api.h new file mode 100644 index 0000000..d21cc36 --- /dev/null +++ b/IntelArc/igcl_api.h @@ -0,0 +1,7175 @@ +//=========================================================================== +// Copyright (C) 2022-23 Intel Corporation +// This software and the related documents are Intel copyrighted materials, and +// your use of them is governed by the express license under which they were +// provided to you ("License"). Unless the License provides otherwise, you may +// not use, modify, copy, publish, distribute, disclose or transmit this software +// or the related documents without Intel's prior written permission. This software +// and the related documents are provided as is, with no express or implied +// warranties, other than those that are expressly stated in the License. +//-------------------------------------------------------------------------- + +/** + * + * @file ctl_api.h + * @version v1-r1 + * + */ +#ifndef _CTL_API_H +#define _CTL_API_H +#if defined(__cplusplus) +#pragma once +#endif + +// standard headers +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// Intel 'ctlApi' common types +#if !defined(__GNUC__) +#pragma region common +#endif +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAKE_VERSION +/// @brief Generates generic ::'ctlApi' API versions +#define CTL_MAKE_VERSION( _major, _minor ) (( _major << 16 )|( _minor & 0x0000ffff)) +#endif // CTL_MAKE_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAJOR_VERSION +/// @brief Extracts ::'ctlApi' API major version +#define CTL_MAJOR_VERSION( _ver ) ( _ver >> 16 ) +#endif // CTL_MAJOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MINOR_VERSION +/// @brief Extracts ::'ctlApi' API minor version +#define CTL_MINOR_VERSION( _ver ) ( _ver & 0x0000ffff ) +#endif // CTL_MINOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_MAJOR_VERSION +/// @brief ::'ctlApi' API major version of this implementation +#define CTL_IMPL_MAJOR_VERSION 1 +#endif // CTL_IMPL_MAJOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_MINOR_VERSION +/// @brief ::'ctlApi' API minor version of this implementation +#define CTL_IMPL_MINOR_VERSION 1 +#endif // CTL_IMPL_MINOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_VERSION +/// @brief ::'ctlApi' API version of this implementation +#define CTL_IMPL_VERSION CTL_MAKE_VERSION( CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION ) +#endif // CTL_IMPL_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_APICALL +#if defined(_WIN32) +/// @brief Calling convention for all API functions +#define CTL_APICALL __cdecl +#else +#define CTL_APICALL +#endif // defined(_WIN32) +#endif // CTL_APICALL + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_APIEXPORT +#if defined(_WIN32) +/// @brief Microsoft-specific dllexport storage-class attribute +#define CTL_APIEXPORT __declspec(dllexport) +#else +#define CTL_APIEXPORT +#endif // defined(_WIN32) +#endif // CTL_APIEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_DLLEXPORT +#if defined(_WIN32) +/// @brief Microsoft-specific dllexport storage-class attribute +#define CTL_DLLEXPORT __declspec(dllexport) +#endif // defined(_WIN32) +#endif // CTL_DLLEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_DLLEXPORT +#if __GNUC__ >= 4 +/// @brief GCC-specific dllexport storage-class attribute +#define CTL_DLLEXPORT __attribute__ ((visibility ("default"))) +#else +#define CTL_DLLEXPORT +#endif // __GNUC__ >= 4 +#endif // CTL_DLLEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_BIT +/// @brief Generic macro for enumerator bit masks +#define CTL_BIT( _i ) ( 1 << _i ) +#endif // CTL_BIT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported initialization flags +typedef uint32_t ctl_init_flags_t; +typedef enum _ctl_init_flag_t +{ + CTL_INIT_FLAG_USE_LEVEL_ZERO = CTL_BIT(0), ///< Use Level0 or not. This is usually required for telemetry, + ///< performance, frequency related APIs + CTL_INIT_FLAG_MAX = 0x80000000 + +} ctl_init_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Version information +typedef uint32_t ctl_version_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a control API instance +typedef struct _ctl_api_handle_t *ctl_api_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device adapter instance +typedef struct _ctl_device_adapter_handle_t *ctl_device_adapter_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device temperature sensor +typedef struct _ctl_temp_handle_t *ctl_temp_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle for a device frequency domain +typedef struct _ctl_freq_handle_t *ctl_freq_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a power device. +typedef struct _ctl_pwr_handle_t *ctl_pwr_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device fan +typedef struct _ctl_fan_handle_t *ctl_fan_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device memory module +typedef struct _ctl_mem_handle_t *ctl_mem_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device engine group +typedef struct _ctl_engine_handle_t *ctl_engine_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Base for all properties types +typedef struct _ctl_base_interface_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + +} ctl_base_interface_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Value type +typedef enum _ctl_property_value_type_t +{ + CTL_PROPERTY_VALUE_TYPE_BOOL = 0, ///< Boolean + CTL_PROPERTY_VALUE_TYPE_FLOAT = 1, ///< Float + CTL_PROPERTY_VALUE_TYPE_INT32 = 2, ///< Int32 + CTL_PROPERTY_VALUE_TYPE_UINT32 = 3, ///< Unsigned Int32 + CTL_PROPERTY_VALUE_TYPE_ENUM = 4, ///< Enum + CTL_PROPERTY_VALUE_TYPE_CUSTOM = 5, ///< Custom argument + CTL_PROPERTY_VALUE_TYPE_MAX + +} ctl_property_value_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details, a generic struct to hold min/max/step size +/// information of various feature properties +typedef struct _ctl_property_range_info_t +{ + float min_possible_value; ///< [out] Minimum possible value + float max_possible_value; ///< [out] Maximum possible value + float step_size; ///< [out] Step size possible + float default_value; ///< [out] Default value + +} ctl_property_range_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details of integer type, a generic struct to hold +/// min/max/step size information of various feature properties +typedef struct _ctl_property_range_info_int_t +{ + int32_t min_possible_value; ///< [out] Minimum possible value + int32_t max_possible_value; ///< [out] Maximum possible value + int32_t step_size; ///< [out] Step size possible + int32_t default_value; ///< [out] Default value + +} ctl_property_range_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details of unsigned integer type, a generic struct to +/// hold min/max/step size information of various feature properties +typedef struct _ctl_property_range_info_uint_t +{ + uint32_t min_possible_value; ///< [out] Minimum possible value + uint32_t max_possible_value; ///< [out] Maximum possible value + uint32_t step_size; ///< [out] Step size possible + uint32_t default_value; ///< [out] Default value + +} ctl_property_range_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Bool feature details +typedef struct _ctl_property_info_boolean_t +{ + bool DefaultState; ///< [out] Default state + +} ctl_property_info_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Bool feature for get/set +typedef struct _ctl_property_boolean_t +{ + bool Enable; ///< [in,out] Enable + +} ctl_property_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumeration feature details +typedef struct _ctl_property_info_enum_t +{ + uint64_t SupportedTypes; ///< [out] Supported possible values represented as a bitmask + uint32_t DefaultType; ///< [out] Default type + +} ctl_property_info_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumeration feature for get/set +typedef struct _ctl_property_enum_t +{ + uint32_t EnableType; ///< [in,out] Enable with specific type + +} ctl_property_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Float feature details +typedef struct _ctl_property_info_float_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Float feature for get/set +typedef struct _ctl_property_float_t +{ + bool Enable; ///< [in,out] Enable + float Value; ///< [in,out] Value + +} ctl_property_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature details +typedef struct _ctl_property_info_int_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_int_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature for get/set +typedef struct _ctl_property_int_t +{ + bool Enable; ///< [in,out] Enable + int32_t Value; ///< [in,out] Value + +} ctl_property_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature details +typedef struct _ctl_property_info_uint_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_uint_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature for get/set +typedef struct _ctl_property_uint_t +{ + bool Enable; ///< [in,out] Enable + uint32_t Value; ///< [in,out] Value + +} ctl_property_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature element details, union of bool/float/enum property_info +/// structs. Used for feature specific capability check +typedef union _ctl_property_info_t +{ + ctl_property_info_boolean_t BoolType; ///< [in,out] Boolean type fields + ctl_property_info_float_t FloatType; ///< [in,out] Float type fields + ctl_property_info_int_t IntType; ///< [in,out] Int type fields + ctl_property_info_enum_t EnumType; ///< [in,out] Enum type fields + ctl_property_info_uint_t UIntType; ///< [in,out] Unsigned Int type fields + +} ctl_property_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature element details, union of bool/float/enum property structs. +/// Used for get/set calls +typedef union _ctl_property_t +{ + ctl_property_boolean_t BoolType; ///< [in,out] Boolean type fields + ctl_property_float_t FloatType; ///< [in,out] Float type fields + ctl_property_int_t IntType; ///< [in,out] Int type fields + ctl_property_enum_t EnumType; ///< [in,out] Enum type fields + ctl_property_uint_t UIntType; ///< [in,out] Unsigned Int type fields + +} ctl_property_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Defines Return/Error codes. +/// All generic error (bit30) codes are between 0x40000000-0x4000FFFF. +/// All 3D (bit 29) specific error codes are between 0x60000000-0x6000FFFF. +/// All media (bit 28) specific error codes are between 0x50000000-0x5000FFFF. +/// All display (bit 27) specific error codes are between 0x48000000-0x4800FFFF +/// All core (bit 26) specific error codes are between 0x44000000-0x4400FFFF +/// Success result code with additional info are between 0x00000001-0x0000FFFF. +typedef enum _ctl_result_t +{ + CTL_RESULT_SUCCESS = 0x00000000, ///< success + CTL_RESULT_SUCCESS_STILL_OPEN_BY_ANOTHER_CALLER = 0x00000001, ///< success but still open by another caller + CTL_RESULT_ERROR_SUCCESS_END = 0x0000FFFF, ///< "Success group error code end value, not to be used + ///< " + CTL_RESULT_ERROR_GENERIC_START = 0x40000000, ///< Generic error code starting value, not to be used + CTL_RESULT_ERROR_NOT_INITIALIZED = 0x40000001, ///< Result not initialized + CTL_RESULT_ERROR_ALREADY_INITIALIZED = 0x40000002, ///< Already initialized + CTL_RESULT_ERROR_DEVICE_LOST = 0x40000003, ///< Device hung, reset, was removed, or driver update occurred + CTL_RESULT_ERROR_OUT_OF_HOST_MEMORY = 0x40000004, ///< Insufficient host memory to satisfy call + CTL_RESULT_ERROR_OUT_OF_DEVICE_MEMORY = 0x40000005, ///< Insufficient device memory to satisfy call + CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS = 0x40000006, ///< Access denied due to permission level + CTL_RESULT_ERROR_NOT_AVAILABLE = 0x40000007, ///< Resource was removed + CTL_RESULT_ERROR_UNINITIALIZED = 0x40000008, ///< Library not initialized + CTL_RESULT_ERROR_UNSUPPORTED_VERSION = 0x40000009, ///< Generic error code for unsupported versions + CTL_RESULT_ERROR_UNSUPPORTED_FEATURE = 0x4000000a, ///< Generic error code for unsupported features + CTL_RESULT_ERROR_INVALID_ARGUMENT = 0x4000000b, ///< Generic error code for invalid arguments + CTL_RESULT_ERROR_INVALID_API_HANDLE = 0x4000000c, ///< API handle in invalid + CTL_RESULT_ERROR_INVALID_NULL_HANDLE = 0x4000000d, ///< Handle argument is not valid + CTL_RESULT_ERROR_INVALID_NULL_POINTER = 0x4000000e, ///< Pointer argument may not be nullptr + CTL_RESULT_ERROR_INVALID_SIZE = 0x4000000f, ///< Size argument is invalid (e.g., must not be zero) + CTL_RESULT_ERROR_UNSUPPORTED_SIZE = 0x40000010, ///< Size argument is not supported by the device (e.g., too large) + CTL_RESULT_ERROR_UNSUPPORTED_IMAGE_FORMAT = 0x40000011, ///< Image format is not supported by the device + CTL_RESULT_ERROR_DATA_READ = 0x40000012, ///< Data read error + CTL_RESULT_ERROR_DATA_WRITE = 0x40000013, ///< Data write error + CTL_RESULT_ERROR_DATA_NOT_FOUND = 0x40000014, ///< Data not found error + CTL_RESULT_ERROR_NOT_IMPLEMENTED = 0x40000015, ///< Function not implemented + CTL_RESULT_ERROR_OS_CALL = 0x40000016, ///< Operating system call failure + CTL_RESULT_ERROR_KMD_CALL = 0x40000017, ///< Kernel mode driver call failure + CTL_RESULT_ERROR_UNLOAD = 0x40000018, ///< Library unload failure + CTL_RESULT_ERROR_ZE_LOADER = 0x40000019, ///< Level0 loader not found + CTL_RESULT_ERROR_INVALID_OPERATION_TYPE = 0x4000001a, ///< Invalid operation type + CTL_RESULT_ERROR_NULL_OS_INTERFACE = 0x4000001b,///< Null OS interface + CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE = 0x4000001c, ///< Null OS adapter handle + CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE = 0x4000001d,///< Null display output handle + CTL_RESULT_ERROR_WAIT_TIMEOUT = 0x4000001e, ///< Timeout in Wait function + CTL_RESULT_ERROR_PERSISTANCE_NOT_SUPPORTED = 0x4000001f,///< Persistance not supported + CTL_RESULT_ERROR_PLATFORM_NOT_SUPPORTED = 0x40000020, ///< Platform not supported + CTL_RESULT_ERROR_UNKNOWN_APPLICATION_UID = 0x40000021, ///< Unknown Appplicaion UID in Initialization call + CTL_RESULT_ERROR_INVALID_ENUMERATION = 0x40000022, ///< The enum is not valid + CTL_RESULT_ERROR_FILE_DELETE = 0x40000023, ///< Error in file delete operation + CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED = 0x40000024,///< The device requires a reset. + CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED = 0x40000025, ///< The device requires a full reboot. + CTL_RESULT_ERROR_LOAD = 0x40000026, ///< Library load failure + CTL_RESULT_ERROR_UNKNOWN = 0x4000FFFF, ///< Unknown or internal error + CTL_RESULT_ERROR_RETRY_OPERATION = 0x40010000, ///< Operation failed, retry previous operation again + CTL_RESULT_ERROR_GENERIC_END = 0x4000FFFF, ///< "Generic error code end value, not to be used + ///< " + CTL_RESULT_ERROR_CORE_START = 0x44000000, ///< Core error code starting value, not to be used + CTL_RESULT_ERROR_CORE_OVERCLOCK_NOT_SUPPORTED = 0x44000001, ///< The Overclock is not supported. + CTL_RESULT_ERROR_CORE_OVERCLOCK_VOLTAGE_OUTSIDE_RANGE = 0x44000002, ///< The Voltage exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_FREQUENCY_OUTSIDE_RANGE = 0x44000003, ///< The Frequency exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_POWER_OUTSIDE_RANGE = 0x44000004, ///< The Power exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_TEMPERATURE_OUTSIDE_RANGE = 0x44000005, ///< The Power exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_IN_VOLTAGE_LOCKED_MODE = 0x44000006,///< The Overclock is in voltage locked mode. + CTL_RESULT_ERROR_CORE_OVERCLOCK_RESET_REQUIRED = 0x44000007,///< It indicates that the requested change will not be applied until the + ///< device is reset. + CTL_RESULT_ERROR_CORE_OVERCLOCK_WAIVER_NOT_SET = 0x44000008,///< The $OverclockWaiverSet function has not been called. + CTL_RESULT_ERROR_CORE_END = 0x0440FFFF, ///< "Core error code end value, not to be used + ///< " + CTL_RESULT_ERROR_3D_START = 0x60000000, ///< 3D error code starting value, not to be used + CTL_RESULT_ERROR_3D_END = 0x6000FFFF, ///< "3D error code end value, not to be used + ///< " + CTL_RESULT_ERROR_MEDIA_START = 0x50000000, ///< Media error code starting value, not to be used + CTL_RESULT_ERROR_MEDIA_END = 0x5000FFFF, ///< "Media error code end value, not to be used + ///< " + CTL_RESULT_ERROR_DISPLAY_START = 0x48000000, ///< Display error code starting value, not to be used + CTL_RESULT_ERROR_INVALID_AUX_ACCESS_FLAG = 0x48000001, ///< Invalid flag for Aux access + CTL_RESULT_ERROR_INVALID_SHARPNESS_FILTER_FLAG = 0x48000002,///< Invalid flag for Sharpness + CTL_RESULT_ERROR_DISPLAY_NOT_ATTACHED = 0x48000003, ///< Error for Display not attached + CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE = 0x48000004, ///< Error for display attached but not active + CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG = 0x48000005, ///< Error for invalid power optimization flag + CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST = 0x48000006,///< DPST is supported only in DC Mode + CTL_RESULT_ERROR_INVALID_PIXTX_GET_CONFIG_QUERY_TYPE = 0x48000007, ///< Invalid query type for pixel transformation get configuration + CTL_RESULT_ERROR_INVALID_PIXTX_SET_CONFIG_OPERATION_TYPE = 0x48000008, ///< Invalid operation type for pixel transformation set configuration + CTL_RESULT_ERROR_INVALID_SET_CONFIG_NUMBER_OF_SAMPLES = 0x48000009, ///< Invalid number of samples for pixel transformation set configuration + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID = 0x4800000a, ///< Invalid block id for pixel transformation + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_TYPE = 0x4800000b, ///< Invalid block type for pixel transformation + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_NUMBER = 0x4800000c, ///< Invalid block number for pixel transformation + CTL_RESULT_ERROR_INSUFFICIENT_PIXTX_BLOCK_CONFIG_MEMORY = 0x4800000d, ///< Insufficient memery allocated for BlockConfigs + CTL_RESULT_ERROR_3DLUT_INVALID_PIPE = 0x4800000e, ///< Invalid pipe for 3dlut + CTL_RESULT_ERROR_3DLUT_INVALID_DATA = 0x4800000f, ///< Invalid 3dlut data + CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR = 0x48000010, ///< 3dlut not supported in HDR + CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION = 0x48000011, ///< Invalid 3dlut operation + CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL = 0x48000012, ///< 3dlut call unsuccessful + CTL_RESULT_ERROR_AUX_DEFER = 0x48000013, ///< AUX defer failure + CTL_RESULT_ERROR_AUX_TIMEOUT = 0x48000014, ///< AUX timeout failure + CTL_RESULT_ERROR_AUX_INCOMPLETE_WRITE = 0x48000015, ///< AUX incomplete write failure + CTL_RESULT_ERROR_I2C_AUX_STATUS_UNKNOWN = 0x48000016, ///< I2C/AUX unkonown failure + CTL_RESULT_ERROR_I2C_AUX_UNSUCCESSFUL = 0x48000017, ///< I2C/AUX unsuccessful + CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED = 0x48000018,///< Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data + ///< passed by user + CTL_RESULT_ERROR_EXTERNAL_DISPLAY_ATTACHED = 0x48000019,///< External Display is Attached hence fail the Display Switch + CTL_RESULT_ERROR_CUSTOM_MODE_STANDARD_CUSTOM_MODE_EXISTS = 0x4800001a, ///< Standard custom mode exists + CTL_RESULT_ERROR_CUSTOM_MODE_NON_CUSTOM_MATCHING_MODE_EXISTS = 0x4800001b, ///< Non custom matching mode exists + CTL_RESULT_ERROR_CUSTOM_MODE_INSUFFICIENT_MEMORY = 0x4800001c, ///< Custom mode insufficent memory + CTL_RESULT_ERROR_DISPLAY_END = 0x4800FFFF, ///< "Display error code end value, not to be used + ///< " + CTL_RESULT_MAX + +} ctl_result_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_DEVICE_NAME_LEN +/// @brief Maximum IPC handle size +#define CTL_MAX_DEVICE_NAME_LEN 100 +#endif // CTL_MAX_DEVICE_NAME_LEN + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_RESERVED_SIZE +/// @brief Maximum reserved size for future members. +#define CTL_MAX_RESERVED_SIZE 116 +#endif // CTL_MAX_RESERVED_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief General Physical Units. +typedef enum _ctl_units_t +{ + CTL_UNITS_FREQUENCY_MHZ = 0, ///< Type is Frequency with units in MHz. + CTL_UNITS_OPERATIONS_GTS = 1, ///< Type is Frequency with units in GT/s (gigatransfers per second). + CTL_UNITS_OPERATIONS_MTS = 2, ///< Type is Frequency with units in MT/s (megatransfers per second). + CTL_UNITS_VOLTAGE_VOLTS = 3, ///< Type is Voltage with units in Volts. + CTL_UNITS_POWER_WATTS = 4, ///< Type is Power with units in Watts. + CTL_UNITS_TEMPERATURE_CELSIUS = 5, ///< Type is Temperature with units in Celsius. + CTL_UNITS_ENERGY_JOULES = 6, ///< Type is Energy with units in Joules. + CTL_UNITS_TIME_SECONDS = 7, ///< Type is Time with units in Seconds. + CTL_UNITS_MEMORY_BYTES = 8, ///< Type is Memory with units in Bytes. + CTL_UNITS_ANGULAR_SPEED_RPM = 9, ///< Type is Angular Speed with units in Revolutions per Minute. + CTL_UNITS_UNKNOWN = 0x4800FFFF, ///< Type of units unknown. + CTL_UNITS_MAX + +} ctl_units_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief General Data Types. +typedef enum _ctl_data_type_t +{ + CTL_DATA_TYPE_INT8 = 0, ///< The data type is 8 bit signed integer. + CTL_DATA_TYPE_UINT8 = 1, ///< The data type is 8 bit unsigned integer. + CTL_DATA_TYPE_INT16 = 2, ///< The data type is 16 bit signed integer. + CTL_DATA_TYPE_UINT16 = 3, ///< The data type is 16 bit unsigned integer. + CTL_DATA_TYPE_INT32 = 4, ///< The data type is 32 bit signed integer. + CTL_DATA_TYPE_UINT32 = 5, ///< The data type is 32 bit unsigned integer. + CTL_DATA_TYPE_INT64 = 6, ///< The data type is 64 bit signed integer. + CTL_DATA_TYPE_UINT64 = 7, ///< The data type is 64 bit unsigned integer. + CTL_DATA_TYPE_FLOAT = 8, ///< The data type is 32 bit floating point. + CTL_DATA_TYPE_DOUBLE = 9, ///< The data type is 64 bit floating point. + CTL_DATA_TYPE_STRING_ASCII = 10, ///< The data type is an array of 8 bit unsigned integers. + CTL_DATA_TYPE_STRING_UTF16 = 11, ///< The data type is an array of 16 bit unsigned integers. + CTL_DATA_TYPE_STRING_UTF132 = 12, ///< The data type is an array of 32 bit unsigned integers. + CTL_DATA_TYPE_UNKNOWN = 0x4800FFFF, ///< The data type is unknown. + CTL_DATA_TYPE_MAX + +} ctl_data_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Union for Generic Data. +/// +/// @details +/// - The telemetry data items could be of different types. +/// - Refer to ::ctl_data_type_t to find the current type. +typedef union _ctl_data_value_t +{ + int8_t data8; ///< [out] The data type is 8 bit signed integer. + uint8_t datau8; ///< [out] The data type is 8 bit unsigned integer. + int16_t data16; ///< [out] The data type is 16 bit signed integer. + uint16_t datau16; ///< [out] The data type is 16 bit unsigned integer. + int32_t data32; ///< [out] The data type is 32 bit signed integer. + uint32_t datau32; ///< [out] The data type is 32 bit unsigned integer. + int64_t data64; ///< [out] The data type is 64 bit signed integer. + uint64_t datau64; ///< [out] The data type is 64 bit unsigned integer. + float datafloat; ///< [out] The data type is 32 bit floating point. + double datadouble; ///< [out] The data type is 64 bit floating point. + +} ctl_data_value_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Base for all properties types +typedef struct _ctl_base_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + +} ctl_base_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Application Unique ID +typedef struct _ctl_application_id_t +{ + uint32_t Data1; ///< [in] Data1 + uint16_t Data2; ///< [in] Data2 + uint16_t Data3; ///< [in] Data3 + uint8_t Data4[8]; ///< [in] Data4 + +} ctl_application_id_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Init arguments +typedef struct _ctl_init_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_version_info_t AppVersion; ///< [in][release] App's IGCL version + ctl_init_flags_t flags; ///< [in][release] Caller version + ctl_version_info_t SupportedVersion; ///< [out][release] IGCL implementation version + ctl_application_id_t ApplicationUID; ///< [in] Application Provided Unique ID.Application can pass all 0's as + ///< the default ID + +} ctl_init_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved struct +typedef struct _ctl_reserved_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + void* pSpecialArg; ///< [in] Reserved struct + uint32_t ArgSize; ///< [in] struct size + +} ctl_reserved_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved base struct +typedef struct _ctl_reserved_args_base_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + +} ctl_reserved_args_base_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved - Unlock function capability +typedef struct _ctl_unlock_capability_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + ctl_application_id_t UnlockCapsID; ///< [in] Unique ID to unlock a specific function + +} ctl_unlock_capability_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Used by loader like modules to specify runtime implementation details +typedef struct _ctl_runtime_path_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_application_id_t UnlockID; ///< [in] Unique ID for reserved/special function + wchar_t* pRuntimePath; ///< [in] Path to runtime DLL + uint16_t DeviceID; ///< [in] Device ID of interest to caller. pRuntimePath should not be NULL. + uint8_t RevID; ///< [in] Revision ID of interest to caller. pRuntimePath should not be + ///< NULL. + +} ctl_runtime_path_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Control Api Init +/// +/// @details +/// - Control Api Init +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pInitDesc` +/// + `nullptr == phAPIHandle` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlInit( + ctl_init_args_t* pInitDesc, ///< [in][out] App's control API version + ctl_api_handle_t* phAPIHandle ///< [in][out][release] Control API handle + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Control Api Destroy +/// +/// @details +/// - Control Api Close +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlClose( + ctl_api_handle_t hAPIHandle ///< [in][release] Control API implementation handle obtained during init + ///< call + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Runtime path +/// +/// @details +/// - Control Api set runtime path. Optional call from a loader which allows +/// the loaded runtime to enumerate only the adapters which the specified +/// runtime is responsible for. This is done usually by a loader or by +/// callers who know how to get the specific runtime of interest. This +/// call right now is reserved for use by Intel components. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetRuntimePath( + ctl_runtime_path_args_t* pArgs ///< [in] Runtime path + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported Functions +typedef uint32_t ctl_supported_functions_flags_t; +typedef enum _ctl_supported_functions_flag_t +{ + CTL_SUPPORTED_FUNCTIONS_FLAG_DISPLAY = CTL_BIT(0), ///< [out] Is Display supported + CTL_SUPPORTED_FUNCTIONS_FLAG_3D = CTL_BIT(1), ///< [out] Is 3D supported + CTL_SUPPORTED_FUNCTIONS_FLAG_MEDIA = CTL_BIT(2),///< [out] Is Media supported + CTL_SUPPORTED_FUNCTIONS_FLAG_MAX = 0x80000000 + +} ctl_supported_functions_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Firmware version +typedef struct _ctl_firmware_version_t +{ + uint64_t major_version; ///< [out] Major version + uint64_t minor_version; ///< [out] Minor version + uint64_t build_number; ///< [out] Build number + +} ctl_firmware_version_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief DeviceType +typedef enum _ctl_device_type_t +{ + CTL_DEVICE_TYPE_GRAPHICS = 1, ///< Graphics Device type + CTL_DEVICE_TYPE_SYSTEM = 2, ///< System Device type + CTL_DEVICE_TYPE_MAX + +} ctl_device_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adapter Properties +typedef uint32_t ctl_adapter_properties_flags_t; +typedef enum _ctl_adapter_properties_flag_t +{ + CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED = CTL_BIT(0),///< [out] Is Integrated Graphics adapter + CTL_ADAPTER_PROPERTIES_FLAG_MAX = 0x80000000 + +} ctl_adapter_properties_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Device Adapter properties +typedef struct _ctl_device_adapter_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + void* pDeviceID; ///< [in,out] OS specific Device ID + uint32_t device_id_size; ///< [in] size of the device ID + ctl_device_type_t device_type; ///< [out] Device Type + ctl_supported_functions_flags_t supported_subfunction_flags;///< [out] Supported functions + uint64_t driver_version; ///< [out] Driver version + ctl_firmware_version_t firmware_version; ///< [out] Firmware version + uint32_t pci_vendor_id; ///< [out] PCI Vendor ID + uint32_t pci_device_id; ///< [out] PCI Device ID + uint32_t rev_id; ///< [out] PCI Revision ID + uint32_t num_eus_per_sub_slice; ///< [out] Number of EUs per sub-slice + uint32_t num_sub_slices_per_slice; ///< [out] Number of sub-slices per slice + uint32_t num_slices; ///< [out] Number of slices + char name[CTL_MAX_DEVICE_NAME_LEN]; ///< [out] Device name + ctl_adapter_properties_flags_t graphics_adapter_properties; ///< [out] Graphics Adapter Properties + uint32_t Frequency; ///< [out] Clock frequency for this device. Supported only for Version > 0 + uint16_t pci_subsys_id; ///< [out] PCI SubSys ID, Supported only for Version > 1 + uint16_t pci_subsys_vendor_id; ///< [out] PCI SubSys Vendor ID, Supported only for Version > 1 + char reserved[CTL_MAX_RESERVED_SIZE]; ///< [out] Reserved + +} ctl_device_adapter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief OperationType +typedef enum _ctl_operation_type_t +{ + CTL_OPERATION_TYPE_READ = 1, ///< Read operation + CTL_OPERATION_TYPE_WRITE = 2, ///< Write operation + CTL_OPERATION_TYPE_MAX + +} ctl_operation_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Generic Structure for Void* datatypes +typedef struct _ctl_generic_void_datatype_t +{ + void* pData; ///< [in,out]void pointer to memory + uint32_t size; ///< [in,out]size of the allocated memory + +} ctl_generic_void_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Generic Structure for Revision datatypes +typedef struct _ctl_revision_datatype_t +{ + uint8_t major_version; ///< [in,out]Major Version + uint8_t minor_version; ///< [in,out]Minor Version + uint8_t revision_version; ///< [in,out]Revision Version + +} ctl_revision_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property Type flags +typedef uint32_t ctl_property_type_flags_t; +typedef enum _ctl_property_type_flag_t +{ + CTL_PROPERTY_TYPE_FLAG_DISPLAY = CTL_BIT(0), ///< Display type. Supported scenarios: Sharpness/gamma/CSC + CTL_PROPERTY_TYPE_FLAG_3D = CTL_BIT(1), ///< 3D type. Supported scenarios: All set calls via IGCL's 3D APIs + CTL_PROPERTY_TYPE_FLAG_MEDIA = CTL_BIT(2), ///< Media type. Supported scenarios: All set calls via IGCL's media APIs + CTL_PROPERTY_TYPE_FLAG_CORE = CTL_BIT(3), ///< For future: Core graphic event types like clocking, frequency etc. + CTL_PROPERTY_TYPE_FLAG_MAX = 0x80000000 + +} ctl_property_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Arguments related to wait for a property change function +typedef struct _ctl_wait_property_change_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_type_flags_t PropertyType; ///< [in] Type of the property + uint32_t TimeOutMilliSec; ///< [in][release] Time-out interval in milliseconds. Specify 0xFFFFFFFF if + ///< time-out is not desired + uint32_t EventMiscFlags; ///< [in][release] Event flags for future use + void* pReserved; ///< [in][release] Reserved for future use + uint64_t ReservedOutFlags; ///< [out] Reserved out argument for future use + +} ctl_wait_property_change_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display orientation (rotation) +typedef enum _ctl_display_orientation_t +{ + CTL_DISPLAY_ORIENTATION_0 = 0, ///< 0 Degree + CTL_DISPLAY_ORIENTATION_90 = 1, ///< 90 Degree + CTL_DISPLAY_ORIENTATION_180 = 2, ///< 180 Degree + CTL_DISPLAY_ORIENTATION_270 = 3, ///< 270 Degree + CTL_DISPLAY_ORIENTATION_MAX + +} ctl_display_orientation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Rectangle +typedef struct _ctl_rect_t +{ + int32_t Left; ///< [in,out] Left + int32_t Top; ///< [in,out] Top + int32_t Right; ///< [in,out] Right + int32_t Bottom; ///< [in,out] Bottom + +} ctl_rect_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Wait for a property change. Note that this is a blocking call +/// +/// @details +/// - Wait for a property change in display, 3d, media etc. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlWaitForPropertyChange( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_wait_property_change_args_t* pArgs ///< [in] Argument containing information about which property changes to + ///< listen for + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved function +/// +/// @details +/// - Reserved function +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlReservedCall( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_reserved_args_t* pArgs ///< [in] Argument containing information + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_base_interface_t +typedef struct _ctl_base_interface_t ctl_base_interface_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_t +typedef struct _ctl_property_range_info_t ctl_property_range_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_int_t +typedef struct _ctl_property_range_info_int_t ctl_property_range_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_uint_t +typedef struct _ctl_property_range_info_uint_t ctl_property_range_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_boolean_t +typedef struct _ctl_property_info_boolean_t ctl_property_info_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_boolean_t +typedef struct _ctl_property_boolean_t ctl_property_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_enum_t +typedef struct _ctl_property_info_enum_t ctl_property_info_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_enum_t +typedef struct _ctl_property_enum_t ctl_property_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_float_t +typedef struct _ctl_property_info_float_t ctl_property_info_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_float_t +typedef struct _ctl_property_float_t ctl_property_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_int_t +typedef struct _ctl_property_info_int_t ctl_property_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_int_t +typedef struct _ctl_property_int_t ctl_property_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_uint_t +typedef struct _ctl_property_info_uint_t ctl_property_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_uint_t +typedef struct _ctl_property_uint_t ctl_property_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_base_properties_t +typedef struct _ctl_base_properties_t ctl_base_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_application_id_t +typedef struct _ctl_application_id_t ctl_application_id_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_init_args_t +typedef struct _ctl_init_args_t ctl_init_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_reserved_args_t +typedef struct _ctl_reserved_args_t ctl_reserved_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_reserved_args_base_t +typedef struct _ctl_reserved_args_base_t ctl_reserved_args_base_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_unlock_capability_t +typedef struct _ctl_unlock_capability_t ctl_unlock_capability_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_runtime_path_args_t +typedef struct _ctl_runtime_path_args_t ctl_runtime_path_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_firmware_version_t +typedef struct _ctl_firmware_version_t ctl_firmware_version_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_device_adapter_properties_t +typedef struct _ctl_device_adapter_properties_t ctl_device_adapter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_generic_void_datatype_t +typedef struct _ctl_generic_void_datatype_t ctl_generic_void_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_revision_datatype_t +typedef struct _ctl_revision_datatype_t ctl_revision_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_wait_property_change_args_t +typedef struct _ctl_wait_property_change_args_t ctl_wait_property_change_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_rect_t +typedef struct _ctl_rect_t ctl_rect_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming_caps_t +typedef struct _ctl_endurance_gaming_caps_t ctl_endurance_gaming_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming_t +typedef struct _ctl_endurance_gaming_t ctl_endurance_gaming_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming2_t +typedef struct _ctl_endurance_gaming2_t ctl_endurance_gaming2_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adaptivesync_caps_t +typedef struct _ctl_adaptivesync_caps_t ctl_adaptivesync_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adaptivesync_getset_t +typedef struct _ctl_adaptivesync_getset_t ctl_adaptivesync_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_app_profiles_caps_t +typedef struct _ctl_3d_app_profiles_caps_t ctl_3d_app_profiles_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_app_profiles_t +typedef struct _ctl_3d_app_profiles_t ctl_3d_app_profiles_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_tier_details_t +typedef struct _ctl_3d_tier_details_t ctl_3d_tier_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_details_t +typedef struct _ctl_3d_feature_details_t ctl_3d_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_caps_t +typedef struct _ctl_3d_feature_caps_t ctl_3d_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_getset_t +typedef struct _ctl_3d_feature_getset_t ctl_3d_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_kmd_load_features_t +typedef struct _ctl_kmd_load_features_t ctl_kmd_load_features_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_display_timing_t +typedef struct _ctl_display_timing_t ctl_display_timing_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_display_properties_t +typedef struct _ctl_display_properties_t ctl_display_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adapter_display_encoder_properties_t +typedef struct _ctl_adapter_display_encoder_properties_t ctl_adapter_display_encoder_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_filter_properties_t +typedef struct _ctl_sharpness_filter_properties_t ctl_sharpness_filter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_caps_t +typedef struct _ctl_sharpness_caps_t ctl_sharpness_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_settings_t +typedef struct _ctl_sharpness_settings_t ctl_sharpness_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_i2c_access_args_t +typedef struct _ctl_i2c_access_args_t ctl_i2c_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_aux_access_args_t +typedef struct _ctl_aux_access_args_t ctl_aux_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_caps_t +typedef struct _ctl_power_optimization_caps_t ctl_power_optimization_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_lrr_t +typedef struct _ctl_power_optimization_lrr_t ctl_power_optimization_lrr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_psr_t +typedef struct _ctl_power_optimization_psr_t ctl_power_optimization_psr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_dpst_t +typedef struct _ctl_power_optimization_dpst_t ctl_power_optimization_dpst_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_settings_t +typedef struct _ctl_power_optimization_settings_t ctl_power_optimization_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_set_brightness_t +typedef struct _ctl_set_brightness_t ctl_set_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_get_brightness_t +typedef struct _ctl_get_brightness_t ctl_get_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_color_primaries_t +typedef struct _ctl_pixtx_color_primaries_t ctl_pixtx_color_primaries_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pixel_format_t +typedef struct _ctl_pixtx_pixel_format_t ctl_pixtx_pixel_format_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_1dlut_config_t +typedef struct _ctl_pixtx_1dlut_config_t ctl_pixtx_1dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_matrix_config_t +typedef struct _ctl_pixtx_matrix_config_t ctl_pixtx_matrix_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_3dlut_sample_t +typedef struct _ctl_pixtx_3dlut_sample_t ctl_pixtx_3dlut_sample_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_3dlut_config_t +typedef struct _ctl_pixtx_3dlut_config_t ctl_pixtx_3dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_block_config_t +typedef struct _ctl_pixtx_block_config_t ctl_pixtx_block_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pipe_get_config_t +typedef struct _ctl_pixtx_pipe_get_config_t ctl_pixtx_pipe_get_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pipe_set_config_t +typedef struct _ctl_pixtx_pipe_set_config_t ctl_pixtx_pipe_set_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_panel_descriptor_access_args_t +typedef struct _ctl_panel_descriptor_access_args_t ctl_panel_descriptor_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_retro_scaling_settings_t +typedef struct _ctl_retro_scaling_settings_t ctl_retro_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_retro_scaling_caps_t +typedef struct _ctl_retro_scaling_caps_t ctl_retro_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_scaling_caps_t +typedef struct _ctl_scaling_caps_t ctl_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_scaling_settings_t +typedef struct _ctl_scaling_settings_t ctl_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_lux_aggr_map_entry_t +typedef struct _ctl_lace_lux_aggr_map_entry_t ctl_lace_lux_aggr_map_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_lux_aggr_map_t +typedef struct _ctl_lace_lux_aggr_map_t ctl_lace_lux_aggr_map_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_config_t +typedef struct _ctl_lace_config_t ctl_lace_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sw_psr_settings_t +typedef struct _ctl_sw_psr_settings_t ctl_sw_psr_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_intel_arc_sync_monitor_params_t +typedef struct _ctl_intel_arc_sync_monitor_params_t ctl_intel_arc_sync_monitor_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mux_properties_t +typedef struct _ctl_mux_properties_t ctl_mux_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_intel_arc_sync_profile_params_t +typedef struct _ctl_intel_arc_sync_profile_params_t ctl_intel_arc_sync_profile_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_edid_management_args_t +typedef struct _ctl_edid_management_args_t ctl_edid_management_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_get_set_custom_mode_args_t +typedef struct _ctl_get_set_custom_mode_args_t ctl_get_set_custom_mode_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_custom_src_mode_t +typedef struct _ctl_custom_src_mode_t ctl_custom_src_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_child_display_target_mode_t +typedef struct _ctl_child_display_target_mode_t ctl_child_display_target_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_combined_display_child_info_t +typedef struct _ctl_combined_display_child_info_t ctl_combined_display_child_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_combined_display_args_t +typedef struct _ctl_combined_display_args_t ctl_combined_display_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_display_info_t +typedef struct _ctl_genlock_display_info_t ctl_genlock_display_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_target_mode_list_t +typedef struct _ctl_genlock_target_mode_list_t ctl_genlock_target_mode_list_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_topology_t +typedef struct _ctl_genlock_topology_t ctl_genlock_topology_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_args_t +typedef struct _ctl_genlock_args_t ctl_genlock_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_engine_properties_t +typedef struct _ctl_engine_properties_t ctl_engine_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_engine_stats_t +typedef struct _ctl_engine_stats_t ctl_engine_stats_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_speed_t +typedef struct _ctl_fan_speed_t ctl_fan_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_temp_speed_t +typedef struct _ctl_fan_temp_speed_t ctl_fan_temp_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_speed_table_t +typedef struct _ctl_fan_speed_table_t ctl_fan_speed_table_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_properties_t +typedef struct _ctl_fan_properties_t ctl_fan_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_config_t +typedef struct _ctl_fan_config_t ctl_fan_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_properties_t +typedef struct _ctl_freq_properties_t ctl_freq_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_range_t +typedef struct _ctl_freq_range_t ctl_freq_range_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_state_t +typedef struct _ctl_freq_state_t ctl_freq_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_throttle_time_t +typedef struct _ctl_freq_throttle_time_t ctl_freq_throttle_time_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_super_resolution_info_t +typedef struct _ctl_video_processing_super_resolution_info_t ctl_video_processing_super_resolution_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_super_resolution_t +typedef struct _ctl_video_processing_super_resolution_t ctl_video_processing_super_resolution_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_noise_reduction_info_t +typedef struct _ctl_video_processing_noise_reduction_info_t ctl_video_processing_noise_reduction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_noise_reduction_t +typedef struct _ctl_video_processing_noise_reduction_t ctl_video_processing_noise_reduction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_adaptive_contrast_enhancement_info_t +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_info_t ctl_video_processing_adaptive_contrast_enhancement_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_adaptive_contrast_enhancement_t +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_t ctl_video_processing_adaptive_contrast_enhancement_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_standard_color_correction_info_t +typedef struct _ctl_video_processing_standard_color_correction_info_t ctl_video_processing_standard_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_standard_color_correction_t +typedef struct _ctl_video_processing_standard_color_correction_t ctl_video_processing_standard_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_total_color_correction_info_t +typedef struct _ctl_video_processing_total_color_correction_info_t ctl_video_processing_total_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_total_color_correction_t +typedef struct _ctl_video_processing_total_color_correction_t ctl_video_processing_total_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_details_t +typedef struct _ctl_video_processing_feature_details_t ctl_video_processing_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_caps_t +typedef struct _ctl_video_processing_feature_caps_t ctl_video_processing_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_getset_t +typedef struct _ctl_video_processing_feature_getset_t ctl_video_processing_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_properties_t +typedef struct _ctl_mem_properties_t ctl_mem_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_state_t +typedef struct _ctl_mem_state_t ctl_mem_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_bandwidth_t +typedef struct _ctl_mem_bandwidth_t ctl_mem_bandwidth_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_telemetry_item_t +typedef struct _ctl_oc_telemetry_item_t ctl_oc_telemetry_item_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_control_info_t +typedef struct _ctl_oc_control_info_t ctl_oc_control_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_properties_t +typedef struct _ctl_oc_properties_t ctl_oc_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_vf_pair_t +typedef struct _ctl_oc_vf_pair_t ctl_oc_vf_pair_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_psu_info_t +typedef struct _ctl_psu_info_t ctl_psu_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_telemetry_t +typedef struct _ctl_power_telemetry_t ctl_power_telemetry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_address_t +typedef struct _ctl_pci_address_t ctl_pci_address_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_speed_t +typedef struct _ctl_pci_speed_t ctl_pci_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_properties_t +typedef struct _ctl_pci_properties_t ctl_pci_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_state_t +typedef struct _ctl_pci_state_t ctl_pci_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_properties_t +typedef struct _ctl_power_properties_t ctl_power_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_energy_counter_t +typedef struct _ctl_power_energy_counter_t ctl_power_energy_counter_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_sustained_limit_t +typedef struct _ctl_power_sustained_limit_t ctl_power_sustained_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_burst_limit_t +typedef struct _ctl_power_burst_limit_t ctl_power_burst_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_peak_limit_t +typedef struct _ctl_power_peak_limit_t ctl_power_peak_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_limits_t +typedef struct _ctl_power_limits_t ctl_power_limits_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_energy_threshold_t +typedef struct _ctl_energy_threshold_t ctl_energy_threshold_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_temp_properties_t +typedef struct _ctl_temp_properties_t ctl_temp_properties_t; + + + +#if !defined(__GNUC__) +#pragma endregion // common +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region 3D +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature type +typedef enum _ctl_3d_feature_t +{ + CTL_3D_FEATURE_FRAME_PACING = 0, ///< Frame pacing. Contains generic enum type fields + CTL_3D_FEATURE_ENDURANCE_GAMING = 1, ///< Endurance gaming. Contains generic integer type fields. Value will be + ///< interpreted as the max FPS to be used when in DC mode globally or per + ///< application + CTL_3D_FEATURE_FRAME_LIMIT = 2, ///< Frame limit for games. Contains generic integer type fields. Value + ///< will be interpreted as the max FPS to be used independent of system + ///< power state + CTL_3D_FEATURE_ANISOTROPIC = 3, ///< ANISOTROPIC. Contains generic enum type fields + CTL_3D_FEATURE_CMAA = 4, ///< CMAA. Contains generic enum type fields + CTL_3D_FEATURE_TEXTURE_FILTERING_QUALITY = 5, ///< Texture filtering quality. Contains generic enum type fields + CTL_3D_FEATURE_ADAPTIVE_TESSELLATION = 6, ///< Adaptive tessellation quality. Contains generic integer type fields + CTL_3D_FEATURE_SHARPENING_FILTER = 7, ///< Sharpening Filter. Contains generic integer type fields + CTL_3D_FEATURE_MSAA = 8, ///< Msaa. Contains generic enum type fields + CTL_3D_FEATURE_GAMING_FLIP_MODES = 9, ///< Various Gaming flip modes like speed frame, smooth sync & force async + ///< flip. Contains generic enum type fields + CTL_3D_FEATURE_ADAPTIVE_SYNC_PLUS = 10, ///< Adaptive sync plus. Refer custom field ::ctl_adaptivesync_caps_t & + ///< ::ctl_adaptivesync_getset_t + CTL_3D_FEATURE_APP_PROFILES = 11, ///< Game Compatibility & Performance Profiles. Refer custom field + ///< ::ctl_3d_app_profiles_caps_t & ::ctl_3d_app_profiles_t + CTL_3D_FEATURE_APP_PROFILE_DETAILS = 12, ///< Game Profile Customization. Refer custom field ::ctl_3d_tier_details_t + CTL_3D_FEATURE_EMULATED_TYPED_64BIT_ATOMICS = 13, ///< Emulated Typed 64bit Atomics support in DG2 + CTL_3D_FEATURE_MAX + +} ctl_3d_feature_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature misc flags +typedef uint32_t ctl_3d_feature_misc_flags_t; +typedef enum _ctl_3d_feature_misc_flag_t +{ + CTL_3D_FEATURE_MISC_FLAG_DX11 = CTL_BIT(0), ///< Feature supported on DX11 + CTL_3D_FEATURE_MISC_FLAG_DX12 = CTL_BIT(1), ///< Feature supported on DX12 + CTL_3D_FEATURE_MISC_FLAG_VULKAN = CTL_BIT(2), ///< Feature supported on VULKAN + CTL_3D_FEATURE_MISC_FLAG_LIVE_CHANGE = CTL_BIT(3), ///< User can change feature live without restarting the game + CTL_3D_FEATURE_MISC_FLAG_MAX = 0x80000000 + +} ctl_3d_feature_misc_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Anisotropic values possible +typedef enum _ctl_3d_anisotropic_types_t +{ + CTL_3D_ANISOTROPIC_TYPES_APP_CHOICE = 0, ///< Application choice + CTL_3D_ANISOTROPIC_TYPES_2X = 2, ///< 2X + CTL_3D_ANISOTROPIC_TYPES_4X = 4, ///< 4X + CTL_3D_ANISOTROPIC_TYPES_8X = 8, ///< 8X + CTL_3D_ANISOTROPIC_TYPES_16X = 16, ///< 16X + CTL_3D_ANISOTROPIC_TYPES_MAX + +} ctl_3d_anisotropic_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Texture filtering values possible +typedef enum _ctl_3d_texture_filtering_quality_types_t +{ + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_PERFORMANCE = 0, ///< Performance + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_BALANCED = 1,///< Balanced + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_QUALITY = 2, ///< Quality + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_MAX + +} ctl_3d_texture_filtering_quality_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frame pacing values possible +typedef enum _ctl_3d_frame_pacing_types_t +{ + CTL_3D_FRAME_PACING_TYPES_DISABLE = 0, ///< Disable + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_FRAME_NO_SMOOTHENING = 1, ///< Enable with scheduler without any frame smoothening + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_FRAME_MAX_SMOOTHENING = 2,///< Enable with scheduler with maximum smoothness + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_COMPETITIVE_GAMING = 3, ///< Enable with scheduler in competitive gaming mode + CTL_3D_FRAME_PACING_TYPES_MAX + +} ctl_3d_frame_pacing_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming control possible +typedef enum _ctl_3d_endurance_gaming_control_t +{ + CTL_3D_ENDURANCE_GAMING_CONTROL_TURN_OFF = 0, ///< Endurance Gaming disable + CTL_3D_ENDURANCE_GAMING_CONTROL_TURN_ON = 1, ///< Endurance Gaming enable + CTL_3D_ENDURANCE_GAMING_CONTROL_AUTO = 2, ///< Endurance Gaming auto + CTL_3D_ENDURANCE_GAMING_CONTROL_MAX + +} ctl_3d_endurance_gaming_control_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming modes possible +typedef enum _ctl_3d_endurance_gaming_mode_t +{ + CTL_3D_ENDURANCE_GAMING_MODE_BETTER_PERFORMANCE = 0,///< Endurance Gaming better performance mode + CTL_3D_ENDURANCE_GAMING_MODE_BALANCED = 1, ///< Endurance Gaming balanced mode + CTL_3D_ENDURANCE_GAMING_MODE_MAXIMUM_BATTERY = 2, ///< Endurance Gaming maximum battery mode + CTL_3D_ENDURANCE_GAMING_MODE_MAX + +} ctl_3d_endurance_gaming_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Cmaa values possible +typedef enum _ctl_3d_cmaa_types_t +{ + CTL_3D_CMAA_TYPES_TURN_OFF = 0, ///< Turn off + CTL_3D_CMAA_TYPES_OVERRIDE_MSAA = 1, ///< Override MSAA + CTL_3D_CMAA_TYPES_ENHANCE_APPLICATION = 2, ///< Enhance Application + CTL_3D_CMAA_TYPES_MAX + +} ctl_3d_cmaa_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Tessellation +typedef enum _ctl_3d_adaptive_tessellation_types_t +{ + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_TURN_OFF = 0,///< Turn off + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_TURN_ON = 1, ///< Turn on + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_MAX + +} ctl_3d_adaptive_tessellation_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sharpening filter values possible +typedef enum _ctl_3d_sharpening_filter_types_t +{ + CTL_3D_SHARPENING_FILTER_TYPES_TURN_OFF = 0, ///< Turn off + CTL_3D_SHARPENING_FILTER_TYPES_TURN_ON = 1, ///< Turn on + CTL_3D_SHARPENING_FILTER_TYPES_MAX + +} ctl_3d_sharpening_filter_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief MSAA values possible +typedef enum _ctl_3d_msaa_types_t +{ + CTL_3D_MSAA_TYPES_APP_CHOICE = 0, ///< Application choice + CTL_3D_MSAA_TYPES_DISABLED = 1, ///< Disabled. MSAA count 1 + CTL_3D_MSAA_TYPES_2X = 2, ///< 2X + CTL_3D_MSAA_TYPES_4X = 4, ///< 4X + CTL_3D_MSAA_TYPES_8X = 8, ///< 8X + CTL_3D_MSAA_TYPES_16X = 16, ///< 16X + CTL_3D_MSAA_TYPES_MAX + +} ctl_3d_msaa_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gaming flip modes +typedef uint32_t ctl_gaming_flip_mode_flags_t; +typedef enum _ctl_gaming_flip_mode_flag_t +{ + CTL_GAMING_FLIP_MODE_FLAG_APPLICATION_DEFAULT = CTL_BIT(0), ///< Application Default + CTL_GAMING_FLIP_MODE_FLAG_VSYNC_OFF = CTL_BIT(1), ///< Convert all sync flips to async on the next possible scanline. + CTL_GAMING_FLIP_MODE_FLAG_VSYNC_ON = CTL_BIT(2),///< Convert all async flips to sync flips. + CTL_GAMING_FLIP_MODE_FLAG_SMOOTH_SYNC = CTL_BIT(3), ///< Reduce tearing effect with async flips + CTL_GAMING_FLIP_MODE_FLAG_SPEED_FRAME = CTL_BIT(4), ///< Application unaware triple buffering + CTL_GAMING_FLIP_MODE_FLAG_CAPPED_FPS = CTL_BIT(5), ///< Limit the game FPS to panel RR + CTL_GAMING_FLIP_MODE_FLAG_MAX = 0x80000000 + +} ctl_gaming_flip_mode_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming caps +typedef struct _ctl_endurance_gaming_caps_t +{ + ctl_property_info_enum_t EGControlCaps; ///< [out] Endurance Gaming control capability + ctl_property_info_enum_t EGModeCaps; ///< [out] Endurance Gaming mode capability + +} ctl_endurance_gaming_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming Get/Set +typedef struct _ctl_endurance_gaming_t +{ + ctl_3d_endurance_gaming_control_t EGControl; ///< [in,out] Endurance Gaming control - Off/On/Auto + ctl_3d_endurance_gaming_mode_t EGMode; ///< [in,out] Endurance Gaming mode - Better Performance/Balanced/Maximum + ///< Battery + +} ctl_endurance_gaming_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming version2 Get/Set +typedef struct _ctl_endurance_gaming2_t +{ + ctl_3d_endurance_gaming_control_t EGControl; ///< [in,out] Endurance Gaming control - Off/On/Auto + ctl_3d_endurance_gaming_mode_t EGMode; ///< [in,out] Endurance Gaming mode - Better Performance/Balanced/Maximum + ///< Battery + bool IsFPRequired; ///< [out] Is frame pacing required, dynamic state + double TargetFPS; ///< [out] Target FPS for frame pacing + double RefreshRate; ///< [out] Refresh rate used to calculate target fps + uint32_t Reserved[4]; ///< [out] Reserved fields + +} ctl_endurance_gaming2_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive sync plus caps +typedef struct _ctl_adaptivesync_caps_t +{ + bool AdaptiveBalanceSupported; ///< [out] Adaptive balance supported + ctl_property_info_float_t AdaptiveBalanceStrengthCaps; ///< [out] Strength of adaptive balance algorithm - min/max/steps/default + +} ctl_adaptivesync_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive sync plus +typedef struct _ctl_adaptivesync_getset_t +{ + bool AdaptiveSync; ///< [in,out] Adaptive sync. Note that in Windows, OS controls state of + ///< adaptive sync and which game gets the feature using it's own policies + bool AdaptiveBalance; ///< [in,out] Adaptive balance + bool AllowAsyncForHighFPS; ///< [in,out] Allow async flips when FPS is higher than max refresh rate of + ///< the panel + float AdaptiveBalanceStrength; ///< [in,out] Adaptive balance strength + +} ctl_adaptivesync_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game tier types +typedef uint32_t ctl_3d_tier_type_flags_t; +typedef enum _ctl_3d_tier_type_flag_t +{ + CTL_3D_TIER_TYPE_FLAG_COMPATIBILITY = CTL_BIT(0), ///< Compatibility Tier + CTL_3D_TIER_TYPE_FLAG_PERFORMANCE = CTL_BIT(1), ///< Performance Tier + CTL_3D_TIER_TYPE_FLAG_MAX = 0x80000000 + +} ctl_3d_tier_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game tiers +typedef uint32_t ctl_3d_tier_profile_flags_t; +typedef enum _ctl_3d_tier_profile_flag_t +{ + CTL_3D_TIER_PROFILE_FLAG_TIER_1 = CTL_BIT(0), ///< Tier 1 Profile + CTL_3D_TIER_PROFILE_FLAG_TIER_2 = CTL_BIT(1), ///< Tier 2 Profile + CTL_3D_TIER_PROFILE_FLAG_TIER_RECOMMENDED = CTL_BIT(30),///< Recommended Tier Profile. If set other tier values shouldn't be set + CTL_3D_TIER_PROFILE_FLAG_MAX = 0x80000000 + +} ctl_3d_tier_profile_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile Capabilities. Typically these remain the same across +/// games. +typedef struct _ctl_3d_app_profiles_caps_t +{ + ctl_3d_tier_type_flags_t SupportedTierTypes; ///< [out] Tier of interest for capability check + uint64_t Reserved; ///< [in,out] Reserved for future + +} ctl_3d_app_profiles_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile tiers +typedef struct _ctl_3d_app_profiles_t +{ + ctl_3d_tier_type_flag_t TierType; ///< [in] Tier type + ctl_3d_tier_profile_flags_t SupportedTierProfiles; ///< [out] Supported tier profiles bitmask + ctl_3d_tier_profile_flags_t DefaultEnabledTierProfiles; ///< [out] Default tiers which driver will enable if there is no user + ///< specific setting for global or per application + ctl_3d_tier_profile_flags_t CustomizationSupportedTierProfiles; ///< [out] Tiers supporting customization - reserved for future + ctl_3d_tier_profile_flags_t EnabledTierProfiles;///< [in,out] Tier profile(s) to be enabled/disabled in the case of a set + ///< call. For a get call this will return the currently enabled tiers + ctl_3d_tier_profile_flags_t CustomizationEnabledTierProfiles; ///< [in,out] Tier profile(s) which are customized. Caller shall call + ///< ::ctl_3d_tier_details_t to get specifics if any. + uint64_t Reserved; ///< [in,out] Reserved for future + +} ctl_3d_app_profiles_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile tiers details +typedef struct _ctl_3d_tier_details_t +{ + ctl_3d_tier_type_flag_t TierType; ///< [in] Tier type + ctl_3d_tier_profile_flag_t TierProfile; ///< [in] Tier profile(s) for get/set details + uint64_t Reserved[4]; ///< [in,out] Reserved for future + +} ctl_3d_tier_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Emulated Typed 64bit Atomics +typedef enum _ctl_emulated_typed_64bit_atomics_types_t +{ + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_DEFAULT = 0, ///< Default settings is based on workload/driver decision. + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_TURN_ON = 1, ///< Force Turn on + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_TURN_OFF = 2,///< Force Turn off + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_MAX + +} ctl_emulated_typed_64bit_atomics_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature capability details which will have range/supported and +/// default values +typedef struct _ctl_3d_feature_details_t +{ + ctl_3d_feature_t FeatureType; ///< [out] 3D feature type + ctl_property_value_type_t ValueType; ///< [out] Type of value + ctl_property_info_t Value; ///< [out] Union of various type of values for 3D features. For enum types + ///< this can be anisotropic/frame pacing etc. This member is valid iff + ///< ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. Typically for a feature requiring custom + ///< struct, caller will know of it upfront and can provide the right size + ///< info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + bool PerAppSupport; ///< [out] Flag indicating whether the feature is supported per application + ///< or not + int64_t ConflictingFeatures; ///< [out] Mask of ::ctl_3d_feature_t values which can't be enabled along + ///< with the mentioned FeatureType. If this is 0, it meant the feature + ///< doesn't have any conflicts with other features + int16_t FeatureMiscSupport; ///< [out] 3D Feature Miscellaneous support flags. This will be based on + ///< ::ctl_3d_feature_misc_flags_t + int16_t Reserved; ///< [out] Reserved + int16_t Reserved1; ///< [out] Reserved + int16_t Reserved2; ///< [out] Reserved + +} ctl_3d_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature which are controllable +typedef struct _ctl_3d_feature_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSupportedFeatures; ///< [in,out] Number of elements in supported features array + ctl_3d_feature_details_t* pFeatureDetails; ///< [in,out] Array of feature details + +} ctl_3d_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature for get/set +typedef struct _ctl_3d_feature_getset_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_3d_feature_t FeatureType; ///< [in] Features interested in + char* ApplicationName; ///< [in] Application name for which the property type is applicable. If + ///< this is an empty string then this will get/set global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + bool bSet; ///< [in] Set this if it's a set call + ctl_property_value_type_t ValueType; ///< [in] Type of value. Caller has to ensure it provides the right value + ///< type which decides how one read the union structure below + ctl_property_t Value; ///< [in,out] Union of various type of values for 3D features. For enum + ///< types this can be anisotropic/frame pacing etc. This member is valid + ///< iff ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. Typically for a feature requiring custom + ///< struct, caller will know of it upfront and cn provide the right size + ///< info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + +} ctl_3d_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Load KMD gaming features. Restricted function +typedef struct _ctl_kmd_load_features_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + bool bLoad; ///< [in] If set, will load known KMD features. If not set will reset known + ///< KMD features to default + int64_t SubsetFeatureMask; ///< [in,out] Mask indicating the subset of KMD features within + ///< ::ctl_3d_feature_t values. Default of 0 indicate all KMD features + char* ApplicationName; ///< [in] Application name for which the KMD properties are loaded for. If + ///< this is an empty string then this will load global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + +} ctl_kmd_load_features_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get 3D capabilities +/// +/// @details +/// - The application gets 3D properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeatureCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupported3DCapabilities( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_3d_feature_caps_t* pFeatureCaps ///< [in,out][release] 3D properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set 3D feature +/// +/// @details +/// - 3D feature details +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeature` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSet3DFeature( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_3d_feature_getset_t* pFeature ///< [in][release] 3D feature get/set parameter + ); + + +#if !defined(__GNUC__) +#pragma endregion // 3D +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region display +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a display output instance +typedef struct _ctl_display_output_handle_t *ctl_display_output_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Check Driver version +/// +/// @details +/// - The application checks driver version +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlCheckDriverVersion( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_version_info_t version_info ///< [in][release] Driver version info + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate devices +/// +/// @details +/// - The application enumerates all device adapters in the system +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateDevices( + ctl_api_handle_t hAPIHandle, ///< [in][release] Applications should pass the Control API handle returned + ///< by the CtlInit function + uint32_t* pCount, ///< [in,out][release] pointer to the number of device instances. If count + ///< is zero, then the api will update the value with the total + ///< number of drivers available. If count is non-zero, then the api will + ///< only retrieve the number of drivers. + ///< If count is larger than the number of drivers available, then the api + ///< will update the value with the correct number of drivers available. + ctl_device_adapter_handle_t* phDevices ///< [in,out][optional][release][range(0, *pCount)] array of driver + ///< instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate display outputs +/// +/// @details +/// - Enumerates display output capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateDisplayOutputs( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + uint32_t* pCount, ///< [in,out][release] pointer to the number of display output instances. + ///< If count is zero, then the api will update the value with the total + ///< number of outputs available. If count is non-zero, then the api will + ///< only retrieve the number of outputs. + ///< If count is larger than the number of drivers available, then the api + ///< will update the value with the correct number of drivers available. + ctl_display_output_handle_t* phDisplayOutputs ///< [in,out][optional][release][range(0, *pCount)] array of display output + ///< instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief OS specific Display identifiers +typedef union _ctl_os_display_encoder_identifier_t +{ + uint32_t WindowsDisplayEncoderID; ///< [out] Windows OS Display encoder ID + ctl_generic_void_datatype_t DisplayEncoderID; ///< [out] Display encoder ID for non-windows OS + +} ctl_os_display_encoder_identifier_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various display types +typedef enum _ctl_display_output_types_t +{ + CTL_DISPLAY_OUTPUT_TYPES_INVALID = 0, ///< Invalid + CTL_DISPLAY_OUTPUT_TYPES_DISPLAYPORT = 1, ///< DisplayPort + CTL_DISPLAY_OUTPUT_TYPES_HDMI = 2, ///< HDMI + CTL_DISPLAY_OUTPUT_TYPES_DVI = 3, ///< DVI + CTL_DISPLAY_OUTPUT_TYPES_MIPI = 4, ///< MIPI + CTL_DISPLAY_OUTPUT_TYPES_CRT = 5, ///< CRT + CTL_DISPLAY_OUTPUT_TYPES_MAX + +} ctl_display_output_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported output bits per color (bpc) bitmasks +typedef uint32_t ctl_output_bpc_flags_t; +typedef enum _ctl_output_bpc_flag_t +{ + CTL_OUTPUT_BPC_FLAG_6BPC = CTL_BIT(0), ///< [out] Is 6bpc supported + CTL_OUTPUT_BPC_FLAG_8BPC = CTL_BIT(1), ///< [out] Is 8bpc supported + CTL_OUTPUT_BPC_FLAG_10BPC = CTL_BIT(2), ///< [out] Is 10bpc supported + CTL_OUTPUT_BPC_FLAG_12BPC = CTL_BIT(3), ///< [out] Is 12bpc supported + CTL_OUTPUT_BPC_FLAG_MAX = 0x80000000 + +} ctl_output_bpc_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display output features. This will indicate only the high level +/// capabilities +typedef uint32_t ctl_std_display_feature_flags_t; +typedef enum _ctl_std_display_feature_flag_t +{ + CTL_STD_DISPLAY_FEATURE_FLAG_HDCP = CTL_BIT(0), ///< [out] Is HDCP supported + CTL_STD_DISPLAY_FEATURE_FLAG_HD_AUDIO = CTL_BIT(1), ///< [out] Is HD Audio supported + CTL_STD_DISPLAY_FEATURE_FLAG_PSR = CTL_BIT(2), ///< [out] Is VESA PSR supported + CTL_STD_DISPLAY_FEATURE_FLAG_ADAPTIVESYNC_VRR = CTL_BIT(3), ///< [out] Is VESA Adaptive Sync or HDMI VRR supported + CTL_STD_DISPLAY_FEATURE_FLAG_VESA_COMPRESSION = CTL_BIT(4), ///< [out] Is display compression (VESA DSC) supported + CTL_STD_DISPLAY_FEATURE_FLAG_HDR = CTL_BIT(5), ///< [out] Is HDR supported + CTL_STD_DISPLAY_FEATURE_FLAG_HDMI_QMS = CTL_BIT(6), ///< [out] Is HDMI QMS supported + CTL_STD_DISPLAY_FEATURE_FLAG_MAX = 0x80000000 + +} ctl_std_display_feature_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Advanced Graphics Features provided by Intel Graphics Adapter. This +/// will indicate only the high level capabilities +typedef uint32_t ctl_intel_display_feature_flags_t; +typedef enum _ctl_intel_display_feature_flag_t +{ + CTL_INTEL_DISPLAY_FEATURE_FLAG_DPST = CTL_BIT(0), ///< [out] Is DPST supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_LACE = CTL_BIT(1), ///< [out] Is LACE supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_DRRS = CTL_BIT(2), ///< [out] Is DRRS supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_MAX = 0x80000000 + +} ctl_intel_display_feature_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Attached Display Mux Type +typedef enum _ctl_attached_display_mux_type_t +{ + CTL_ATTACHED_DISPLAY_MUX_TYPE_NATIVE = 0, ///< [out] Native DP / HDMI + CTL_ATTACHED_DISPLAY_MUX_TYPE_THUNDERBOLT = 1, ///< [out] Thunderbolt + CTL_ATTACHED_DISPLAY_MUX_TYPE_TYPE_C = 2, ///< [out] USB Type C + CTL_ATTACHED_DISPLAY_MUX_TYPE_USB4 = 3, ///< [out] USB4 + CTL_ATTACHED_DISPLAY_MUX_TYPE_MAX + +} ctl_attached_display_mux_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Signal Standard +typedef enum _ctl_signal_standard_type_t +{ + CTL_SIGNAL_STANDARD_TYPE_UNKNOWN = 0, ///< [out] Unknown Signal Standard + CTL_SIGNAL_STANDARD_TYPE_CUSTOM = 1, ///< [out] Custom added timing + CTL_SIGNAL_STANDARD_TYPE_DMT = 2, ///< [out] DMT timing + CTL_SIGNAL_STANDARD_TYPE_GTF = 3, ///< [out] GTF Timing + CTL_SIGNAL_STANDARD_TYPE_CVT = 4, ///< [out] CVT Timing + CTL_SIGNAL_STANDARD_TYPE_CTA = 5, ///< [out] CTA Timing + CTL_SIGNAL_STANDARD_TYPE_MAX + +} ctl_signal_standard_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Protocol Converter Location +typedef uint32_t ctl_protocol_converter_location_flags_t; +typedef enum _ctl_protocol_converter_location_flag_t +{ + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_ONBOARD = CTL_BIT(0), ///< [out] OnBoard Protocol Converter + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_EXTERNAL = CTL_BIT(1), ///< [out] External Dongle + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_MAX = 0x80000000 + +} ctl_protocol_converter_location_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief [out] Display Output configuration related flags which indicate how +/// the output pixel stream drive the panel +typedef uint32_t ctl_display_config_flags_t; +typedef enum _ctl_display_config_flag_t +{ + CTL_DISPLAY_CONFIG_FLAG_DISPLAY_ACTIVE = CTL_BIT(0),///< [out] DisplayActive 0: InActive 1: Active + CTL_DISPLAY_CONFIG_FLAG_DISPLAY_ATTACHED = CTL_BIT(1), ///< [out] DisplayAttached.This Bit indicates if any dongle/display/hub is + ///< attached to the encoder. 0: Not Attached 1: Attached + CTL_DISPLAY_CONFIG_FLAG_IS_DONGLE_CONNECTED_TO_ENCODER = CTL_BIT(2),///< [out] This BIT will be set if a dongle/hub/onboard protocol converter + ///< , is attached to the encoder + CTL_DISPLAY_CONFIG_FLAG_DITHERING_ENABLED = CTL_BIT(3), ///< [out] This BIT will be set if dithering is enabled on the encoder + CTL_DISPLAY_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_display_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief [out] Encoder configuration related flags which indicate how the +/// output pixel stream drive the panel +typedef uint32_t ctl_encoder_config_flags_t; +typedef enum _ctl_encoder_config_flag_t +{ + CTL_ENCODER_CONFIG_FLAG_INTERNAL_DISPLAY = CTL_BIT(0), ///< [out] Internal connection or not + CTL_ENCODER_CONFIG_FLAG_VESA_TILED_DISPLAY = CTL_BIT(1),///< [out] VESA DisplayID based tiled display which is driven by either + ///< multiple physical connections (DisplayPort SST) or virtual streams + ///< (DisplayPort MST) + CTL_ENCODER_CONFIG_FLAG_TYPEC_CAPABLE = CTL_BIT(2), ///< [out] This is set if encoder supports type c display + CTL_ENCODER_CONFIG_FLAG_TBT_CAPABLE = CTL_BIT(3), ///< [out] This is set if encoder supports Thunderbolt display + CTL_ENCODER_CONFIG_FLAG_DITHERING_SUPPORTED = CTL_BIT(4), ///< [out] This BIT will be set if encoder supports dithering + CTL_ENCODER_CONFIG_FLAG_VIRTUAL_DISPLAY = CTL_BIT(5), ///< [out] This BIT will be set if this is a virtual display.Hardware based + ///< features will not be applicable to this display.For collage display + ///< this will be set for the virtual output created by driver. For split + ///< display this will be set for the virtual split displays created out of + ///< one single physical display + CTL_ENCODER_CONFIG_FLAG_HIDDEN_DISPLAY = CTL_BIT(6),///< [out] This BIT will be set if display is hidden from OS + CTL_ENCODER_CONFIG_FLAG_COLLAGE_DISPLAY = CTL_BIT(7), ///< [out] This BIT will be set if this is a collage display + CTL_ENCODER_CONFIG_FLAG_SPLIT_DISPLAY = CTL_BIT(8), ///< [out] This BIT will be set if this is a split display + CTL_ENCODER_CONFIG_FLAG_COMPANION_DISPLAY = CTL_BIT(9), ///< [out] This BIT will be set if this is a companion display + CTL_ENCODER_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_encoder_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Timing +typedef struct _ctl_display_timing_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t PixelClock; ///< [out] Pixel Clock in Hz + uint32_t HActive; ///< [out] Horizontal Active + uint32_t VActive; ///< [out] Vertical Active + uint32_t HTotal; ///< [out] Horizontal Total + uint32_t VTotal; ///< [out] Vertical Total + uint32_t HBlank; ///< [out] Horizontal Blank + uint32_t VBlank; ///< [out] Vertical Blank + uint32_t HSync; ///< [out] Horizontal Blank + uint32_t VSync; ///< [out] Vertical Blank + float RefreshRate; ///< [out] Refresh Rate + ctl_signal_standard_type_t SignalStandard; ///< [out] Signal Standard + uint8_t VicId; ///< [out] VIC ID for CTA timings + +} ctl_display_timing_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief This structure will contain the properties of the display currently +/// attached to the encoder. +typedef struct _ctl_display_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_os_display_encoder_identifier_t Os_display_encoder_handle; ///< [out] OS specific Display ID + ctl_display_output_types_t Type; ///< [out] Device Type from display HW stand point. If a DisplayPort + ///< protocol converter is involved, this will indicate it's DisplayPort. + ///< The protocol converter's output will be available from + ///< ProtocolConverterOutput field + ctl_attached_display_mux_type_t AttachedDisplayMuxType; ///< [out] Attached Display Mux Type + ctl_display_output_types_t ProtocolConverterOutput; ///< [out] Protocol output type which can be used if config flags indicate + ///< it's a protocol converter. If it's not a protocol converter this will + ///< be set to CTL_DISPLAY_OUTPUT_TYPES_INVALID + ctl_revision_datatype_t SupportedSpec; ///< [out] Supported industry spec version. + ctl_output_bpc_flags_t SupportedOutputBPCFlags; ///< [out] Supported output bits per color. Refer ::ctl_output_bpc_flag_t. + ///< This is independent of RGB or YCbCr output.This is the max BPC + ///< supported.BPC will vary per mode based on restrictions like bandwidth + ///< and monitor support + ctl_protocol_converter_location_flags_t ProtocolConverterType; ///< [out] Currently Active Protocol Converter. Refer + ///< ::ctl_protocol_converter_location_flag_t + ctl_display_config_flags_t DisplayConfigFlags; ///< [out] Output configuration related flags which indicate how the output + ///< pixel stream drive the panel. Refer ::ctl_display_config_flag_t + ctl_std_display_feature_flags_t FeatureEnabledFlags;///< [out] Enabled Display features.Refer ::ctl_std_display_feature_flag_t. + ctl_std_display_feature_flags_t FeatureSupportedFlags; ///< [out] Display Supported feature.Refer ::ctl_std_display_feature_flag_t + ctl_intel_display_feature_flags_t AdvancedFeatureEnabledFlags; ///< [out] Enabled advanced feature.Refer + ///< ::ctl_intel_display_feature_flag_t. + ctl_intel_display_feature_flags_t AdvancedFeatureSupportedFlags;///< [out] Supported advanced feature.Refer + ///< ::ctl_intel_display_feature_flag_t. + ctl_display_timing_t Display_Timing_Info; ///< [out] Applied Timing on the Display + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_display_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adapter's display encoder properties +typedef struct _ctl_adapter_display_encoder_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_os_display_encoder_identifier_t Os_display_encoder_handle; ///< [out] OS specific Display ID + ctl_display_output_types_t Type; ///< [out] Device Type from display HW stand point. If a DisplayPort + ///< protocol converter is involved, this will indicate it's DisplayPort. + ///< The protocol converter's output will be available from + ///< ProtocolConverterOutput field + bool IsOnBoardProtocolConverterOutputPresent; ///< [out] Protocol output type which can be used if it's a protocol + ///< converter. If it's not a protocol converter this will be set to + ///< CTL_DISPLAY_OUTPUT_TYPES_INVALID + ctl_revision_datatype_t SupportedSpec; ///< [out] Supported industry spec version + ctl_output_bpc_flags_t SupportedOutputBPCFlags; ///< [out] Supported output bits per color. Refer ::ctl_output_bpc_flag_t. + ///< This is independent of RGB or YCbCr output.This is the max BPC + ///< supported.BPC will vary per mode based on restrictions like bandwidth + ///< and monitor support + ctl_encoder_config_flags_t EncoderConfigFlags; ///< [out] Output configuration related flags which indicate how the output + ///< pixel stream drive the panel. Refer ::ctl_encoder_config_flag_t + ///< Note: + ///< Virtual = 1: This indicates that its a software display. Hardware + ///< based features will not be applicable to this display. + ///< Collage=1,Virtual=1: Indicates the fake display output created by + ///< driver which has the combined resolution of multiple physical displays + ///< involved in collage configuration + ///< Collage=1,Virtual=0: Indicates the child physical displays involved + ///< in a collage configuration. These are real physical outputs + ///< Split=1,Virtual=1 : Indicates the fake display output created by + ///< driver which occupies a portion of a real physical display + ///< Split=1,Virtual=0 : Indicates the physical display which got split + ///< to form multiple split displays + ///< Split=1,Collage=1 : Invalid combination + ctl_std_display_feature_flags_t FeatureSupportedFlags; ///< [out] Adapter Supported feature flags. Refer + ///< ::ctl_std_display_feature_flag_t + ctl_intel_display_feature_flags_t AdvancedFeatureSupportedFlags;///< [out] Advanced Features Supported by the Adapter. Refer + ///< ::ctl_intel_display_feature_flag_t + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_adapter_display_encoder_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Device Properties +/// +/// @details +/// - The application gets device properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetDeviceProperties( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to control device adapter + ctl_device_adapter_properties_t* pProperties ///< [in,out][release] Query result for device properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Display Properties +/// +/// @details +/// - The application gets display properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetDisplayProperties( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_display_properties_t* pProperties ///< [in,out][release] Query result for display properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Adapter Display encoder Properties +/// +/// @details +/// - The application gets the graphic adapters display encoder properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetAdaperDisplayEncoderProperties( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_adapter_display_encoder_properties_t* pProperties ///< [in,out][release] Query result for adapter display encoder properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Level0 Device handle +/// +/// @details +/// - The application gets OneAPI Level0 Device handles +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pZeDevice` +/// + `nullptr == hInstance` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetZeDevice( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + void* pZeDevice, ///< [out][release] ze_device handle + void** hInstance ///< [out][release] Module instance which caller can use to get export + ///< functions directly + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various sharpness filter types +typedef uint32_t ctl_sharpness_filter_type_flags_t; +typedef enum _ctl_sharpness_filter_type_flag_t +{ + CTL_SHARPNESS_FILTER_TYPE_FLAG_NON_ADAPTIVE = CTL_BIT(0), ///< Non-adaptive sharpness + CTL_SHARPNESS_FILTER_TYPE_FLAG_ADAPTIVE = CTL_BIT(1), ///< Adaptive sharpness + CTL_SHARPNESS_FILTER_TYPE_FLAG_MAX = 0x80000000 + +} ctl_sharpness_filter_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sharpness filter properties +typedef struct _ctl_sharpness_filter_properties_t +{ + ctl_sharpness_filter_type_flags_t FilterType; ///< [out] Filter type. Refer ::ctl_sharpness_filter_type_flag_t + ctl_property_range_info_t FilterDetails; ///< [out] Min, max & step size information + +} ctl_sharpness_filter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various sharpness filter types +typedef struct _ctl_sharpness_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_sharpness_filter_type_flags_t SupportedFilterFlags; ///< [out] Supported sharpness filters for a given display output. Refer + ///< ::ctl_sharpness_filter_type_flag_t + uint8_t NumFilterTypes; ///< [out] Number of elements in filter properties array + ctl_sharpness_filter_properties_t* pFilterProperty; ///< [in,out] Array of filter properties structure describing supported + ///< filter capabilities. Caller should provide a pre-allocated memory for + ///< this. + +} ctl_sharpness_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Current sharpness setting +typedef struct _ctl_sharpness_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enable; ///< [in,out] Current or new state of sharpness setting + ctl_sharpness_filter_type_flags_t FilterType; ///< [in,out] Current or new filter to be set. Refer + ///< ::ctl_sharpness_filter_type_flag_t + float Intensity; ///< [in,out] Setting intensity to be applied + +} ctl_sharpness_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Sharpness capability +/// +/// @details +/// - Returns sharpness capability +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSharpnessCaps( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_caps_t* pSharpnessCaps ///< [in,out][release] Query result for sharpness capability + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Sharpness setting +/// +/// @details +/// - Returns current sharpness settings +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetCurrentSharpness( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_settings_t* pSharpnessSettings ///< [in,out][release] Query result for sharpness current settings + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Sharpness setting +/// +/// @details +/// - Set current sharpness settings +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetCurrentSharpness( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_settings_t* pSharpnessSettings ///< [in][release] Set sharpness current settings + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_I2C_MAX_DATA_SIZE +/// @brief I2C Maximum data size +#define CTL_I2C_MAX_DATA_SIZE 0x0080 +#endif // CTL_I2C_MAX_DATA_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2CFlags bitmasks +typedef uint32_t ctl_i2c_flags_t; +typedef enum _ctl_i2c_flag_t +{ + CTL_I2C_FLAG_ATOMICI2C = CTL_BIT(0), ///< Force Atomic I2C + CTL_I2C_FLAG_MAX = 0x80000000 + +} ctl_i2c_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C access arguments +typedef struct _ctl_i2c_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t DataSize; ///< [in,out] Valid data size + uint32_t Address; ///< [in] Adreess to read or write + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write, for Write operation, App + ///< needs to run with admin privileges + uint32_t Offset; ///< [in] Offset + ctl_i2c_flags_t Flags; ///< [in] I2C Flags. Refer ::ctl_i2c_flag_t + uint64_t RAD; ///< [in] RAD, For Future use, to be used for branch devices, Interface + ///< will be provided to get RAD + uint8_t Data[CTL_I2C_MAX_DATA_SIZE]; ///< [in,out] Data array + +} ctl_i2c_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C Access +/// +/// @details +/// - The application does I2C aceess +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pI2cAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid I2C data size" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlI2CAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_i2c_access_args_t* pI2cAccessArgs ///< [in,out] I2c access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_AUX_MAX_DATA_SIZE +/// @brief Aux Maximum data size +#define CTL_AUX_MAX_DATA_SIZE 132 +#endif // CTL_AUX_MAX_DATA_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief AUX Flags bitmasks +typedef uint32_t ctl_aux_flags_t; +typedef enum _ctl_aux_flag_t +{ + CTL_AUX_FLAG_NATIVE_AUX = CTL_BIT(0), ///< For Native AUX operation + CTL_AUX_FLAG_I2C_AUX = CTL_BIT(1), ///< For I2C AUX operation + CTL_AUX_FLAG_I2C_AUX_MOT = CTL_BIT(2), ///< For I2C AUX MOT operation + CTL_AUX_FLAG_MAX = 0x80000000 + +} ctl_aux_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief AUX access arguments +typedef struct _ctl_aux_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write, for Write operation, App + ///< needs to run with admin privileges + ctl_aux_flags_t Flags; ///< [in] Aux Flags. Refer ::ctl_aux_flag_t + uint32_t Address; ///< [in] Adreess to read or write + uint64_t RAD; ///< [in] RAD, For Future use, to be used for branch devices, Interface + ///< will be provided to get RAD + uint32_t PortID; ///< [in] Port ID, For Future use, to be used for SST tiled devices + uint32_t DataSize; ///< [in,out] Valid data size + uint8_t Data[CTL_AUX_MAX_DATA_SIZE]; ///< [in,out] Data array + +} ctl_aux_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Aux Access +/// +/// @details +/// - The application does Aux aceess, PSR needs to be disabled for AUX +/// call. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pAuxAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid AUX data size" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_INVALID_AUX_ACCESS_FLAG - "Invalid flag for AUX access" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlAUXAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_aux_access_args_t* pAuxAccessArgs ///< [in,out] Aux access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power saving features (Each individual feature's set & get call can be +/// called only once at a time) +typedef uint32_t ctl_power_optimization_flags_t; +typedef enum _ctl_power_optimization_flag_t +{ + CTL_POWER_OPTIMIZATION_FLAG_FBC = CTL_BIT(0), ///< Frame buffer compression + CTL_POWER_OPTIMIZATION_FLAG_PSR = CTL_BIT(1), ///< Panel self refresh + CTL_POWER_OPTIMIZATION_FLAG_DPST = CTL_BIT(2), ///< Display power saving technology (Panel technology dependent) + CTL_POWER_OPTIMIZATION_FLAG_LRR = CTL_BIT(3), ///< Low refresh rate (LRR/ALRR/UBRR), UBRR is supported only for IGCC and + ///< NDA clients. UBZRR and UBLRR both can not be enabled at the same time, + ///< only one can be enabled at a given time + CTL_POWER_OPTIMIZATION_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief GPU/Panel/TCON dependent power optimization technology +typedef uint32_t ctl_power_optimization_dpst_flags_t; +typedef enum _ctl_power_optimization_dpst_flag_t +{ + CTL_POWER_OPTIMIZATION_DPST_FLAG_BKLT = CTL_BIT(0), ///< Intel DPST with Backlight control + CTL_POWER_OPTIMIZATION_DPST_FLAG_PANEL_CABC = CTL_BIT(1), ///< Panel TCON specific Content Adaptive Control mechanism + CTL_POWER_OPTIMIZATION_DPST_FLAG_OPST = CTL_BIT(2), ///< Intel OLED Power Saving Technology + CTL_POWER_OPTIMIZATION_DPST_FLAG_ELP = CTL_BIT(3), ///< TCON based Edge Luminance Profile + CTL_POWER_OPTIMIZATION_DPST_FLAG_EPSM = CTL_BIT(4), ///< Extra power saving mode + CTL_POWER_OPTIMIZATION_DPST_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_dpst_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Source +typedef enum _ctl_power_source_t +{ + CTL_POWER_SOURCE_AC = 0, ///< Power Source AC + CTL_POWER_SOURCE_DC = 1, ///< Power Source DC + CTL_POWER_SOURCE_MAX + +} ctl_power_source_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Optimization Plan +typedef enum _ctl_power_optimization_plan_t +{ + CTL_POWER_OPTIMIZATION_PLAN_BALANCED = 0, ///< Balanced mode + CTL_POWER_OPTIMIZATION_PLAN_HIGH_PERFORMANCE = 1, ///< High Performance Mode + CTL_POWER_OPTIMIZATION_PLAN_POWER_SAVER = 2, ///< Power Saver Mode + CTL_POWER_OPTIMIZATION_PLAN_MAX + +} ctl_power_optimization_plan_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Type of low refresh rate feature +typedef uint32_t ctl_power_optimization_lrr_flags_t; +typedef enum _ctl_power_optimization_lrr_flag_t +{ + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR10 = CTL_BIT(0), ///< LRR 1.0 + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR20 = CTL_BIT(1), ///< LRR 2.0 + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR25 = CTL_BIT(2), ///< LRR 2.5 + CTL_POWER_OPTIMIZATION_LRR_FLAG_ALRR = CTL_BIT(3), ///< Autonomous LRR + CTL_POWER_OPTIMIZATION_LRR_FLAG_UBLRR = CTL_BIT(4), ///< User based low refresh rate + CTL_POWER_OPTIMIZATION_LRR_FLAG_UBZRR = CTL_BIT(5), ///< User based zero refresh rate + CTL_POWER_OPTIMIZATION_LRR_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_lrr_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power optimization caps +typedef struct _ctl_power_optimization_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_flags_t SupportedFeatures; ///< [out] Supported power optimization features. Refer + ///< ::ctl_power_optimization_flag_t + +} ctl_power_optimization_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power optimization features +/// +/// @details +/// - Returns power optimization capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetPowerOptimizationCaps( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_caps_t* pPowerOptimizationCaps ///< [in,out][release] Query result for power optimization features + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief LRR detailed settings +typedef struct _ctl_power_optimization_lrr_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_lrr_flags_t SupportedLRRTypes; ///< [out] LRR type(s). Refer ::ctl_power_optimization_lrr_flag_t + ctl_power_optimization_lrr_flags_t CurrentLRRTypes; ///< [in,out] Current enabled LRR type(s) or the LRR type(s) to set to. + ///< Refer ::ctl_power_optimization_lrr_flag_t + bool bRequirePSRDisable; ///< [out] Require PSR disable for any change in the selected LRR feature. + ///< Caller can re-enable PSR once the respective LRR feature is + ///< enable/disabled. E.g. for UBRR based on platform this flag may not be + ///< set in which case caller doesn't need to do an explicit PSR disable + uint16_t LowRR; ///< [out] Lowest RR used for LRR functionality if known to source + +} ctl_power_optimization_lrr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSR detailed settings +typedef struct _ctl_power_optimization_psr_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t PSRVersion; ///< [in,out] A value of 1 means PSR1, 2 means PSR2 + bool FullFetchUpdate; ///< [in,out] Full fetch and update + +} ctl_power_optimization_psr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief DPST detailed settings +typedef struct _ctl_power_optimization_dpst_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t MinLevel; ///< [out] Minimum supported aggressiveness level + uint8_t MaxLevel; ///< [out] Maximum supported aggressiveness level + uint8_t Level; ///< [in,out] Current aggressiveness level to be set + ctl_power_optimization_dpst_flags_t SupportedFeatures; ///< [out] Supported features + ctl_power_optimization_dpst_flags_t EnabledFeatures;///< [in,out] Features enabled or to be enabled + +} ctl_power_optimization_dpst_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature specific power optimization data +typedef union _ctl_power_optimization_feature_specific_info_t +{ + ctl_power_optimization_lrr_t LRRInfo; ///< [out] LRR info + ctl_power_optimization_psr_t PSRInfo; ///< [in,out] PSR info + ctl_power_optimization_dpst_t DPSTInfo; ///< [in,out] DPST info + +} ctl_power_optimization_feature_specific_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power optimization settings +typedef struct _ctl_power_optimization_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_plan_t PowerOptimizationPlan;///< [in] Power optimization power plan (max power/max perf/balanced) + ctl_power_optimization_flags_t PowerOptimizationFeature;///< [in] Power optimization feature interested in. Refer + ///< ::ctl_power_optimization_flag_t + bool Enable; ///< [in,out] Enable state + ctl_power_optimization_feature_specific_info_t FeatureSpecificData; ///< [in,out] Data specific to the feature caller is interested in + ctl_power_source_t PowerSource; ///< [in] AC/DC + +} ctl_power_optimization_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Brightness settings for SET call +typedef struct _ctl_set_brightness_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t TargetBrightness; ///< [in] The brightness level that the display need to transitioning to in + ///< milli-percentage. Range is 0-100000 (100%) + uint32_t SmoothTransitionTimeInMs; ///< [in] Transition Time for brightness to take effect in milli-seconds. + ///< If its 0 then it will be an immediate change. Maximum possible value + ///< is 1000ms. + uint32_t ReservedFields[4]; ///< [in] Reserved for future use + +} ctl_set_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Brightness settings for GET call +typedef struct _ctl_get_brightness_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t TargetBrightness; ///< [out] The brightness level that the display is currently transitioning + ///< to in milli-percentage. If not in a transition, this should equal the + ///< current brightness. Range is 0-100000 (100%) + uint32_t CurrentBrightness; ///< [out] The current brightness level of the display in milli-percentage + uint32_t ReservedFields[4]; ///< [out] Reserved for future use + +} ctl_get_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power optimization setting +/// +/// @details +/// - Returns power optimization setting for a specific feature +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG - "Unsupported PowerOptimizationFeature" +/// - ::CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST - "DPST is supported only in DC Mode" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetPowerOptimizationSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_settings_t* pPowerOptimizationSettings ///< [in,out][release] Power optimization data to be fetched + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Power optimization setting +/// +/// @details +/// - Set power optimization setting for a specific feature +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG - "Unsupported PowerOptimizationFeature" +/// - ::CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST - "DPST is supported only in DC Mode" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetPowerOptimizationSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_settings_t* pPowerOptimizationSettings ///< [in][release] Power optimization data to be applied + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Brightness on companion display +/// +/// @details +/// - Set Brightness for a target display. Currently support is only for +/// companion display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSetBrightnessSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid Brightness data passed as argument" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE - "Display not active" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Currently Brightness API is supported only on companion display" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetBrightnessSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_set_brightness_t* pSetBrightnessSetting ///< [in][release] Brightness settings to be applied + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Brightness setting +/// +/// @details +/// - Get Brightness for a target display. Currently support is only for +/// companion display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetBrightnessSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE - "Display not active" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Currently Brightness API is supported only on companion display" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetBrightnessSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_get_brightness_t* pGetBrightnessSetting ///< [out][release] Brightness settings data to be fetched + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT +/// @brief Maximum number of samples per channel 1D LUT +#define CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT 8192 +#endif // CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixtx pipe set configuration flags bitmasks +typedef uint32_t ctl_pixtx_pipe_set_config_flags_t; +typedef enum _ctl_pixtx_pipe_set_config_flag_t +{ + CTL_PIXTX_PIPE_SET_CONFIG_FLAG_PERSIST_ACROSS_POWER_EVENTS = CTL_BIT(0),///< For maintaining persistance across power events + CTL_PIXTX_PIPE_SET_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_pixtx_pipe_set_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation block types +typedef enum _ctl_pixtx_block_type_t +{ + CTL_PIXTX_BLOCK_TYPE_1D_LUT = 1, ///< Block type 1D LUT + CTL_PIXTX_BLOCK_TYPE_3D_LUT = 2, ///< Block type 3D LUT + CTL_PIXTX_BLOCK_TYPE_3X3_MATRIX = 3, ///< Block type 3x3 matrix + CTL_PIXTX_BLOCK_TYPE_3X3_MATRIX_AND_OFFSETS = 4,///< Block type 3x3 matrix and offsets + CTL_PIXTX_BLOCK_TYPE_MAX + +} ctl_pixtx_block_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation LUT sampling types +typedef enum _ctl_pixtx_lut_sampling_type_t +{ + CTL_PIXTX_LUT_SAMPLING_TYPE_UNIFORM = 0, ///< Uniform LUT sampling + CTL_PIXTX_LUT_SAMPLING_TYPE_NONUNIFORM = 1, ///< Non uniform LUT sampling, Required mainly in HDR mode + CTL_PIXTX_LUT_SAMPLING_TYPE_MAX + +} ctl_pixtx_lut_sampling_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configuration query types +typedef enum _ctl_pixtx_config_query_type_t +{ + CTL_PIXTX_CONFIG_QUERY_TYPE_CAPABILITY = 0, ///< Get complete pixel processing pipeline capability + CTL_PIXTX_CONFIG_QUERY_TYPE_CURRENT = 1, ///< Get the configuration set through last set call + CTL_PIXTX_CONFIG_QUERY_TYPE_MAX + +} ctl_pixtx_config_query_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configuration operation types +typedef enum _ctl_pixtx_config_opertaion_type_t +{ + CTL_PIXTX_CONFIG_OPERTAION_TYPE_RESTORE_DEFAULT = 1,///< Restore block by block or entire pipe line. Use NumBlocks = 0 to + ///< restore all. + CTL_PIXTX_CONFIG_OPERTAION_TYPE_SET_CUSTOM = 2, ///< Custom LUT or matrix can be set thorugh this option. + CTL_PIXTX_CONFIG_OPERTAION_TYPE_MAX + +} ctl_pixtx_config_opertaion_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation gamma encoding types +typedef enum _ctl_pixtx_gamma_encoding_type_t +{ + CTL_PIXTX_GAMMA_ENCODING_TYPE_SRGB = 0, ///< Gamma encoding SRGB + CTL_PIXTX_GAMMA_ENCODING_TYPE_REC709 = 1, ///< Gamma encoding REC709, Applicable for REC2020 as well + CTL_PIXTX_GAMMA_ENCODING_TYPE_ST2084 = 2, ///< Gamma encoding ST2084 + CTL_PIXTX_GAMMA_ENCODING_TYPE_HLG = 3, ///< Gamma encoding HLG + CTL_PIXTX_GAMMA_ENCODING_TYPE_LINEAR = 4, ///< Gamma encoding linear + CTL_PIXTX_GAMMA_ENCODING_TYPE_MAX + +} ctl_pixtx_gamma_encoding_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color space types +typedef enum _ctl_pixtx_color_space_t +{ + CTL_PIXTX_COLOR_SPACE_REC709 = 0, ///< Color space REC709 + CTL_PIXTX_COLOR_SPACE_REC2020 = 1, ///< Color space REC2020 + CTL_PIXTX_COLOR_SPACE_ADOBE_RGB = 2, ///< Color space AdobeRGB + CTL_PIXTX_COLOR_SPACE_P3_D65 = 3, ///< Color space P3_D65 + CTL_PIXTX_COLOR_SPACE_P3_DCI = 4, ///< Color space P3_DCI + CTL_PIXTX_COLOR_SPACE_P3_D60 = 5, ///< Color space P3_D60 + CTL_PIXTX_COLOR_SPACE_CUSTOM = 0xFFFF, ///< Color space custom, Refer ::ctl_pixtx_color_primaries_t for color + ///< primary details + CTL_PIXTX_COLOR_SPACE_MAX + +} ctl_pixtx_color_space_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color model types +typedef enum _ctl_pixtx_color_model_t +{ + CTL_PIXTX_COLOR_MODEL_RGB_FR = 0, ///< Color model RGB full range + CTL_PIXTX_COLOR_MODEL_RGB_LR = 1, ///< Color model RGB limited range + CTL_PIXTX_COLOR_MODEL_YCBCR_422_FR = 2, ///< Color model YCBCR 422 full range + CTL_PIXTX_COLOR_MODEL_YCBCR_422_LR = 3, ///< Color model YCBCR 422 limited range + CTL_PIXTX_COLOR_MODEL_YCBCR_420_FR = 4, ///< Color model YCBCR 420 full range + CTL_PIXTX_COLOR_MODEL_YCBCR_420_LR = 5, ///< Color model YCBCR 420 limited range + CTL_PIXTX_COLOR_MODEL_MAX + +} ctl_pixtx_color_model_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color primaries +typedef struct _ctl_pixtx_color_primaries_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double xR; ///< [out] CIE1931 x value with maximum red pixel value + double yR; ///< [out] CIE1931 y value with maximum red pixel value + double xG; ///< [out] CIE1931 x value with maximum green pixel value + double yG; ///< [out] CIE1931 y value with maximum green pixel value + double xB; ///< [out] CIE1931 x value with maximum blue pixel value + double yB; ///< [out] CIE1931 y value with maximum blue pixel value + double xW; ///< [out] CIE1931 x value with maximum white pixel value + double yW; ///< [out] CIE1931 y value with maximum white pixel value + +} ctl_pixtx_color_primaries_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pixel format +typedef struct _ctl_pixtx_pixel_format_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t BitsPerColor; ///< [out] Bits per color, It Will be 16 for FP16 case + bool IsFloat; ///< [out] Will be set for FP16 or other floating point encoding schemes + ctl_pixtx_gamma_encoding_type_t EncodingType; ///< [out] Encoding type + ctl_pixtx_color_space_t ColorSpace; ///< [out] Color space + ctl_pixtx_color_model_t ColorModel; ///< [out] Color model + ctl_pixtx_color_primaries_t ColorPrimaries; ///< [out] Color primaries, Used mainly for custom color space + double MaxBrightness; ///< [out] Maximum brightness of pixel values. If no input is given, + ///< default will be set to sRGB during set call. If panel capability is + ///< not known get call will default to sRGB. + double MinBrightness; ///< [out] Minimum brightness of pixel values + +} ctl_pixtx_pixel_format_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 1D LUT configuration +typedef struct _ctl_pixtx_1dlut_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_lut_sampling_type_t SamplingType; ///< [in,out] Blocks with non-uniform sampling capability support unifrom + ///< sampling also but not vice versa. + uint32_t NumSamplesPerChannel; ///< [in,out] Number of samples per channel. Resampled internally based on + ///< HW capability for uniformly sampled LUT.Maximum supported value is + ///< ::CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT Caller needs to use exact + ///< sampling position given in pSamplePositions for non-uniformly sampled + ///< LUTs. + uint32_t NumChannels; ///< [in,out] Number of channels, 1 for Grey scale LUT, 3 for RGB LUT + double* pSampleValues; ///< [in,out] Pointer to sample values, R array followed by G and B arrays + ///< in case of multi-channel LUT. Allocation size for pSampleValues should + ///< be NumSamplesPerChannel * NumChannels * sizeof(double) + double* pSamplePositions; ///< [out] LUT (same for all channels) to represent sampling positions for + ///< non-uniformly sampled LUTs.Can be NULL in case uniformly sampled LUTs + +} ctl_pixtx_1dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation matrix configuration +typedef struct _ctl_pixtx_matrix_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double PreOffsets[3]; ///< [in,out] Pre offsets + double PostOffsets[3]; ///< [in,out] Post offsets + double Matrix[3][3]; ///< [in,out] 3x3 Matrix + +} ctl_pixtx_matrix_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 3D LUT sample. Samples are converted to integer +/// based on underlying HW capabilities. Hence slight precision loss will +/// be observed while getting sample values. +typedef struct _ctl_pixtx_3dlut_sample_t +{ + double Red; ///< [in,out] Red output value + double Green; ///< [in,out] Green output value + double Blue; ///< [in,out] Blue output value + +} ctl_pixtx_3dlut_sample_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 3D LUT configuration +typedef struct _ctl_pixtx_3dlut_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSamplesPerChannel; ///< [in,out] Number of samples per channel + ctl_pixtx_3dlut_sample_t* pSampleValues; ///< [in,out] Pointer to sample values, R in outer most loop followed by G + ///< and B + +} ctl_pixtx_3dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation configuration +typedef union _ctl_pixtx_config_t +{ + ctl_pixtx_1dlut_config_t OneDLutConfig; ///< [in,out] 1D LUT configuration + ctl_pixtx_3dlut_config_t ThreeDLutConfig; ///< [in,out] 3D LUT configuration + ctl_pixtx_matrix_config_t MatrixConfig; ///< [in,out] Matrix configuration + +} ctl_pixtx_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation block configuration +typedef struct _ctl_pixtx_block_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t BlockId; ///< [in,out] Unique ID for each pixel processing block. Id for a block is + ///< fixed for a platform. + ctl_pixtx_block_type_t BlockType; ///< [in,out] Block type + ctl_pixtx_config_t Config; ///< [in,out] Configuration + +} ctl_pixtx_block_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pipe get configuration +typedef struct _ctl_pixtx_pipe_get_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_config_query_type_t QueryType; ///< [in] Query operation type + ctl_pixtx_pixel_format_t InputPixelFormat; ///< [out] Input pixel format + ctl_pixtx_pixel_format_t OutputPixelFormat; ///< [out] Output pixel format + uint32_t NumBlocks; ///< [out] Number of blocks + ctl_pixtx_block_config_t* pBlockConfigs; ///< [out] Pointer to specific configs + +} ctl_pixtx_pipe_get_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pipe set configuration +typedef struct _ctl_pixtx_pipe_set_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_config_opertaion_type_t OpertaionType;///< [in] Set operation type + ctl_pixtx_pipe_set_config_flags_t Flags; ///< [in] Config flags. Refer ::ctl_pixtx_pipe_set_config_flag_t + uint32_t NumBlocks; ///< [in] Number of blocks + ctl_pixtx_block_config_t* pBlockConfigs; ///< [in,out] Array of block specific configs + +} ctl_pixtx_pipe_set_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation get pipe configuration +/// +/// @details +/// - The application does pixel transformation get pipe configuration +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPixTxGetConfigArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_GET_CONFIG_QUERY_TYPE - "Invalid query type" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID - "Invalid block id" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PIXTX_BLOCK_CONFIG_MEMORY - "Insufficient memery allocated for BlockConfigs" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_PIPE - "Invalid pipe for 3dlut" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_DATA - "Invalid 3dlut data" +/// - ::CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR - "3dlut not supported in HDR" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION - "Invalid 3dlut operation" +/// - ::CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL - "3dlut call unsuccessful" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPixelTransformationGetConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_pixtx_pipe_get_config_t* pPixTxGetConfigArgs///< [in,out] Pixel transformation get pipe configiguration arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation set pipe configuration +/// +/// @details +/// - The application does pixel transformation set pipe configuration +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPixTxSetConfigArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_SET_CONFIG_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SET_CONFIG_NUMBER_OF_SAMPLES - "Invalid number of samples" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID - "Invalid block id" +/// - ::CTL_RESULT_ERROR_PERSISTANCE_NOT_SUPPORTED - "Persistance not supported" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_PIPE - "Invalid pipe for 3dlut" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_DATA - "Invalid 3dlut data" +/// - ::CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR - "3dlut not supported in HDR" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION - "Invalid 3dlut operation" +/// - ::CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL - "3dlut call unsuccessful" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPixelTransformationSetConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_pixtx_pipe_set_config_t* pPixTxSetConfigArgs///< [in,out] Pixel transformation set pipe configiguration arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Panel descriptor access arguments +typedef struct _ctl_panel_descriptor_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write. App needs to run with + ///< admin privileges for Write operation, Currently only Read operation is + ///< supported + uint32_t BlockNumber; ///< [in] Block number, Need to provide only if acccessing EDID + uint32_t DescriptorDataSize; ///< [in] Descriptor data size, Should be 0 for querying the size and + ///< should be DescriptorDataSize derived from query call otherwise + uint8_t* pDescriptorData; ///< [in,out] Panel descriptor data + +} ctl_panel_descriptor_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Panel Descriptor Access +/// +/// @details +/// - The application does EDID or Display ID access +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPanelDescriptorAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPanelDescriptorAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_panel_descriptor_access_args_t* pPanelDescriptorAccessArgs ///< [in,out] Panel descriptor access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retro Scaling Types +typedef uint32_t ctl_retro_scaling_type_flags_t; +typedef enum _ctl_retro_scaling_type_flag_t +{ + CTL_RETRO_SCALING_TYPE_FLAG_INTEGER = CTL_BIT(0), ///< Integer Scaling + CTL_RETRO_SCALING_TYPE_FLAG_NEAREST_NEIGHBOUR = CTL_BIT(1), ///< Nearest Neighbour Scaling + CTL_RETRO_SCALING_TYPE_FLAG_MAX = 0x80000000 + +} ctl_retro_scaling_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get Retro Scaling Type +typedef struct _ctl_retro_scaling_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Get; ///< [in][release] Set to true to get current scaling . Set to False to Set + ///< the scaling + bool Enable; ///< [in,out] State of the scaler + ctl_retro_scaling_type_flags_t RetroScalingType;///< [out] Requested retro scaling types. Refer + ///< ::ctl_retro_scaling_type_flag_t + +} ctl_retro_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retro Scaling caps +typedef struct _ctl_retro_scaling_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_retro_scaling_type_flags_t SupportedRetroScaling; ///< [out] Supported retro scaling types + +} ctl_retro_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Supported Retro Scaling Types +/// +/// @details +/// - Returns supported retro scaling capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pRetroScalingCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedRetroScalingCapability( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + ctl_retro_scaling_caps_t* pRetroScalingCaps ///< [in,out][release] Query result for supported retro scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Retro Scaling +/// +/// @details +/// - Get or Set the status of retro scaling.This Api will do a physical +/// modeset resulting in flash on the screen +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetSetRetroScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetRetroScaling( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + ctl_retro_scaling_settings_t* pGetSetRetroScalingType ///< [in,out][release] Get or Set the retro scaling type + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Scaling Types +typedef uint32_t ctl_scaling_type_flags_t; +typedef enum _ctl_scaling_type_flag_t +{ + CTL_SCALING_TYPE_FLAG_IDENTITY = CTL_BIT(0), ///< No scaling is applied and display manages scaling itself when possible + CTL_SCALING_TYPE_FLAG_CENTERED = CTL_BIT(1), ///< Source is not scaled but place in the center of the target display + CTL_SCALING_TYPE_FLAG_STRETCHED = CTL_BIT(2), ///< Source is stretched to fit the target size + CTL_SCALING_TYPE_FLAG_ASPECT_RATIO_CENTERED_MAX = CTL_BIT(3), ///< The aspect ratio is maintained with the source centered + CTL_SCALING_TYPE_FLAG_CUSTOM = CTL_BIT(4), ///< None of the standard types match this .Additional parameters are + ///< required which should be set via a private driver interface + CTL_SCALING_TYPE_FLAG_MAX = 0x80000000 + +} ctl_scaling_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Scaling caps +typedef struct _ctl_scaling_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_scaling_type_flags_t SupportedScaling; ///< [out] Supported scaling types. Refer ::ctl_scaling_type_flag_t + +} ctl_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get Scaling type +typedef struct _ctl_scaling_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enable; ///< [in,out] State of the scaler + ctl_scaling_type_flags_t ScalingType; ///< [in,out] Requested scaling types. Refer ::ctl_scaling_type_flag_t + uint32_t CustomScalingX; ///< [in,out] Custom Scaling X resolution + uint32_t CustomScalingY; ///< [in,out] Custom Scaling Y resolution + bool HardwareModeSet; ///< [in] Flag to indicate hardware modeset should be done to apply the + ///< scaling.Setting this to true would result in a flash on the screen. If + ///< this flag is set to false , API will request the OS to do a virtual + ///< modeset , but the OS can ignore this request and do a hardware modeset + ///< in some instances + +} ctl_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Supported Scaling Types +/// +/// @details +/// - Returns supported scaling capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pScalingCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedScalingCapability( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_caps_t* pScalingCaps ///< [in,out][release] Query result for supported scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Current Scaling +/// +/// @details +/// - Returns current active scaling +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetCurrentScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetCurrentScaling( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_settings_t* pGetCurrentScalingType ///< [in,out][release] Query result for active scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Scaling Type +/// +/// @details +/// - Returns current active scaling +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSetScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetCurrentScaling( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_settings_t* pSetScalingType ///< [in,out][release] Set scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Ambient light based enhancement table entry +typedef struct _ctl_lace_lux_aggr_map_entry_t +{ + uint32_t Lux; ///< [in,out] Ambient lux + uint8_t AggressivenessPercent; ///< [in,out] Pixel boost agressiveness + +} ctl_lace_lux_aggr_map_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Ambient light based enhancement table +typedef struct _ctl_lace_lux_aggr_map_t +{ + uint32_t MaxNumEntries; ///< [out] Max Number of entries in mapping table supported + uint32_t NumEntries; ///< [in,out] Number of entries in the given mapping table + ctl_lace_lux_aggr_map_entry_t* pLuxToAggrMappingTable; ///< [in] Max number of Entries which can be passed in + ///< LuxToAggrMappingTable + +} ctl_lace_lux_aggr_map_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Data specific to the mode caller is interested in +typedef union _ctl_lace_aggr_config_t +{ + uint8_t FixedAggressivenessLevelPercent; ///< [in,out] Fixed aggressiveness level, applicable for + ///< CTL_LACE_MODE_FIXED_AGGR_LEVEL + ctl_lace_lux_aggr_map_t AggrLevelMap; ///< [in,out] Lux to enhancement mapping table, applicable for + ///< CTL_LACE_MODE_AMBIENT_ADAPTIVE + +} ctl_lace_aggr_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Operations used for additional settings +typedef uint32_t ctl_get_operation_flags_t; +typedef enum _ctl_get_operation_flag_t +{ + CTL_GET_OPERATION_FLAG_CURRENT = CTL_BIT(0), ///< Get the details set through last set call + CTL_GET_OPERATION_FLAG_DEFAULT = CTL_BIT(1), ///< Get the driver default values + CTL_GET_OPERATION_FLAG_CAPABILITY = CTL_BIT(2), ///< Get capability + CTL_GET_OPERATION_FLAG_MAX = 0x80000000 + +} ctl_get_operation_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Operations used for additional settings +typedef enum _ctl_set_operation_t +{ + CTL_SET_OPERATION_RESTORE_DEFAULT = 0, ///< Restore default values + CTL_SET_OPERATION_CUSTOM = 1, ///< Set custom values + CTL_SET_OPERATION_MAX + +} ctl_set_operation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Lace Trigger Modes +typedef uint32_t ctl_lace_trigger_flags_t; +typedef enum _ctl_lace_trigger_flag_t +{ + CTL_LACE_TRIGGER_FLAG_AMBIENT_LIGHT = CTL_BIT(0), ///< LACE enhancement depends on Ambient light + CTL_LACE_TRIGGER_FLAG_FIXED_AGGRESSIVENESS = CTL_BIT(1),///< LACE enhancement is as per given fixed aggressiveness level + CTL_LACE_TRIGGER_FLAG_MAX = 0x80000000 + +} ctl_lace_trigger_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get LACE Config +typedef struct _ctl_lace_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enabled; ///< [in,out] Enable or disable LACE feature + ctl_get_operation_flags_t OpTypeGet; ///< [in] Get Operations used for additional settings + ctl_set_operation_t OpTypeSet; ///< [in] Set Operations used for additional settings + ctl_lace_trigger_flags_t Trigger; ///< [in,out] LACE operating mode to be Triggerd + ctl_lace_aggr_config_t LaceConfig; ///< [in,out] Data specific to the mode, caller is interested in + +} ctl_lace_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get LACE Config +/// +/// @details +/// - Returns current LACE Config +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLaceConfig` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED - "Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data passed by user" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetLACEConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_lace_config_t* pLaceConfig ///< [out]Lace configuration + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sets LACE Config +/// +/// @details +/// - Sets LACE Config +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLaceConfig` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED - "Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data passed by user" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetLACEConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in]Handle to display output + ctl_lace_config_t* pLaceConfig ///< [in]Lace configuration + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Software PSR status/Set Software PSR settings +typedef struct _ctl_sw_psr_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Set; ///< [in][release] Set to False to Get Software PSR status. Set to True to + ///< Enable/Disable Software PSR + bool Supported; ///< [out] When Get is True, returns if SW PSR is supported + bool Enable; ///< [in,out] When Get is True, returns current state of Software PSR. + ///< When Get is False, Enables/Diasbles Software PSR + +} ctl_sw_psr_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Software PSR caps/Set software PSR State +/// +/// @details +/// - Returns Software PSR status or Sets Software PSR capabilities. This is +/// a reserved capability. By default, software PSR is not supported/will +/// not be enabled, need application to activate it, please contact Intel +/// for activation. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSoftwarePsrSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSoftwarePSR( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sw_psr_settings_t* pSoftwarePsrSetting ///< [in,out][release] Get Software PSR caps/state or Set Software PSR + ///< state + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync Monitor Params +typedef struct _ctl_intel_arc_sync_monitor_params_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool IsIntelArcSyncSupported; ///< [out] Intel Arc Sync support for the monitor + float MinimumRefreshRateInHz; ///< [out] Minimum Intel Arc Sync refresh rate supported by the monitor + float MaximumRefreshRateInHz; ///< [out] Maximum Intel Arc Sync refresh rate supported by the monitor + uint32_t MaxFrameTimeIncreaseInUs; ///< [out] Max frame time increase in micro seconds from DID2.1 Adaptive + ///< Sync block + uint32_t MaxFrameTimeDecreaseInUs; ///< [out] Max frame time decrease in micro seconds from DID2.1 Adaptive + ///< Sync block + +} ctl_intel_arc_sync_monitor_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Intel Arc Sync information for monitor +/// +/// @details +/// - Returns Intel Arc Sync information for selected monitor +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncMonitorParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetIntelArcSyncInfoForMonitor( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_monitor_params_t* pIntelArcSyncMonitorParams ///< [in,out][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a MUX output instance +typedef struct _ctl_mux_output_handle_t *ctl_mux_output_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate Display MUX Devices on this system across adapters +/// +/// @details +/// - The application enumerates all MUX devices in the system +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// + `nullptr == phMuxDevices` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateMuxDevices( + ctl_api_handle_t hAPIHandle, ///< [in][release] Applications should pass the Control API handle returned + ///< by the CtlInit function + uint32_t* pCount, ///< [in,out][release] pointer to the number of MUX device instances. If + ///< input count is zero, then the api will update the value with the total + ///< number of MUX devices available and return the Count value. If input + ///< count is non-zero, then the api will only retrieve the number of MUX Devices. + ///< If count is larger than the number of MUX devices available, then the + ///< api will update the value with the correct number of MUX devices available. + ctl_mux_output_handle_t* phMuxDevices ///< [out][range(0, *pCount)] array of MUX device instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display MUX device properties +typedef struct _ctl_mux_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t MuxId; ///< [out] MUX ID of this MUX device enumerated + uint32_t Count; ///< [in,out] Pointer to the number of display output instances this MUX + ///< object can drive. If count is zero, then the api will update the value + ///< with the total + ///< number of outputs available. If count is non-zero, then the api will + ///< only retrieve the number of outputs. + ///< If count is larger than the number of display outputs MUX can drive, + ///< then the api will update the value with the correct number of display + ///< outputs MUX can driver. + ctl_display_output_handle_t* phDisplayOutputs; ///< [in,out][range(0, *pCount)] Array of display output instance handles + ///< this MUX device can drive + uint8_t IndexOfDisplayOutputOwningMux; ///< [out] [range(0, (Count-1))] This is the index into the + ///< phDisplayOutputs list to the display output which currently owns the + ///< MUX output. This doesn't mean display is active + +} ctl_mux_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Display Mux properties +/// +/// @details +/// - Get the propeties of the Mux device +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMuxDevice` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pMuxProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetMuxProperties( + ctl_mux_output_handle_t hMuxDevice, ///< [in] MUX device instance handle + ctl_mux_properties_t* pMuxProperties ///< [in,out] MUX device properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Switch Mux output +/// +/// @details +/// - Switches the MUX output +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMuxDevice` +/// + `nullptr == hInactiveDisplayOutput` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSwitchMux( + ctl_mux_output_handle_t hMuxDevice, ///< [in] MUX device instance handle + ctl_display_output_handle_t hInactiveDisplayOutput ///< [out] Input selection for this MUX, which if active will drive the + ///< output of this MUX device. This should be one of the display output + ///< handles reported under this MUX device's properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync profile +typedef enum _ctl_intel_arc_sync_profile_t +{ + CTL_INTEL_ARC_SYNC_PROFILE_INVALID = 0, ///< Invalid profile + CTL_INTEL_ARC_SYNC_PROFILE_RECOMMENDED = 1, ///< Default. Selects appropriate profile based on the monitor. COMPATIBLE + ///< profile is applied if profile is not available for the monitor + CTL_INTEL_ARC_SYNC_PROFILE_EXCELLENT = 2, ///< Unconstrained. Full VRR range of the monitor can be used + CTL_INTEL_ARC_SYNC_PROFILE_GOOD = 3, ///< Some minor range constraints, unlikely to effect user experience but + ///< can reduce flicker on some monitors + CTL_INTEL_ARC_SYNC_PROFILE_COMPATIBLE = 4, ///< Significant constraints that will reduce flicker considerably but are + ///< likely to cause some level of judder onscreen especially when refresh + ///< rates are changing rapidly + CTL_INTEL_ARC_SYNC_PROFILE_OFF = 5, ///< Disable Intel Arc Sync on this monitor. This disables variable rate + ///< flips on this monitor. All sync flips will occur at the OS requested + ///< refresh rate + CTL_INTEL_ARC_SYNC_PROFILE_VESA = 6, ///< Applies vesa specified constraints if the monitor has provided them, + ///< COMPATIBLE profile if not + CTL_INTEL_ARC_SYNC_PROFILE_CUSTOM = 7, ///< Unlocks controls to set a custom Intel Arc Sync profile + CTL_INTEL_ARC_SYNC_PROFILE_MAX + +} ctl_intel_arc_sync_profile_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync Profile Params +typedef struct _ctl_intel_arc_sync_profile_params_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_intel_arc_sync_profile_t IntelArcSyncProfile; ///< [in,out] Intel Arc Sync profile used by driver. Refer + ///< ::ctl_intel_arc_sync_profile_t + float MaxRefreshRateInHz; ///< [in,out] Maximum refresh rate utilized by the driver + float MinRefreshRateInHz; ///< [in,out] Minimum refresh rate utilized by the driver + uint32_t MaxFrameTimeIncreaseInUs; ///< [in,out] Maximum frame time increase (in micro seconds) imposed by the + ///< driver + uint32_t MaxFrameTimeDecreaseInUs; ///< [in,out] Maximum frame time decrease (in micro seconds) imposed by the + ///< driver + +} ctl_intel_arc_sync_profile_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Intel Arc Sync profile +/// +/// @details +/// - Returns Intel Arc Sync profile for selected monitor +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncProfileParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetIntelArcSyncProfile( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_profile_params_t* pIntelArcSyncProfileParams ///< [in,out][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Intel Arc Sync profile +/// +/// @details +/// - Sets Intel Arc Sync profile for selected monitor. In a mux situation, +/// this API should be called for all display IDs associated with a +/// physical display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncProfileParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetIntelArcSyncProfile( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_profile_params_t* pIntelArcSyncProfileParams ///< [in][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID Management operation type +typedef enum _ctl_edid_management_optype_t +{ + CTL_EDID_MANAGEMENT_OPTYPE_READ_EDID = 1, ///< This operation type is to read an output's EDID. Set edid_type input + ///< arg to read MONITOR EDID or previously OVERRIDDEN EDID or CURRENT + ///< active EDID. Read EDID is a 2 pass call. First call with size = 0, + ///< pEdidBuf = nullptr to get the size, then call with allocated buffer to + ///< get the EDID data. READ operation is applicable for any normal, edid + ///< locked or edid overridden display output device. + CTL_EDID_MANAGEMENT_OPTYPE_LOCK_EDID = 2, ///< To make an output always connected with OVERRIDE or MONITOR EDID + ///< across reboots. When output isn't connected call with OVERRIDE EDID; + ///< when connected, either set OVERRIDE and provide pEdidBuf or set + ///< MONITOR and driver will use monitor's EDID. There is no change to EDID + ///< stored in Monitor. Cannot be called when override is active. Any OS + ///< EDID override will take precedence over IGCL override. + CTL_EDID_MANAGEMENT_OPTYPE_UNLOCK_EDID = 3, ///< To undo lock EDID operation, i.e. it makes output as detached in + ///< response to unplug. This operation removes past supplied EDID; output + ///< status is reported to OS as it is; output restores back to monitor's + ///< EDID when it is connected + CTL_EDID_MANAGEMENT_OPTYPE_OVERRIDE_EDID = 4, ///< To replace an output's EDID with supplied one (pEdidBuf) only when + ///< physical display is connected. There is no change to EDID stored in + ///< Monitor. Cannot apply this operation on locked output. When no output + ///< device attached, the supplied EDID will be persisted in driver for + ///< future use. Any OS EDID override will take precedence over IGCL + ///< override. + CTL_EDID_MANAGEMENT_OPTYPE_UNDO_OVERRIDE_EDID = 5, ///< To undo override EDID operation, that is remove previously overridden + ///< EDID on an output. Output restores back to monitor's EDID when it is + ///< connected + CTL_EDID_MANAGEMENT_OPTYPE_MAX + +} ctl_edid_management_optype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID type. Used in LOCK_EDID and READ_EDID calls. +typedef enum _ctl_edid_type_t +{ + CTL_EDID_TYPE_CURRENT = 1, ///< [in] Used to return currently active EDID in READ_EDID call. + CTL_EDID_TYPE_OVERRIDE = 2, ///< [in] Is it user supplied EDID. Used in LOCK_EDID call with Supplied + ///< EDID or in READ_EDID to get Supplied EDID. + CTL_EDID_TYPE_MONITOR = 3, ///< [in] Is it Monitor's EDID. Used in LOCK_EDID and READ_EDID calls. + CTL_EDID_TYPE_MAX + +} ctl_edid_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Edid management operation Out Flags +typedef uint32_t ctl_edid_management_out_flags_t; +typedef enum _ctl_edid_management_out_flag_t +{ + CTL_EDID_MANAGEMENT_OUT_FLAG_OS_CONN_NOTIFICATION = CTL_BIT(0), ///< [out] If OS was notified about a connection change. App will need to + ///< wait for the OS action to complete. + CTL_EDID_MANAGEMENT_OUT_FLAG_SUPPLIED_EDID = CTL_BIT(1),///< [out] Is it previously supplied EDID, set for READ_EDID(CURRENT). + CTL_EDID_MANAGEMENT_OUT_FLAG_MONITOR_EDID = CTL_BIT(2), ///< [out] Is it Monitor's EDID, set for READ_EDID(CURRENT). + CTL_EDID_MANAGEMENT_OUT_FLAG_DISPLAY_CONNECTED = CTL_BIT(3),///< [out] Is Monitor physically connected + CTL_EDID_MANAGEMENT_OUT_FLAG_MAX = 0x80000000 + +} ctl_edid_management_out_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID management +typedef struct _ctl_edid_management_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_edid_management_optype_t OpType; ///< [in] EDID managmeent operation type + ctl_edid_type_t EdidType; ///< [in] EDID Type, Monitor or Supplied + uint32_t EdidSize; ///< [in,out] EDID Size, should be 0 for querying the size of EDID, should + ///< be previously returned size to read EDID. if buffer isn't big enough + ///< to fit EDID, returns size of EDID bytes. + uint8_t* pEdidBuf; ///< [in,out] buffer holding EDID data + ctl_edid_management_out_flags_t OutFlags; ///< [out] Output flags to inform about status of EDID management + ///< operations + +} ctl_edid_management_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID Management allows managing an output's EDID or Plugged Status. +/// +/// @details +/// - To manage output's EDID or Display ID. Supports native DP SST and HDMI +/// Display types. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pEdidManagementArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ATTACHED - "Error for Output Device not attached" +/// - ::CTL_RESULT_ERROR_OUT_OF_DEVICE_MEMORY - "Insufficient device memory to satisfy call" +/// - ::CTL_RESULT_ERROR_DATA_NOT_FOUND - "Requested EDID data not present." +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEdidManagement( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_edid_management_args_t* pEdidManagementArgs ///< [in,out] EDID management arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Custom mode operation types +typedef enum _ctl_custom_mode_operation_types_t +{ + CTL_CUSTOM_MODE_OPERATION_TYPES_GET_CUSTOM_SOURCE_MODES = 0,///< Get details of all previous applied custom modes if any. + CTL_CUSTOM_MODE_OPERATION_TYPES_ADD_CUSTOM_SOURCE_MODE = 1, ///< Add a new mode. Allows only single mode adition at a time. + CTL_CUSTOM_MODE_OPERATION_TYPES_REMOVE_CUSTOM_SOURCE_MODES = 2, ///< Remove previously added custom mode. Allows single or multiple mode + ///< removal at a time. + CTL_CUSTOM_MODE_OPERATION_TYPES_MAX + +} ctl_custom_mode_operation_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom Mode +typedef struct _ctl_get_set_custom_mode_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_custom_mode_operation_types_t CustomModeOpType; ///< [in] Custom mode operation type + uint32_t NumOfModes; ///< [in,out] Number of Custom Src Modes to be added/removed/Read. + ctl_custom_src_mode_t* pCustomSrcModeList; ///< [in,out] Custom mode source list which holds source modes to be + ///< added/removed/Read. + +} ctl_get_set_custom_mode_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom Mode +typedef struct _ctl_custom_src_mode_t +{ + uint32_t SourceX; ///< [in,out] CustomMode Source X Size + uint32_t SourceY; ///< [in,out] CustomMode Source Y Size + +} ctl_custom_src_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom mode. +/// +/// @details +/// - To get or set custom mode. +/// - Add custom source mode operation supports only single mode additon at +/// a time. +/// - Remove custom source mode operation supports single or multiple mode +/// removal at a time. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCustomModeArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_STANDARD_CUSTOM_MODE_EXISTS - "Standard custom mode exists" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_NON_CUSTOM_MATCHING_MODE_EXISTS - "Non custom matching mode exists" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_INSUFFICIENT_MEMORY - "Custom mode insufficent memory" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetCustomMode( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_get_set_custom_mode_args_t* pCustomModeArgs ///< [in,out] Custom mode arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display operation type +typedef enum _ctl_combined_display_optype_t +{ + CTL_COMBINED_DISPLAY_OPTYPE_IS_SUPPORTED_CONFIG = 1,///< To check whether given outputs can form a combined display, no changes + ///< are applied + CTL_COMBINED_DISPLAY_OPTYPE_ENABLE = 2, ///< To setup and enable a combined display + CTL_COMBINED_DISPLAY_OPTYPE_DISABLE = 3, ///< To disable combined display + CTL_COMBINED_DISPLAY_OPTYPE_QUERY_CONFIG = 4, ///< To query combined display configuration + CTL_COMBINED_DISPLAY_OPTYPE_MAX + +} ctl_combined_display_optype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display's child display target mode +typedef struct _ctl_child_display_target_mode_t +{ + uint32_t Width; ///< [in,out] Width + uint32_t Height; ///< [in,out] Height + float RefreshRate; ///< [in,out] Refresh Rate + uint32_t ReservedFields[4]; ///< [out] Reserved field of 16 bytes + +} ctl_child_display_target_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display's child display information +typedef struct _ctl_combined_display_child_info_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in,out] Display output handle under combined display configuration + ctl_rect_t FbSrc; ///< [in,out] FrameBuffer source's RECT within Combined Display respective + ctl_rect_t FbPos; ///< [in,out] FrameBuffer target's RECT within output size + ctl_display_orientation_t DisplayOrientation; ///< [in,out] 0/180 Degree Display orientation (rotation) + ctl_child_display_target_mode_t TargetMode; ///< [in,out] Desired target mode (width, height, refresh) + +} ctl_combined_display_child_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display arguments +typedef struct _ctl_combined_display_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_combined_display_optype_t OpType; ///< [in] Combined display operation type + bool IsSupported; ///< [out] Returns yes/no in response to IS_SUPPORTED_CONFIG command + uint8_t NumOutputs; ///< [in,out] Number of outputs part of desired combined display + ///< configuration + uint32_t CombinedDesktopWidth; ///< [in,out] Width of desired combined display configuration + uint32_t CombinedDesktopHeight; ///< [in,out] Height of desired combined display configuration + ctl_combined_display_child_info_t* pChildInfo; ///< [in,out] List of child display information respective to each output + ctl_display_output_handle_t hCombinedDisplayOutput; ///< [in,out] Handle to combined display output + +} ctl_combined_display_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Combined Display +/// +/// @details +/// - To get or set combined display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCombinedDisplayArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_FEATURE_NOT_SUPPORTED - "Combined Display feature is not supported in this platform" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetCombinedDisplay( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] Handle to control device adapter + ctl_combined_display_args_t* pCombinedDisplayArgs ///< [in,out] Setup and get combined display arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Operations +typedef enum _ctl_genlock_operation_t +{ + CTL_GENLOCK_OPERATION_GET_TIMING_DETAILS = 0, ///< Get details of GENLOCK support and timing information + CTL_GENLOCK_OPERATION_VALIDATE = 1, ///< Driver to verify that the topology is Genlock capable + CTL_GENLOCK_OPERATION_ENABLE = 2, ///< Enable GENLOCK + CTL_GENLOCK_OPERATION_DISABLE = 3, ///< Disable GENLOCK + CTL_GENLOCK_OPERATION_GET_TOPOLOGY = 4, ///< Get details of the current Genlock topology that is applied + CTL_GENLOCK_OPERATION_MAX + +} ctl_genlock_operation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Info +typedef struct _ctl_genlock_display_info_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in,out] Display output handle under Genlock topology + bool IsPrimary; ///< [in,out] Genlock Primary + +} ctl_genlock_display_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Genlock Target Mode List +typedef struct _ctl_genlock_target_mode_list_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in] Display output handle for whom target mode list is required + uint32_t NumModes; ///< [in,out] Number of supported Modes that is returned from a driver + ctl_display_timing_t* pTargetModes; ///< [out] Display Genlock operation and information + +} ctl_genlock_target_mode_list_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Genlock Topology +typedef struct _ctl_genlock_topology_t +{ + uint8_t NumGenlockDisplays; ///< [in,out] Number of Genlock displays + bool IsPrimaryGenlockSystem; ///< [in,out] Primary Genlock system + ctl_display_timing_t CommonTargetMode; ///< [in] Common target mode + ctl_genlock_display_info_t* pGenlockDisplayInfo;///< [in,out] List of Genlock display info + ctl_genlock_target_mode_list_t* pGenlockModeList; ///< [out] List of Genlock target modes + +} ctl_genlock_topology_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Arg type +typedef struct _ctl_genlock_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_genlock_operation_t Operation; ///< [in] Display Genlock Operation + ctl_genlock_topology_t GenlockTopology; ///< [in,out] Display Genlock array of topology structures + bool IsGenlockEnabled; ///< [out] Whether the feature is currently enabled or not + bool IsGenlockPossible; ///< [out] Indicates if Genlock can be enabled/disabled with the given + ///< topology + +} ctl_genlock_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Display Genlock +/// +/// @details +/// - To get or set Display Genlock. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == hDeviceAdapter` +/// + `nullptr == pGenlockArgs` +/// + `nullptr == hFailureDeviceAdapter` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid topology structure size" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetDisplayGenlock( + ctl_device_adapter_handle_t* hDeviceAdapter, ///< [in][release] Handle to control device adapter + ctl_genlock_args_t** pGenlockArgs, ///< [in,out] Display Genlock operation and information + uint32_t AdapterCount, ///< [in] Number of device adapters + ctl_device_adapter_handle_t* hFailureDeviceAdapter ///< [out] Handle to address the failure device adapter in an error case + ); + + +#if !defined(__GNUC__) +#pragma endregion // display +#endif +// Intel 'ctlApi' for Device Adapter - Engine groups +#if !defined(__GNUC__) +#pragma region engine +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Accelerator engine groups +typedef enum _ctl_engine_group_t +{ + CTL_ENGINE_GROUP_GT = 0, ///< Access information about all engines combined. + CTL_ENGINE_GROUP_RENDER = 1, ///< Access information about all render and compute engines combined. + CTL_ENGINE_GROUP_MEDIA = 2, ///< Access information about all media engines combined. + CTL_ENGINE_GROUP_MAX + +} ctl_engine_group_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Engine group properties +typedef struct _ctl_engine_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_engine_group_t type; ///< [out] The engine group + +} ctl_engine_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Engine activity counters +/// +/// @details +/// - Percent utilization is calculated by taking two snapshots (s1, s2) and +/// using the equation: %util = (s2.activeTime - s1.activeTime) / +/// (s2.timestamp - s1.timestamp) +typedef struct _ctl_engine_stats_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t activeTime; ///< [out] Monotonic counter for time in microseconds that this resource is + ///< actively running workloads. + uint64_t timestamp; ///< [out] Monotonic timestamp counter in microseconds when activeTime + ///< counter was sampled. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_engine_stats_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of engine groups +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumEngineGroups( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_engine_handle_t* phEngine ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get engine group properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hEngine` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEngineGetProperties( + ctl_engine_handle_t hEngine, ///< [in] Handle for the component. + ctl_engine_properties_t* pProperties ///< [in,out] The properties for the specified engine group. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the activity stats for an engine group +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hEngine` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pStats` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEngineGetActivity( + ctl_engine_handle_t hEngine, ///< [in] Handle for the component. + ctl_engine_stats_t* pStats ///< [in,out] Will contain a snapshot of the engine group activity + ///< counters. + ); + + +#if !defined(__GNUC__) +#pragma endregion // engine +#endif +// Intel 'ctlApi' for Device Adapter- Fan management +#if !defined(__GNUC__) +#pragma region fan +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan resource speed mode +typedef enum _ctl_fan_speed_mode_t +{ + CTL_FAN_SPEED_MODE_DEFAULT = 0, ///< The fan speed is operating using the hardware default settings + CTL_FAN_SPEED_MODE_FIXED = 1, ///< The fan speed is currently set to a fixed value + CTL_FAN_SPEED_MODE_TABLE = 2, ///< The fan speed is currently controlled dynamically by hardware based on + ///< a temp/speed table + CTL_FAN_SPEED_MODE_MAX + +} ctl_fan_speed_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed units +typedef enum _ctl_fan_speed_units_t +{ + CTL_FAN_SPEED_UNITS_RPM = 0, ///< The fan speed is in units of revolutions per minute (rpm) + CTL_FAN_SPEED_UNITS_PERCENT = 1, ///< The fan speed is a percentage of the maximum speed of the fan + CTL_FAN_SPEED_UNITS_MAX + +} ctl_fan_speed_units_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed +typedef struct _ctl_fan_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t speed; ///< [in,out] The speed of the fan. On output, a value of -1 indicates that + ///< there is no fixed fan speed setting. + ctl_fan_speed_units_t units; ///< [in,out] The units that the fan speed is expressed in. On output, if + ///< fan speed is -1 then units should be ignored. + +} ctl_fan_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan temperature/speed pair +typedef struct _ctl_fan_temp_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t temperature; ///< [in,out] Temperature in degrees Celsius. + ctl_fan_speed_t speed; ///< [in,out] The speed of the fan + +} ctl_fan_temp_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_FAN_TEMP_SPEED_PAIR_COUNT +/// @brief Maximum number of fan temperature/speed pairs in the fan speed table. +#define CTL_FAN_TEMP_SPEED_PAIR_COUNT 32 +#endif // CTL_FAN_TEMP_SPEED_PAIR_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed table +typedef struct _ctl_fan_speed_table_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t numPoints; ///< [in,out] The number of valid points in the fan speed table. 0 means + ///< that there is no fan speed table configured. -1 means that a fan speed + ///< table is not supported by the hardware. + ctl_fan_temp_speed_t table[CTL_FAN_TEMP_SPEED_PAIR_COUNT]; ///< [in,out] Array of temperature/fan speed pairs. The table is ordered + ///< based on temperature from lowest to highest. + +} ctl_fan_speed_table_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan properties +typedef struct _ctl_fan_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool canControl; ///< [out] Indicates if software can control the fan speed assuming the + ///< user has permissions + uint32_t supportedModes; ///< [out] Bitfield of supported fan configuration modes + ///< (1<<::ctl_fan_speed_mode_t) + uint32_t supportedUnits; ///< [out] Bitfield of supported fan speed units + ///< (1<<::ctl_fan_speed_units_t) + int32_t maxRPM; ///< [out] The maximum RPM of the fan. A value of -1 means that this + ///< property is unknown. + int32_t maxPoints; ///< [out] The maximum number of points in the fan temp/speed table. A + ///< value of -1 means that this fan doesn't support providing a temp/speed + ///< table. + +} ctl_fan_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan configuration +typedef struct _ctl_fan_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_fan_speed_mode_t mode; ///< [in,out] The fan speed mode (fixed, temp-speed table) + ctl_fan_speed_t speedFixed; ///< [in,out] The current fixed fan speed setting + ctl_fan_speed_table_t speedTable; ///< [out] A table containing temperature/speed pairs + +} ctl_fan_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of fans +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumFans( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to the adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_fan_handle_t* phFan ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get fan properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetProperties( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_properties_t* pProperties ///< [in,out] Will contain the properties of the fan. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get fan configurations and the current fan speed mode (default, fixed, +/// temp-speed table) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pConfig` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetConfig( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_config_t* pConfig ///< [in,out] Will contain the current configuration of the fan. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to run with hardware factory settings (set mode to +/// ::CTL_FAN_SPEED_MODE_DEFAULT) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetDefaultMode( + ctl_fan_handle_t hFan ///< [in] Handle for the component. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to rotate at a fixed speed (set mode to +/// ::CTL_FAN_SPEED_MODE_FIXED) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == speed` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + Fixing the fan speed not supported by the hardware or the fan speed units are not supported. See ::ctl_fan_properties_t.supportedModes and ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetFixedSpeedMode( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + const ctl_fan_speed_t* speed ///< [in] The fixed fan speed setting + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to adjust speed based on a temperature/speed table +/// (set mode to ::CTL_FAN_SPEED_MODE_TABLE) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == speedTable` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT +/// + The temperature/speed pairs in the array are not sorted on temperature from lowest to highest. +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + Fan speed table not supported by the hardware or the fan speed units are not supported. See ::ctl_fan_properties_t.supportedModes and ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetSpeedTableMode( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + const ctl_fan_speed_table_t* speedTable ///< [in] A table containing temperature/speed pairs. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current state of a fan - current mode and speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_ENUMERATION +/// + `::CTL_FAN_SPEED_UNITS_PERCENT < units` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSpeed` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + The requested fan speed units are not supported. See ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetState( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_speed_units_t units, ///< [in] The units in which the fan speed should be returned. + int32_t* pSpeed ///< [in,out] Will contain the current speed of the fan in the units + ///< requested. A value of -1 indicates that the fan speed cannot be + ///< measured. + ); + + +#if !defined(__GNUC__) +#pragma endregion // fan +#endif +// Intel 'ctlApi' for Device Adapter - Frequency domains +#if !defined(__GNUC__) +#pragma region frequency +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency domains. +typedef enum _ctl_freq_domain_t +{ + CTL_FREQ_DOMAIN_GPU = 0, ///< GPU Core Domain. + CTL_FREQ_DOMAIN_MEMORY = 1, ///< Local Memory Domain. + CTL_FREQ_DOMAIN_MAX + +} ctl_freq_domain_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency properties +typedef struct _ctl_freq_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_freq_domain_t type; ///< [out] The hardware block that this frequency domain controls (GPU, + ///< memory, ...) + bool canControl; ///< [out] Indicates if software can control the frequency of this domain + ///< assuming the user has permissions + double min; ///< [out] The minimum hardware clock frequency in units of MHz. + double max; ///< [out] The maximum non-overclock hardware clock frequency in units of + ///< MHz. + +} ctl_freq_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency range between which the hardware can operate. The limits can +/// be above or below the hardware limits - the hardware will clamp +/// appropriately. +typedef struct _ctl_freq_range_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double min; ///< [in,out] The min frequency in MHz below which hardware frequency + ///< management will not request frequencies. On input, setting to 0 will + ///< permit the frequency to go down to the hardware minimum. On output, a + ///< negative value indicates that no external minimum frequency limit is + ///< in effect. + double max; ///< [in,out] The max frequency in MHz above which hardware frequency + ///< management will not request frequencies. On input, setting to 0 or a + ///< very big number will permit the frequency to go all the way up to the + ///< hardware maximum. On output, a negative number indicates that no + ///< external maximum frequency limit is in effect. + +} ctl_freq_range_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency throttle reasons +typedef uint32_t ctl_freq_throttle_reason_flags_t; +typedef enum _ctl_freq_throttle_reason_flag_t +{ + CTL_FREQ_THROTTLE_REASON_FLAG_AVE_PWR_CAP = CTL_BIT(0), ///< frequency throttled due to average power excursion (PL1) + CTL_FREQ_THROTTLE_REASON_FLAG_BURST_PWR_CAP = CTL_BIT(1), ///< frequency throttled due to burst power excursion (PL2) + CTL_FREQ_THROTTLE_REASON_FLAG_CURRENT_LIMIT = CTL_BIT(2), ///< frequency throttled due to current excursion (PL4) + CTL_FREQ_THROTTLE_REASON_FLAG_THERMAL_LIMIT = CTL_BIT(3), ///< frequency throttled due to thermal excursion (T > TjMax) + CTL_FREQ_THROTTLE_REASON_FLAG_PSU_ALERT = CTL_BIT(4), ///< frequency throttled due to power supply assertion + CTL_FREQ_THROTTLE_REASON_FLAG_SW_RANGE = CTL_BIT(5),///< frequency throttled due to software supplied frequency range + CTL_FREQ_THROTTLE_REASON_FLAG_HW_RANGE = CTL_BIT(6),///< frequency throttled due to a sub block that has a lower frequency + ///< range when it receives clocks + CTL_FREQ_THROTTLE_REASON_FLAG_MAX = 0x80000000 + +} ctl_freq_throttle_reason_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency state +typedef struct _ctl_freq_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double currentVoltage; ///< [out] Current voltage in Volts. A negative value indicates that this + ///< property is not known. + double request; ///< [out] The current frequency request in MHz. A negative value indicates + ///< that this property is not known. + double tdp; ///< [out] The maximum frequency in MHz supported under the current TDP + ///< conditions. This fluctuates dynamically based on the power and thermal + ///< limits of the part. A negative value indicates that this property is + ///< not known. + double efficient; ///< [out] The efficient minimum frequency in MHz. A negative value + ///< indicates that this property is not known. + double actual; ///< [out] The resolved frequency in MHz. A negative value indicates that + ///< this property is not known. + ctl_freq_throttle_reason_flags_t throttleReasons; ///< [out] The reasons that the frequency is being limited by the hardware. + ///< Returns 0 (frequency not throttled) or a combination of ::ctl_freq_throttle_reason_flag_t. + +} ctl_freq_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency throttle time snapshot +/// +/// @details +/// - Percent time throttled is calculated by taking two snapshots (s1, s2) +/// and using the equation: %throttled = (s2.throttleTime - +/// s1.throttleTime) / (s2.timestamp - s1.timestamp) +typedef struct _ctl_freq_throttle_time_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t throttleTime; ///< [out] The monotonic counter of time in microseconds that the frequency + ///< has been limited by the hardware. + uint64_t timestamp; ///< [out] Microsecond timestamp when throttleTime was captured. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_freq_throttle_time_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of frequency domains +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumFrequencyDomains( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_freq_handle_t* phFrequency ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get frequency properties - available frequencies +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetProperties( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_properties_t* pProperties ///< [in,out] The frequency properties for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get available non-overclocked hardware clock frequencies for the +/// frequency domain +/// +/// @details +/// - The list of available frequencies is returned in order of slowest to +/// fastest. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetAvailableClocks( + ctl_freq_handle_t hFrequency, ///< [in] Device handle of the device. + uint32_t* pCount, ///< [in,out] pointer to the number of frequencies. + ///< if count is zero, then the driver shall update the value with the + ///< total number of frequencies that are available. + ///< if count is greater than the number of frequencies that are available, + ///< then the driver shall update the value with the correct number of frequencies. + double* phFrequency ///< [in,out][optional][range(0, *pCount)] array of frequencies in units of + ///< MHz and sorted from slowest to fastest. + ///< if count is less than the number of frequencies that are available, + ///< then the driver shall only retrieve that number of frequencies. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current frequency limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLimits` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetRange( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_range_t* pLimits ///< [in,out] The range between which the hardware can operate for the + ///< specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set frequency range between which the hardware can operate. +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLimits` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencySetRange( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + const ctl_freq_range_t* pLimits ///< [in] The limits between which the hardware can operate for the + ///< specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current frequency state - frequency request, actual frequency, TDP +/// limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetState( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_state_t* pState ///< [in,out] Frequency state for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get frequency throttle time +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pThrottleTime` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetThrottleTime( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_throttle_time_t* pThrottleTime ///< [in,out] Will contain a snapshot of the throttle time counters for the + ///< specified domain. + ); + + +#if !defined(__GNUC__) +#pragma endregion // frequency +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region media +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature type +typedef enum _ctl_video_processing_feature_t +{ + CTL_VIDEO_PROCESSING_FEATURE_FILM_MODE_DETECTION = 0, ///< Film mode detection. Contains CTL_PROPERTY_VALUE_TYPE_BOOL ValueType. + CTL_VIDEO_PROCESSING_FEATURE_NOISE_REDUCTION = 1, ///< Noise reduction. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field + ///< using struct ::ctl_video_processing_noise_reduction_t. + CTL_VIDEO_PROCESSING_FEATURE_SHARPNESS = 2, ///< Sharpness. Contains CTL_PROPERTY_VALUE_TYPE_UINT32 ValueType. + CTL_VIDEO_PROCESSING_FEATURE_ADAPTIVE_CONTRAST_ENHANCEMENT = 3, ///< Adaptive contrast enhancement. Contains + ///< CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using struct + ///< ::ctl_video_processing_adaptive_contrast_enhancement_t. + CTL_VIDEO_PROCESSING_FEATURE_SUPER_RESOLUTION = 4, ///< Super resolution. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM ValueType + ///< using ::ctl_video_processing_super_resolution_t. By defaut, Super + ///< resolution is not active, need application to activate it, please + ///< contact Intel for super resolution activation. + CTL_VIDEO_PROCESSING_FEATURE_STANDARD_COLOR_CORRECTION = 5, ///< Standard color correction. Controls Hue, Saturation, Contrast, + ///< Brightness. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using + ///< struct ::ctl_video_processing_standard_color_correction_t. + CTL_VIDEO_PROCESSING_FEATURE_TOTAL_COLOR_CORRECTION = 6,///< Total color correction. Controls Red, Green, Blue, Yellow, Cyan, + ///< Magenta. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using + ///< struct ::ctl_video_processing_total_color_correction_t. + CTL_VIDEO_PROCESSING_FEATURE_SKIN_TONE_ENHANCEMENT = 7, ///< Skin tone enhancement. Contains CTL_PROPERTY_VALUE_TYPE_UINT32 + ///< ValueType. + CTL_VIDEO_PROCESSING_FEATURE_MAX + +} ctl_video_processing_feature_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super resolution values possible +typedef uint32_t ctl_video_processing_super_resolution_flags_t; +typedef enum _ctl_video_processing_super_resolution_flag_t +{ + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_DISABLE = CTL_BIT(0),///< Disable + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_DEFAULT_SCENARIO_MODE = CTL_BIT(1), ///< Enable with default super resolution mode + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_CONFERENCE_SCENARIO_MODE = CTL_BIT(2),///< Super resolution mode targeted at video conference content + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_CAMERA_SCENARIO_MODE = CTL_BIT(3),///< Super resolution mode targeted at camera capture content (e.g. + ///< security camera) + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_MAX = 0x80000000 + +} ctl_video_processing_super_resolution_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super Resolution feature details structure to be used with +/// SUPER_RESOLUTION +typedef struct _ctl_video_processing_super_resolution_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_super_resolution_flags_t super_resolution_flag;///< [in,out] SUPER_RESOLUTION flag + ctl_property_info_uint_t super_resolution_range_in_width; ///< [in,out] The range of input width information(min, max, default and + ///< step size)which super resolution is capable of supporting. + ctl_property_info_uint_t super_resolution_range_in_height; ///< [in,out] The range of input height information(min, max, default and + ///< step size)which super resolution is capable of supporting. + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_super_resolution_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super Resolution Get/Set structure to be used with SUPER_RESOLUTION +typedef struct _ctl_video_processing_super_resolution_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_super_resolution_flags_t super_resolution_flag;///< [in,out] SUPER_RESOLUTION flag + bool super_resolution_max_in_enabled; ///< [in,out] The enabling of maximum input width and height limition. If + ///< enabled, super resolution will always take effect if the input + ///< resolution is smaller than the below specified max resolution; + ///< otherwise, super_resolution_max_in_width and + ///< super_resolution_max_in_height will be ignored + uint32_t super_resolution_max_in_width; ///< [in,out] The maximum input width limition value setting which super + ///< resolution will be allowed to enabled. + uint32_t super_resolution_max_in_height; ///< [in,out] The maximum input height limiation value setting which super + ///< resolution will be allowed to enabled. + bool super_resolution_reboot_reset; ///< [in,out] Resetting of super resolution after rebooting. + uint32_t ReservedFields[15]; ///< [out] Reserved field of 60 bytes + char ReservedBytes[3]; ///< [out] Reserved field of 3 bytes + +} ctl_video_processing_super_resolution_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Noise Reduction feature details structure to be used with +/// NOISE_REDUCTION +typedef struct _ctl_video_processing_noise_reduction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_info_uint_t noise_reduction; ///< [in,out] Noise reduction min, max, default and step size information + bool noise_reduction_auto_detect_supported; ///< [in,out] Noise reduction Auto Detect is supported; only valid if + ///< NOISE_REDUCTION is enabled. If enabled, noise reduction level is + ///< automatically determined and set value is not used. + ctl_property_info_boolean_t noise_reduction_auto_detect;///< [in,out] Noise reduction auto detect default information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_noise_reduction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Noise Reduction Get/Set structure to be used with NOISE_REDUCTION +typedef struct _ctl_video_processing_noise_reduction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_uint_t noise_reduction; ///< [in,out] Noise reduction enable and value setting + ctl_property_boolean_t noise_reduction_auto_detect; ///< [in,out] Noise reduction auto detect setting + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_noise_reduction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Contrast Enhancement feature details structure to be used +/// with ADAPTIVE_CONTRAST_ENHANCEMENT +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_info_uint_t adaptive_contrast_enhancement; ///< [in,out] Adaptive Contrast Enhancement min, max, default and step size + ///< information + bool adaptive_contrast_enhancement_coexistence_supported; ///< [in,out] Adaptive contrast enhancement coexistance is supported; only + ///< valid if ADAPTIVE_CONTRAST_ENHANCEMENT is enabled. If enabled, Video + ///< adaptive contrast ehancement will be allowed to be enabled and coexist + ///< with Display adaptive contrast ehancement feature. + ctl_property_info_boolean_t adaptive_contrast_enhancement_coexistence; ///< [in,out] Adaptive contrast enhancement coexistence default information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_adaptive_contrast_enhancement_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Contrast Enhancement Get/Set structure to be used with +/// ADAPTIVE_CONTRAST_ENHANCEMENT +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_uint_t adaptive_contrast_enhancement; ///< [in,out] Adaptive Contrast Enhancement enable and value setting + ctl_property_boolean_t adaptive_contrast_enhancement_coexistence; ///< [in,out] Adaptive contrast enhancement coexistance setting + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_adaptive_contrast_enhancement_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Standard Color Correction feature details structure to be used with +/// STANDARD_COLOR_CORRECTION +typedef struct _ctl_video_processing_standard_color_correction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool standard_color_correction_default_enable; ///< [in,out] STANDARD_COLOR_CORRECTION default enable setting. This + ///< global settings controls all of Hue, Saturation, Contrast, Brightness + ///< enabling. Individual Enable controls shall be ignored. + ctl_property_info_float_t brightness; ///< [in,out] Brightness min, max, default and step size information + ctl_property_info_float_t contrast; ///< [in,out] Contrast min, max, default and step size information + ctl_property_info_float_t hue; ///< [in,out] Hue min, max, default and step size information + ctl_property_info_float_t saturation; ///< [in,out] Saturation min, max, default and step size information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_standard_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Standard Color Correction Get/Set structure to be used with +/// STANDARD_COLOR_CORRECTION +typedef struct _ctl_video_processing_standard_color_correction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool standard_color_correction_enable; ///< [in,out] STANDARD_COLOR_CORRECTION enable setting. This global + ///< setting controls all of Hue, Saturation, Contrast, Brightness + ///< enabling. + float brightness; ///< [in,out] Brightness value + float contrast; ///< [in,out] Contrast value + float hue; ///< [in,out] Hue value + float saturation; ///< [in,out] Saturation value + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_standard_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Total Color Correction Get/Set structure to be used with +/// TOTAL_COLOR_CORRECTION +typedef struct _ctl_video_processing_total_color_correction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool total_color_correction_default_enable; ///< [in,out] TOTAL_COLOR_CORRECTION enable setting. This global setting + ///< controls all of Red, Green, Blue, Yellow, Cyan, Magenta enabling. + ///< Individual Enable controls shall be ignored. + ctl_property_info_uint_t red; ///< [in,out] Red min, max, default and step size information + ctl_property_info_uint_t green; ///< [in,out] Green min, max, default and step size information + ctl_property_info_uint_t blue; ///< [in,out] Blue min, max, default and step size information + ctl_property_info_uint_t yellow; ///< [in,out] Yellow min, max, default and step size information + ctl_property_info_uint_t cyan; ///< [in,out] Cyan min, max, default and step size information + ctl_property_info_uint_t magenta; ///< [in,out] Magenta min, max, default and step size information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_total_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Total Color Correction Get/Set structure to be used with +/// TOTAL_COLOR_CORRECTION +typedef struct _ctl_video_processing_total_color_correction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool total_color_correction_enable; ///< [in,out] TOTAL_COLOR_CORRECTION enable setting. This global setting + ///< controls all of Red, Green, Blue, Yellow, Cyan, Magenta enabling. + uint32_t red; ///< [in,out] Red value + uint32_t green; ///< [in,out] Green value + uint32_t blue; ///< [in,out] Blue value + uint32_t yellow; ///< [in,out] Yellow value + uint32_t cyan; ///< [in,out] Cyan value + uint32_t magenta; ///< [in,out] Magenta value + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_total_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing feature details which will have range supported and +/// default values +typedef struct _ctl_video_processing_feature_details_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_feature_t FeatureType; ///< [out] Video processing feature type + ctl_property_value_type_t ValueType; ///< [out] Type of value + ctl_property_info_t Value; ///< [out] Union of various type of values for Video Processing features. + ///< For enum types this can be noise reduction, color control etc. This + ///< member is valid iff ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Features that use CustomType, + ///< after the first query for all of the supported features the user needs + ///< to allocate this buffer and then query again just this specific + ///< feature for the structure to be filled in. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM. + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing features which are controllable +typedef struct _ctl_video_processing_feature_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSupportedFeatures; ///< [in,out] Number of elements in supported features array + ctl_video_processing_feature_details_t* pFeatureDetails;///< [in,out] Array of supported features and their details + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing feature for get/set +typedef struct _ctl_video_processing_feature_getset_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_feature_t FeatureType; ///< [in] Features interested in + char* ApplicationName; ///< [in] Application name for which the property type is applicable. If + ///< this is an empty string then this will get/set global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path. [This is not currently + ///< supported and should be an empty string.] + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + bool bSet; ///< [in] Set this if it's a set call + ctl_property_value_type_t ValueType; ///< [in] Type of value. Caller has to ensure it provides the right value + ///< type which decides how one read the union structure below + ctl_property_t Value; ///< [in,out] Union of various type of values for Video Processing + ///< features. For enum types this can be noise reduction, color control + ///< etc. This member is valid iff ValueType is not + ///< CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. For a feature requiring custom struct, + ///< caller will know of it upfront the struct to use based on the feautre + ///< and can provide the right size info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Video Processing capabilities +/// +/// @details +/// - The application gets Video Processing properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeatureCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedVideoProcessingCapabilities( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_video_processing_feature_caps_t* pFeatureCaps ///< [in,out][release] Video Processing properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Video Processing feature details +/// +/// @details +/// - Video Processing feature details +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeature` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetVideoProcessingFeature( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_video_processing_feature_getset_t* pFeature ///< [in][release] Video Processing feature get/set parameter + ); + + +#if !defined(__GNUC__) +#pragma endregion // media +#endif +// Intel 'ctlApi' for Device Adapter - Memory management +#if !defined(__GNUC__) +#pragma region memory +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory module types +typedef enum _ctl_mem_type_t +{ + CTL_MEM_TYPE_HBM = 0, ///< HBM memory + CTL_MEM_TYPE_DDR = 1, ///< DDR memory + CTL_MEM_TYPE_DDR3 = 2, ///< DDR3 memory + CTL_MEM_TYPE_DDR4 = 3, ///< DDR4 memory + CTL_MEM_TYPE_DDR5 = 4, ///< DDR5 memory + CTL_MEM_TYPE_LPDDR = 5, ///< LPDDR memory + CTL_MEM_TYPE_LPDDR3 = 6, ///< LPDDR3 memory + CTL_MEM_TYPE_LPDDR4 = 7, ///< LPDDR4 memory + CTL_MEM_TYPE_LPDDR5 = 8, ///< LPDDR5 memory + CTL_MEM_TYPE_GDDR4 = 9, ///< GDDR4 memory + CTL_MEM_TYPE_GDDR5 = 10, ///< GDDR5 memory + CTL_MEM_TYPE_GDDR5X = 11, ///< GDDR5X memory + CTL_MEM_TYPE_GDDR6 = 12, ///< GDDR6 memory + CTL_MEM_TYPE_GDDR6X = 13, ///< GDDR6X memory + CTL_MEM_TYPE_GDDR7 = 14, ///< GDDR7 memory + CTL_MEM_TYPE_UNKNOWN = 15, ///< UNKNOWN memory + CTL_MEM_TYPE_MAX + +} ctl_mem_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory module location +typedef enum _ctl_mem_loc_t +{ + CTL_MEM_LOC_SYSTEM = 0, ///< System memory + CTL_MEM_LOC_DEVICE = 1, ///< On board local device memory + CTL_MEM_LOC_MAX + +} ctl_mem_loc_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory properties +typedef struct _ctl_mem_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_mem_type_t type; ///< [out] The memory type + ctl_mem_loc_t location; ///< [out] Location of this memory (system, device) + uint64_t physicalSize; ///< [out] Physical memory size in bytes. A value of 0 indicates that this + ///< property is not known. However, a call to ::ctlMemoryGetState() will + ///< correctly return the total size of usable memory. + int32_t busWidth; ///< [out] Width of the memory bus. A value of -1 means that this property + ///< is unknown. + int32_t numChannels; ///< [out] The number of memory channels. A value of -1 means that this + ///< property is unknown. + +} ctl_mem_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory state - health, allocated +/// +/// @details +/// - Percent allocation is given by 100 * (size - free / size. +/// - Percent free is given by 100 * free / size. +typedef struct _ctl_mem_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t free; ///< [out] The free memory in bytes + uint64_t size; ///< [out] The total allocatable memory in bytes (can be less than + ///< ::ctl_mem_properties_t.physicalSize) + +} ctl_mem_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory bandwidth +/// +/// @details +/// - Percent bandwidth is calculated by taking two snapshots (s1, s2) and +/// using the equation: %bw = 10^6 * ((s2.readCounter - s1.readCounter) + +/// (s2.writeCounter - s1.writeCounter)) / (s2.maxBandwidth * +/// (s2.timestamp - s1.timestamp)) +typedef struct _ctl_mem_bandwidth_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t maxBandwidth; ///< [out] Current maximum bandwidth in units of bytes/sec + uint64_t timestamp; ///< [out] The timestamp (in microseconds) when these measurements were sampled. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + uint64_t readCounter; ///< [out] Total bytes read from memory. Supported only for Version > 0 + uint64_t writeCounter; ///< [out] Total bytes written to memory. Supported only for Version > 0 + +} ctl_mem_bandwidth_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of memory modules +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumMemoryModules( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_mem_handle_t* phMemory ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetProperties( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_properties_t* pProperties ///< [in,out] Will contain memory properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory state - health, allocated +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetState( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_state_t* pState ///< [in,out] Will contain the current health and allocated memory. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory bandwidth +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pBandwidth` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to query this telemetry. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetBandwidth( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_bandwidth_t* pBandwidth ///< [in,out] Will contain the current health, free memory, total memory + ///< size. + ); + + +#if !defined(__GNUC__) +#pragma endregion // memory +#endif +// Intel 'ctlApi' for Device Adapter - Overclock +#if !defined(__GNUC__) +#pragma region overclock +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Telemetry Item for each telemetry property +/// +/// @details +/// - If the supported field is true, then the entire structure has valid +/// information. +/// - The ::ctl_data_value_t is of type ::ctl_data_type_t and units +/// ::ctl_units_t +typedef struct _ctl_oc_telemetry_item_t +{ + bool bSupported; ///< [out] Indicates if the value is supported. + ctl_units_t units; ///< [out] Indicates the units of the value. + ctl_data_type_t type; ///< [out] Indicates the data type. + ctl_data_value_t value; ///< [out] The value of type ::ctl_data_type_t and units ::ctl_units_t. + +} ctl_oc_telemetry_item_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclocking Control Information +/// +/// @details +/// - Whether the device supports overclocking. +/// - The +/// bSupported/bRelative/bReference/units/min/max/step/default/reference +/// values for the available overclock controls +/// - The idea is to facilitate the way the applications present overclock +/// settings to the user. If bSupported is false, the corresponding +/// overclock control is not supported +/// - The setting units will be an enum that enables the application to know +/// the units for the control setting e.g. MHz. The min and max settings +/// give the limits for the control. +/// - The step setting gives the minimum change in the control value (plus +/// or minus) - if a control is not changed by at least this amount, the +/// hardware may round up or down. +/// - The default values gives the manufacturing setting for the control. +/// Some controls such as frequency offset and voltage offset are +/// relative; in this case, bRelative will be true, otherwise the control +/// settings are absolute values. +/// - For relative controls and if bReference is true, the reference value +/// gives the absolute value at the default setting. +/// - If bReference is false, the absolute value of the default setting is +/// no not known and it is probably better to display the setting to users +/// as percentage offsets. +typedef struct _ctl_oc_control_info_t +{ + bool bSupported; ///< [out] Indicates if the values are known. + bool bRelative; ///< [out] Indicates if the values are meant to be taken as relative values + ///< instead of absolut values. + bool bReference; ///< [out] For relative values, this indicates if a reference is available. + ctl_units_t units; ///< [out] Units for the values. + double min; ///< [out] Minimum Value. + double max; ///< [out] Maximum Value. + double step; ///< [out] Step Value. + double Default; ///< [out] Default Value. + double reference; ///< [out] Reference Value if the bReference is true. + +} ctl_oc_control_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock properties +typedef struct _ctl_oc_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool bSupported; ///< [out] Indicates if the adapter supports overclocking. + ctl_oc_control_info_t gpuFrequencyOffset; ///< [out] related to function ::ctlOverclockGpuFrequencyOffsetSet + ctl_oc_control_info_t gpuVoltageOffset; ///< [out] related to function ::ctlOverclockGpuVoltageOffsetSet + ctl_oc_control_info_t vramFrequencyOffset; ///< [out] related to function ::ctlOverclockVramFrequencyOffsetSet + ctl_oc_control_info_t vramVoltageOffset; ///< [out] related to function ::ctlOverclockVramVoltageOffsetSet + ctl_oc_control_info_t powerLimit; ///< [out] related to function ::ctlOverclockPowerLimitSet + ctl_oc_control_info_t temperatureLimit; ///< [out] related to function ::ctlOverclockTemperatureLimitSet + +} ctl_oc_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock Voltage Frequency Pair +typedef struct _ctl_oc_vf_pair_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double Voltage; ///< [in,out] Voltage component of the pair in mV. + double Frequency; ///< [in,out] Frequency component of the pair in MHz. + +} ctl_oc_vf_pair_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_PSU_COUNT +/// @brief Maximum number power supply units. +#define CTL_PSU_COUNT 5 +#endif // CTL_PSU_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSU Type. +typedef enum _ctl_psu_type_t +{ + CTL_PSU_TYPE_PSU_NONE = 0, ///< Type of the PSU is unknown. + CTL_PSU_TYPE_PSU_PCIE = 1, ///< Type of the PSU is PCIe + CTL_PSU_TYPE_PSU_6PIN = 2, ///< Type of the PSU is 6 PIN + CTL_PSU_TYPE_PSU_8PIN = 3, ///< Type of the PSU is 8 PIN + CTL_PSU_TYPE_MAX + +} ctl_psu_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSU Info +typedef struct _ctl_psu_info_t +{ + bool bSupported; ///< [out] Indicates if this PSU entry is supported. + ctl_psu_type_t psuType; ///< [out] Type of the PSU. + ctl_oc_telemetry_item_t energyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed this power source. By taking the + ///< delta between two snapshots and dividing by the delta time in seconds, + ///< an application can compute the average power. + ctl_oc_telemetry_item_t voltage; ///< [out] Instantaneous snapshot of the voltage of this power source. + +} ctl_psu_info_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_FAN_COUNT +/// @brief Maximum number of Fans +#define CTL_FAN_COUNT 5 +#endif // CTL_FAN_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Telemetry +typedef struct _ctl_power_telemetry_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_oc_telemetry_item_t timeStamp; ///< [out] Snapshot of the timestamp counter that measures the total time + ///< since Jan 1, 1970 UTC. It is a decimal value in seconds with a minimum + ///< accuracy of 1 millisecond. + ctl_oc_telemetry_item_t gpuEnergyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed by the GPU chip. By taking the + ///< delta between two snapshots and dividing by the delta time in seconds, + ///< an application can compute the average power. + ctl_oc_telemetry_item_t gpuVoltage; ///< [out] Instantaneous snapshot of the voltage feeding the GPU chip. It + ///< is measured at the power supply output - chip input will be lower. + ctl_oc_telemetry_item_t gpuCurrentClockFrequency; ///< [out] Instantaneous snapshot of the GPU chip frequency. + ctl_oc_telemetry_item_t gpuCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from + ///< the sensor reporting the highest value. + ctl_oc_telemetry_item_t globalActivityCounter; ///< [out] Snapshot of the monotonic global activity counter. It measures + ///< the time in seconds (accurate down to 1 millisecond) that any GPU + ///< engine is busy. By taking the delta between two snapshots and dividing + ///< by the delta time in seconds, an application can compute the average + ///< percentage utilization of the GPU.. + ctl_oc_telemetry_item_t renderComputeActivityCounter; ///< [out] Snapshot of the monotonic 3D/compute activity counter. It + ///< measures the time in seconds (accurate down to 1 millisecond) that any + ///< 3D render/compute engine is busy. By taking the delta between two + ///< snapshots and dividing by the delta time in seconds, an application + ///< can compute the average percentage utilization of all 3D + ///< render/compute blocks in the GPU. + ctl_oc_telemetry_item_t mediaActivityCounter; ///< [out] Snapshot of the monotonic media activity counter. It measures + ///< the time in seconds (accurate down to 1 millisecond) that any media + ///< engine is busy. By taking the delta between two snapshots and dividing + ///< by the delta time in seconds, an application can compute the average + ///< percentage utilization of all media blocks in the GPU. + bool gpuPowerLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip is exceeding the maximum power limits. + ///< Increasing the power limits using ::ctlOverclockPowerLimitSet() is one + ///< way to remove this limitation. + bool gpuTemperatureLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip is exceeding the temperature limits. + ///< Increasing the temperature limits using + ///< ::ctlOverclockTemperatureLimitSet() is one way to reduce this + ///< limitation. Improving the cooling solution is another way. + bool gpuCurrentLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip has exceeded the power supply current + ///< limits. A better power supply is required to reduce this limitation. + bool gpuVoltageLimited; ///< [out] Instantaneous indication that the GPU frequency cannot be + ///< increased because the voltage limits have been reached. Increase the + ///< voltage offset using ::ctlOverclockGpuVoltageOffsetSet() is one way to + ///< reduce this limitation. + bool gpuUtilizationLimited; ///< [out] Instantaneous indication that due to lower GPU utilization, the + ///< hardware has lowered the GPU frequency. + ctl_oc_telemetry_item_t vramEnergyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed by the local memory modules. By + ///< taking the delta between two snapshots and dividing by the delta time + ///< in seconds, an application can compute the average power. + ctl_oc_telemetry_item_t vramVoltage; ///< [out] Instantaneous snapshot of the voltage feeding the memory + ///< modules. + ctl_oc_telemetry_item_t vramCurrentClockFrequency; ///< [out] Instantaneous snapshot of the raw clock frequency driving the + ///< memory modules. + ctl_oc_telemetry_item_t vramCurrentEffectiveFrequency; ///< [out] Instantaneous snapshot of the effective data transfer rate that + ///< the memory modules can sustain based on the current clock frequency.. + ctl_oc_telemetry_item_t vramReadBandwidthCounter; ///< [out] Instantaneous snapshot of the monotonic counter that measures + ///< the read traffic from the memory modules. By taking the delta between + ///< two snapshots and dividing by the delta time in seconds, an + ///< application can compute the average read bandwidth. + ctl_oc_telemetry_item_t vramWriteBandwidthCounter; ///< [out] Instantaneous snapshot of the monotonic counter that measures + ///< the write traffic to the memory modules. By taking the delta between + ///< two snapshots and dividing by the delta time in seconds, an + ///< application can compute the average write bandwidth. + ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from + ///< the sensor reporting the highest value. + bool vramPowerLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules are exceeding the maximum power + ///< limits. + bool vramTemperatureLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules are exceeding the temperature + ///< limits. + bool vramCurrentLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules have exceeded the power supply + ///< current limits. + bool vramVoltageLimited; ///< [out] Instantaneous indication that the memory frequency cannot be + ///< increased because the voltage limits have been reached. + bool vramUtilizationLimited; ///< [out] Instantaneous indication that due to lower memory traffic, the + ///< hardware has lowered the memory frequency. + ctl_oc_telemetry_item_t totalCardEnergyCounter; ///< [out] Total Card Energy Counter. + ctl_psu_info_t psu[CTL_PSU_COUNT]; ///< [out] PSU voltage and power. + ctl_oc_telemetry_item_t fanSpeed[CTL_FAN_COUNT];///< [out] Fan speed. + +} ctl_power_telemetry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get overclock properties - available properties. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGetProperties( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_properties_t* pOcProperties ///< [in,out] The overclocking properties for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock Waiver - Warranty Waiver. +/// +/// @details +/// - Most of the overclock functions will return an error if the waiver is +/// not set. This is because most overclock settings will increase the +/// electric/thermal stress on the part and thus reduce its lifetime. +/// - By setting the waiver, the user is indicate that they are accepting a +/// reduction in the lifetime of the part. +/// - It is the responsibility of overclock applications to notify each user +/// at least once with a popup of the dangers and requiring acceptance. +/// - Only once the user has accepted should this function be called by the +/// application. +/// - It is acceptable for the application to cache the user choice and call +/// this function on future executions without issuing the popup. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockWaiverSet( + ctl_device_adapter_handle_t hDeviceHandle ///< [in][release] Handle to display adapter + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Frequency Offset for the GPU in MHz. +/// +/// @details +/// - Determine the current frequency offset in effect (refer to +/// ::ctlOverclockGpuFrequencyOffsetSet() for details). +/// - The value returned may be different from the value that was previously +/// set by the application depending on hardware limitations or if the +/// function ::ctlOverclockGpuFrequencyOffsetSet() has been called or +/// another application that has changed the value. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcFrequencyOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuFrequencyOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcFrequencyOffset ///< [in,out] The Turbo Overclocking Frequency Desired in MHz. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Frequency Offset for the GPU in MHZ. +/// +/// @details +/// - The purpose of this function is to increase/decrease the frequency at +/// which typical workloads will run within the same thermal budget. +/// - The frequency offset is expressed in units of ±1MHz. +/// - The actual operating frequency for each workload is not guaranteed to +/// change exactly by the specified offset. +/// - For positive frequency offsets, the factory maximum frequency may +/// increase by up to the specified amount. +/// - For negative frequency offsets, the overclock waiver must have been +/// set since this can result in running the part at voltages beyond the +/// part warrantee limits. An error is returned if the waiver has not been +/// set. +/// - Specifying large values for the frequency offset can lead to +/// instability. It is recommended that changes are made in small +/// increments and stability/performance measured running intense GPU +/// workloads before increasing further. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuFrequencyOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocFrequencyOffset ///< [in] The Turbo Overclocking Frequency Desired in MHz. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Gpu Voltage Offset in mV. +/// +/// @details +/// - Determine the current voltage offset in effect on the hardware (refer +/// to ::ctlOverclockGpuVoltageOffsetSet for details). +/// - The value returned may be different from the value that was previously +/// set by the application depending on hardware limitations or if the +/// function ::ctlOverclockGpuVoltageOffsetSet has been called or another +/// application that has changed the value. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcVoltageOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuVoltageOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcVoltageOffset ///< [in,out] The Turbo Overclocking Frequency Desired in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Gpu Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to attempt to run the GPU up to higher +/// voltages beyond the part warrantee limits. This can permit running at +/// even higher frequencies than can be obtained using the frequency +/// offset setting, but at the risk of reducing the lifetime of the part. +/// - The voltage offset is expressed in units of ±millivolts with values +/// permitted down to a resolution of 1 millivolt. +/// - The overclock waiver must be set before calling this function +/// otherwise and error will be returned. +/// - There is no guarantee that a workload can operate at the higher +/// frequencies permitted by this setting. Significantly more heat will be +/// generated at these high frequencies/voltages which will necessitate a +/// good cooling solution. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuVoltageOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocVoltageOffset ///< [in] The Turbo Overclocking Frequency Desired in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gets the Locked GPU Voltage for Overclocking in mV. +/// +/// @details +/// - The purpose of this function is to determine if the current values of +/// the frequency/voltage lock. +/// - If the lock is not currently active, will return 0 for frequency and +/// voltage. +/// - Note that the operating frequency/voltage may be lower than these +/// settings if power/thermal limits are exceeded. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pVfPair` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuLockGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_vf_pair_t* pVfPair ///< [out] The current locked voltage and frequency. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Locks the GPU voltage for Overclocking in mV. +/// +/// @details +/// - The purpose of this function is to provide an interface for scanners +/// to lock the frequency and voltage to fixed values. +/// - The frequency is expressed in units of MHz with a resolution of 1MHz. +/// - The voltage is expressed in units of ±millivolts with values +/// permitted down to a resolution of 1 millivolt. +/// - The overclock waiver must be set since fixing the voltage at a high +/// value puts unnecessary stress on the part. +/// - The actual frequency may reduce depending on power/thermal +/// limitations. +/// - Requesting a frequency and/or voltage of 0 will return the hardware to +/// dynamic frequency/voltage management with any previous frequency +/// offset or voltage offset settings reapplied. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuLockSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_vf_pair_t vFPair ///< [in] The current locked voltage and frequency. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the current Vram Frequency Offset in GT/s. +/// +/// @details +/// - The purpose of this function is to return the current VRAM frequency +/// offset in units of GT/s. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcFrequencyOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramFrequencyOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcFrequencyOffset ///< [in,out] The current Memory Frequency in GT/s. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the desired Vram frquency Offset in GT/s +/// +/// @details +/// - The purpose of this function is to increase/decrease the frequency of +/// VRAM. +/// - The frequency offset is expressed in units of GT/s with a minimum step +/// size given by ::ctlOverclockGetProperties. +/// - The actual operating frequency for each workload is not guaranteed to +/// change exactly by the specified offset. +/// - The waiver must be set using clibOverclockWaiverSet() before this +/// function can be called. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// - If the memory controller doesn't support changes to frequency on the +/// fly, one of the following return codes will be given: +/// - ::CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED: The requested memory +/// overclock will be applied when the device is reset or the system is +/// rebooted. In this case, the overclock software should check if the +/// overclock request was applied after the reset/reboot. If it was and +/// when the overclock application shuts down gracefully and if the +/// overclock application wants the setting to be persistent, the +/// application should request the same overclock settings again so that +/// they will be applied on the next reset/reboot. If this is not done, +/// then every time the device is reset and overclock is requested, the +/// device needs to be reset a second time. +/// - ::CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED: The requested memory +/// overclock will be applied when the system is rebooted. In this case, +/// the overclock software should check if the overclock request was +/// applied after the reboot. If it was and when the overclock application +/// shuts down gracefully and if the overclock application wants the +/// setting to be persistent, the application should request the same +/// overclock settings again so that they will be applied on the next +/// reset/reboot. If this is not done and the overclock setting is +/// requested after the reboot has occurred, a second reboot will be +/// required. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramFrequencyOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocFrequencyOffset ///< [in] The desired Memory Frequency in GT/s. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Vram Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to increase/decrease the voltage of +/// VRAM. +/// - The voltage offset is expressed in units of millivolts with a minimum +/// step size given by ::ctlOverclockGetProperties. +/// - The waiver must be set using ::ctlOverclockWaiverSet before this +/// function can be called. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// - If the memory controller doesn't support changes to voltage on the +/// fly, one of the following return codes will be given: +/// - ::CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED: The requested memory +/// overclock will be applied when the device is reset or the system is +/// rebooted. In this case, the overclock software should check if the +/// overclock request was applied after the reset/reboot. If it was and +/// when the overclock application shuts down gracefully and if the +/// overclock application wants the setting to be persistent, the +/// application should request the same overclock settings again so that +/// they will be applied on the next reset/reboot. If this is not done, +/// then every time the device is reset and overclock is requested, the +/// device needs to be reset a second time. +/// - ::CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED: The requested memory +/// overclock will be applied when the system is rebooted. In this case, +/// the overclock software should check if the overclock request was +/// applied after the reboot. If it was and when the overclock application +/// shuts down gracefully and if the overclock application wants the +/// setting to be persistent, the application should request the same +/// overclock settings again so that they will be applied on the next +/// reset/reboot. If this is not done and the overclock setting is +/// requested after the reboot has occurred, a second reboot will be +/// required. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pVoltage` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramVoltageOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pVoltage ///< [out] The current locked voltage in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Vram Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to set the maximum sustained power +/// limit. If the average GPU power averaged over a few seconds exceeds +/// this value, the frequency of the GPU will be throttled. +/// - Set a value of 0 to disable this power limit. In this case, the GPU +/// frequency will not throttle due to average power but may hit other +/// limits. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramVoltageOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double voltage ///< [in] The voltage to be locked in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the sustained power limit in mW. +/// +/// @details +/// - The purpose of this function is to read the current sustained power +/// limit. +/// - A value of 0 means that the limit is disabled - the GPU frequency can +/// run as high as possible until other limits are hit. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSustainedPowerLimit` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockPowerLimitGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pSustainedPowerLimit ///< [in,out] The current sustained power limit in mW. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the sustained power limit in mW. +/// +/// @details +/// - The purpose of this function is to set the maximum sustained power +/// limit. If the average GPU power averaged over a few seconds exceeds +/// this value, the frequency of the GPU will be throttled. +/// - Set a value of 0 to disable this power limit. In this case, the GPU +/// frequency will not throttle due to average power but may hit other +/// limits. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockPowerLimitSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double sustainedPowerLimit ///< [in] The desired sustained power limit in mW. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the current temperature limit in Celsius. +/// +/// @details +/// - The purpose of this function is to read the current thermal limit. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTemperatureLimit` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockTemperatureLimitGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pTemperatureLimit ///< [in,out] The current temperature limit in Celsius. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the temperature limit in Celsius. +/// +/// @details +/// - The purpose of this function is to change the maximum thermal limit. +/// When the GPU temperature exceeds this value, the GPU frequency will be +/// throttled. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockTemperatureLimitSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double temperatureLimit ///< [in] The desired temperature limit in Celsius. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power Telemetry. +/// +/// @details +/// - Limited rate of 50 ms, any call under 50 ms will return the same +/// information. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTelemetryInfo` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerTelemetryGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_power_telemetry_t* pTelemetryInfo ///< [out] The overclocking properties for the specified domain. + ); + + +#if !defined(__GNUC__) +#pragma endregion // overclock +#endif +// Intel 'ctlApi' for Device Adapter - PCI Information +#if !defined(__GNUC__) +#pragma region pci +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief PCI address +typedef struct _ctl_pci_address_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t domain; ///< [out] BDF domain + uint32_t bus; ///< [out] BDF bus + uint32_t device; ///< [out] BDF device + uint32_t function; ///< [out] BDF function + +} ctl_pci_address_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PCI speed +typedef struct _ctl_pci_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t gen; ///< [out] The link generation. A value of -1 means that this property is + ///< unknown. + int32_t width; ///< [out] The number of lanes. A value of -1 means that this property is + ///< unknown. + int64_t maxBandwidth; ///< [out] The maximum bandwidth in bytes/sec (sum of all lanes). A value + ///< of -1 means that this property is unknown. + +} ctl_pci_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Static PCI properties +typedef struct _ctl_pci_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pci_address_t address; ///< [out] The BDF address + ctl_pci_speed_t maxSpeed; ///< [out] Fastest port configuration supported by the device (sum of all + ///< lanes) + bool resizable_bar_supported; ///< [out] Support for Resizable Bar on this device. + bool resizable_bar_enabled; ///< [out] Resizable Bar enabled on this device + +} ctl_pci_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Dynamic PCI state +typedef struct _ctl_pci_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pci_speed_t speed; ///< [out] The current port configure speed + +} ctl_pci_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get PCI properties - address, max speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPciGetProperties( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_pci_properties_t* pProperties ///< [in,out] Will contain the PCI properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current PCI state - current speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPciGetState( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_pci_state_t* pState ///< [in,out] Will contain the PCI properties. + ); + + +#if !defined(__GNUC__) +#pragma endregion // pci +#endif +// Intel 'ctlApi' for Device Adapter - Power management +#if !defined(__GNUC__) +#pragma region power +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Properties related to device power settings +typedef struct _ctl_power_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool canControl; ///< [out] Software can change the power limits of this domain assuming the + ///< user has permissions. + int32_t defaultLimit; ///< [out] The factory default TDP power limit of the part in milliwatts. A + ///< value of -1 means that this is not known. + int32_t minLimit; ///< [out] The minimum power limit in milliwatts that can be requested. + int32_t maxLimit; ///< [out] The maximum power limit in milliwatts that can be requested. + +} ctl_power_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Energy counter snapshot +/// +/// @details +/// - Average power is calculated by taking two snapshots (s1, s2) and using +/// the equation: PowerWatts = (s2.energy - s1.energy) / (s2.timestamp - +/// s1.timestamp) +typedef struct _ctl_power_energy_counter_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t energy; ///< [out] The monotonic energy counter in microjoules. + uint64_t timestamp; ///< [out] Microsecond timestamp when energy was captured. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_power_energy_counter_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sustained power limits +/// +/// @details +/// - The power controller (Punit) will throttle the operating frequency if +/// the power averaged over a window (typically seconds) exceeds this +/// limit. +typedef struct _ctl_power_sustained_limit_t +{ + bool enabled; ///< [in,out] indicates if the limit is enabled (true) or ignored (false) + int32_t power; ///< [in,out] power limit in milliwatts + int32_t interval; ///< [in,out] power averaging window (Tau) in milliseconds + +} ctl_power_sustained_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Burst power limit +/// +/// @details +/// - The power controller (Punit) will throttle the operating frequency of +/// the device if the power averaged over a few milliseconds exceeds a +/// limit known as PL2. Typically PL2 > PL1 so that it permits the +/// frequency to burst higher for short periods than would be otherwise +/// permitted by PL1. +typedef struct _ctl_power_burst_limit_t +{ + bool enabled; ///< [in,out] indicates if the limit is enabled (true) or ignored (false) + int32_t power; ///< [in,out] power limit in milliwatts + +} ctl_power_burst_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Peak power limit +/// +/// @details +/// - The power controller (Punit) will preemptively throttle the operating +/// frequency of the device when the instantaneous power exceeds this +/// limit. The limit is known as PL4. It expresses the maximum power that +/// can be drawn from the power supply. +/// - If this power limit is removed or set too high, the power supply will +/// generate an interrupt when it detects an overcurrent condition and the +/// power controller will throttle the device frequencies down to min. It +/// is thus better to tune the PL4 value in order to avoid such +/// excursions. +typedef struct _ctl_power_peak_limit_t +{ + int32_t powerAC; ///< [in,out] power limit in milliwatts for the AC power source. + int32_t powerDC; ///< [in,out] power limit in milliwatts for the DC power source. On input, + ///< this is ignored if the product does not have a battery. On output, + ///< this will be -1 if the product does not have a battery. + +} ctl_power_peak_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power limits +typedef struct _ctl_power_limits_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_sustained_limit_t sustainedPowerLimit;///< [in,out] sustained power limit. + ctl_power_burst_limit_t burstPowerLimit; ///< [in,out] burst power limit. + ctl_power_peak_limit_t peakPowerLimits; ///< [in,out] peak power limit. + +} ctl_power_limits_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Energy threshold +/// +/// @details +/// - . +typedef struct _ctl_energy_threshold_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool enable; ///< [in,out] Indicates if the energy threshold is enabled. + double threshold; ///< [in,out] The energy threshold in Joules. Will be 0.0 if no threshold + ///< has been set. + uint32_t processId; ///< [in,out] The host process ID that set the energy threshold. Will be + ///< 0xFFFFFFFF if no threshold has been set. + +} ctl_energy_threshold_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of power domains +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumPowerDomains( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_pwr_handle_t* phPower ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get properties related to a power domain +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetProperties( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_properties_t* pProperties ///< [in,out] Structure that will contain property data. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get energy counter +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pEnergy` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetEnergyCounter( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_energy_counter_t* pEnergy ///< [in,out] Will contain the latest snapshot of the energy counter and + ///< timestamp when the last counter value was measured. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get power limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetLimits( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_limits_t* pPowerLimits ///< [in,out][optional] Structure that will contain the power limits. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set power limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_NOT_AVAILABLE +/// + The device is in use, meaning that the GPU is under Over clocking, applying power limits under overclocking is not supported. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerSetLimits( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + const ctl_power_limits_t* pPowerLimits ///< [in][optional] Structure that will contain the power limits. + ); + + +#if !defined(__GNUC__) +#pragma endregion // power +#endif +// Intel 'ctlApi' for Device Adapter - Temperature Sensors +#if !defined(__GNUC__) +#pragma region temperature +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Temperature sensors +typedef enum _ctl_temp_sensors_t +{ + CTL_TEMP_SENSORS_GLOBAL = 0, ///< The maximum temperature across all device sensors + CTL_TEMP_SENSORS_GPU = 1, ///< The maximum temperature across all sensors in the GPU + CTL_TEMP_SENSORS_MEMORY = 2, ///< The maximum temperature across all sensors in the local memory + CTL_TEMP_SENSORS_GLOBAL_MIN = 3, ///< The minimum temperature across all device sensors + CTL_TEMP_SENSORS_GPU_MIN = 4, ///< The minimum temperature across all sensors in the GPU + CTL_TEMP_SENSORS_MEMORY_MIN = 5, ///< The minimum temperature across all sensors in the local device memory + CTL_TEMP_SENSORS_MAX + +} ctl_temp_sensors_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Temperature sensor properties +typedef struct _ctl_temp_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_temp_sensors_t type; ///< [out] Which part of the device the temperature sensor measures + double maxTemperature; ///< [out] Will contain the maximum temperature for the specific device in + ///< degrees Celsius. + +} ctl_temp_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of temperature sensors +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumTemperatureSensors( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_temp_handle_t* phTemperature ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get temperature sensor properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hTemperature` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlTemperatureGetProperties( + ctl_temp_handle_t hTemperature, ///< [in] Handle for the component. + ctl_temp_properties_t* pProperties ///< [in,out] Will contain the temperature sensor properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the temperature from a specified sensor +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hTemperature` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTemperature` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlTemperatureGetState( + ctl_temp_handle_t hTemperature, ///< [in] Handle for the component. + double* pTemperature ///< [in,out] Will contain the temperature read from the specified sensor + ///< in degrees Celsius. + ); + + +#if !defined(__GNUC__) +#pragma endregion // temperature +#endif + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlInit +typedef ctl_result_t (CTL_APICALL *ctl_pfnInit_t)( + ctl_init_args_t*, + ctl_api_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlClose +typedef ctl_result_t (CTL_APICALL *ctl_pfnClose_t)( + ctl_api_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetRuntimePath +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetRuntimePath_t)( + ctl_runtime_path_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlWaitForPropertyChange +typedef ctl_result_t (CTL_APICALL *ctl_pfnWaitForPropertyChange_t)( + ctl_device_adapter_handle_t, + ctl_wait_property_change_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlReservedCall +typedef ctl_result_t (CTL_APICALL *ctl_pfnReservedCall_t)( + ctl_device_adapter_handle_t, + ctl_reserved_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupported3DCapabilities +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupported3DCapabilities_t)( + ctl_device_adapter_handle_t, + ctl_3d_feature_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSet3DFeature +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSet3DFeature_t)( + ctl_device_adapter_handle_t, + ctl_3d_feature_getset_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlCheckDriverVersion +typedef ctl_result_t (CTL_APICALL *ctl_pfnCheckDriverVersion_t)( + ctl_device_adapter_handle_t, + ctl_version_info_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateDevices +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateDevices_t)( + ctl_api_handle_t, + uint32_t*, + ctl_device_adapter_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateDisplayOutputs +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateDisplayOutputs_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_display_output_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetDeviceProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetDeviceProperties_t)( + ctl_device_adapter_handle_t, + ctl_device_adapter_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetDisplayProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetDisplayProperties_t)( + ctl_display_output_handle_t, + ctl_display_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetAdaperDisplayEncoderProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetAdaperDisplayEncoderProperties_t)( + ctl_display_output_handle_t, + ctl_adapter_display_encoder_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetZeDevice +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetZeDevice_t)( + ctl_device_adapter_handle_t, + void*, + void** + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSharpnessCaps +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSharpnessCaps_t)( + ctl_display_output_handle_t, + ctl_sharpness_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetCurrentSharpness +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetCurrentSharpness_t)( + ctl_display_output_handle_t, + ctl_sharpness_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetCurrentSharpness +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetCurrentSharpness_t)( + ctl_display_output_handle_t, + ctl_sharpness_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlI2CAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnI2CAccess_t)( + ctl_display_output_handle_t, + ctl_i2c_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlAUXAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnAUXAccess_t)( + ctl_display_output_handle_t, + ctl_aux_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetPowerOptimizationCaps +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetPowerOptimizationCaps_t)( + ctl_display_output_handle_t, + ctl_power_optimization_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetPowerOptimizationSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetPowerOptimizationSetting_t)( + ctl_display_output_handle_t, + ctl_power_optimization_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetPowerOptimizationSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetPowerOptimizationSetting_t)( + ctl_display_output_handle_t, + ctl_power_optimization_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetBrightnessSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetBrightnessSetting_t)( + ctl_display_output_handle_t, + ctl_set_brightness_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetBrightnessSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetBrightnessSetting_t)( + ctl_display_output_handle_t, + ctl_get_brightness_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPixelTransformationGetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnPixelTransformationGetConfig_t)( + ctl_display_output_handle_t, + ctl_pixtx_pipe_get_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPixelTransformationSetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnPixelTransformationSetConfig_t)( + ctl_display_output_handle_t, + ctl_pixtx_pipe_set_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPanelDescriptorAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnPanelDescriptorAccess_t)( + ctl_display_output_handle_t, + ctl_panel_descriptor_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedRetroScalingCapability +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedRetroScalingCapability_t)( + ctl_device_adapter_handle_t, + ctl_retro_scaling_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetRetroScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetRetroScaling_t)( + ctl_device_adapter_handle_t, + ctl_retro_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedScalingCapability +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedScalingCapability_t)( + ctl_display_output_handle_t, + ctl_scaling_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetCurrentScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetCurrentScaling_t)( + ctl_display_output_handle_t, + ctl_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetCurrentScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetCurrentScaling_t)( + ctl_display_output_handle_t, + ctl_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetLACEConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetLACEConfig_t)( + ctl_display_output_handle_t, + ctl_lace_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetLACEConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetLACEConfig_t)( + ctl_display_output_handle_t, + ctl_lace_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSoftwarePSR +typedef ctl_result_t (CTL_APICALL *ctl_pfnSoftwarePSR_t)( + ctl_display_output_handle_t, + ctl_sw_psr_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetIntelArcSyncInfoForMonitor +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetIntelArcSyncInfoForMonitor_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_monitor_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateMuxDevices +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateMuxDevices_t)( + ctl_api_handle_t, + uint32_t*, + ctl_mux_output_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetMuxProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetMuxProperties_t)( + ctl_mux_output_handle_t, + ctl_mux_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSwitchMux +typedef ctl_result_t (CTL_APICALL *ctl_pfnSwitchMux_t)( + ctl_mux_output_handle_t, + ctl_display_output_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetIntelArcSyncProfile +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetIntelArcSyncProfile_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_profile_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetIntelArcSyncProfile +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetIntelArcSyncProfile_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_profile_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEdidManagement +typedef ctl_result_t (CTL_APICALL *ctl_pfnEdidManagement_t)( + ctl_display_output_handle_t, + ctl_edid_management_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetCustomMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetCustomMode_t)( + ctl_display_output_handle_t, + ctl_get_set_custom_mode_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetCombinedDisplay +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetCombinedDisplay_t)( + ctl_device_adapter_handle_t, + ctl_combined_display_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetDisplayGenlock +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetDisplayGenlock_t)( + ctl_device_adapter_handle_t*, + ctl_genlock_args_t**, + uint32_t, + ctl_device_adapter_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumEngineGroups +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumEngineGroups_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_engine_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEngineGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnEngineGetProperties_t)( + ctl_engine_handle_t, + ctl_engine_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEngineGetActivity +typedef ctl_result_t (CTL_APICALL *ctl_pfnEngineGetActivity_t)( + ctl_engine_handle_t, + ctl_engine_stats_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumFans +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumFans_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_fan_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetProperties_t)( + ctl_fan_handle_t, + ctl_fan_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetConfig_t)( + ctl_fan_handle_t, + ctl_fan_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetDefaultMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetDefaultMode_t)( + ctl_fan_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetFixedSpeedMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetFixedSpeedMode_t)( + ctl_fan_handle_t, + const ctl_fan_speed_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetSpeedTableMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetSpeedTableMode_t)( + ctl_fan_handle_t, + const ctl_fan_speed_table_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetState_t)( + ctl_fan_handle_t, + ctl_fan_speed_units_t, + int32_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumFrequencyDomains +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumFrequencyDomains_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_freq_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetProperties_t)( + ctl_freq_handle_t, + ctl_freq_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetAvailableClocks +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetAvailableClocks_t)( + ctl_freq_handle_t, + uint32_t*, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetRange +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetRange_t)( + ctl_freq_handle_t, + ctl_freq_range_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencySetRange +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencySetRange_t)( + ctl_freq_handle_t, + const ctl_freq_range_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetState_t)( + ctl_freq_handle_t, + ctl_freq_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetThrottleTime +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetThrottleTime_t)( + ctl_freq_handle_t, + ctl_freq_throttle_time_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedVideoProcessingCapabilities +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedVideoProcessingCapabilities_t)( + ctl_device_adapter_handle_t, + ctl_video_processing_feature_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetVideoProcessingFeature +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetVideoProcessingFeature_t)( + ctl_device_adapter_handle_t, + ctl_video_processing_feature_getset_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumMemoryModules +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumMemoryModules_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_mem_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetProperties_t)( + ctl_mem_handle_t, + ctl_mem_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetState_t)( + ctl_mem_handle_t, + ctl_mem_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetBandwidth +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetBandwidth_t)( + ctl_mem_handle_t, + ctl_mem_bandwidth_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGetProperties_t)( + ctl_device_adapter_handle_t, + ctl_oc_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockWaiverSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockWaiverSet_t)( + ctl_device_adapter_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuFrequencyOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuFrequencyOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuFrequencyOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuFrequencyOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuVoltageOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuVoltageOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuVoltageOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuVoltageOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuLockGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuLockGet_t)( + ctl_device_adapter_handle_t, + ctl_oc_vf_pair_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuLockSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuLockSet_t)( + ctl_device_adapter_handle_t, + ctl_oc_vf_pair_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramFrequencyOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramFrequencyOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramFrequencyOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramFrequencyOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramVoltageOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramVoltageOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramVoltageOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramVoltageOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockPowerLimitGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockPowerLimitGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockPowerLimitSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockPowerLimitSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockTemperatureLimitGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockTemperatureLimitGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockTemperatureLimitSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockTemperatureLimitSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerTelemetryGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerTelemetryGet_t)( + ctl_device_adapter_handle_t, + ctl_power_telemetry_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPciGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnPciGetProperties_t)( + ctl_device_adapter_handle_t, + ctl_pci_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPciGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnPciGetState_t)( + ctl_device_adapter_handle_t, + ctl_pci_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumPowerDomains +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumPowerDomains_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_pwr_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetProperties_t)( + ctl_pwr_handle_t, + ctl_power_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetEnergyCounter +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetEnergyCounter_t)( + ctl_pwr_handle_t, + ctl_power_energy_counter_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetLimits +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetLimits_t)( + ctl_pwr_handle_t, + ctl_power_limits_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerSetLimits +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerSetLimits_t)( + ctl_pwr_handle_t, + const ctl_power_limits_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumTemperatureSensors +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumTemperatureSensors_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_temp_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlTemperatureGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnTemperatureGetProperties_t)( + ctl_temp_handle_t, + ctl_temp_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlTemperatureGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnTemperatureGetState_t)( + ctl_temp_handle_t, + double* + ); + + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // _CTL_API_H \ No newline at end of file diff --git a/IntelOC/IntelOC - Backup.csproj b/IntelOC/IntelOC - Backup.csproj new file mode 100644 index 0000000..6c10be6 --- /dev/null +++ b/IntelOC/IntelOC - Backup.csproj @@ -0,0 +1,22 @@ + + + + Exe + net6.0 + enable + enable + False + False + + + + + IntelOCWrapper.dll + + + + + + + + diff --git a/IntelOC/IntelOC.csproj b/IntelOC/IntelOC.csproj new file mode 100644 index 0000000..8a0b3ce --- /dev/null +++ b/IntelOC/IntelOC.csproj @@ -0,0 +1,22 @@ + + + + Exe + net6.0 + enable + enable + False + False + + + + + IntelOCWrapper.dll + + + + + + + + diff --git a/IntelOC/IntelOC.sln b/IntelOC/IntelOC.sln new file mode 100644 index 0000000..212839a --- /dev/null +++ b/IntelOC/IntelOC.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33502.453 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntelOC", "IntelOC.csproj", "{189E7D46-9656-4C7A-BEEA-05DE894E1555}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {189E7D46-9656-4C7A-BEEA-05DE894E1555}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {189E7D46-9656-4C7A-BEEA-05DE894E1555}.Debug|Any CPU.Build.0 = Debug|Any CPU + {189E7D46-9656-4C7A-BEEA-05DE894E1555}.Release|Any CPU.ActiveCfg = Release|Any CPU + {189E7D46-9656-4C7A-BEEA-05DE894E1555}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DEA226DB-417E-4549-8E0A-C4AE2C3CFA25} + EndGlobalSection +EndGlobal diff --git a/IntelOC/IntelOCWrapper.dll b/IntelOC/IntelOCWrapper.dll new file mode 100644 index 0000000000000000000000000000000000000000..fa6f5dc56d45db1ddb3b2d7e6f12fcf2fb48657a GIT binary patch literal 189952 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 output_PnPSignedDriver.txt +Get-WmiObject -query "SELECT * FROM Win32_PnPAllocatedResource" > output_PnPAllocatedResource.txt + + +Intel(R) NF I2C Host Controller + + +\\?\C:\Users\gburri\Projects\temp2RGB\target\debug\WinRing0x64.sys + +A770: +"\\\\?\\PCI#VEN_8086&DEV_56A0&SUBSYS_38881025&REV_08#6&1cb01252&0&00080009#{1ca05180-a699-450a-9a0c-de4fbe3ddd89}" + + + [return: MarshalAs(UnmanagedType.U1)] + internal static unsafe bool CVGAAdaptor\u002ESetLEDColor( + [In] CVGAAdaptor* obj0, + byte nArea, + byte r, + byte g, + byte b) + { + \u0024ArrayType\u0024\u0024\u0024BY08E arrayTypeBy08E; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ref arrayTypeBy08E = (sbyte) 7; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 1) = (sbyte) 7; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 2) = (sbyte) nArea; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 3) = (sbyte) r; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 4) = (sbyte) g; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 5) = (sbyte) b; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 6) = (sbyte) 0; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 7) = (sbyte) 0; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + ^(sbyte&) ((IntPtr) &arrayTypeBy08E + 8) = (sbyte) 0; + ulong num1 = 9; + \u0024ArrayType\u0024\u0024\u0024BY08E* arrayTypeBy08EPtr1 = &\u003CModule\u003E.\u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDColor\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEE\u0040Z\u00404PAEA; + \u0024ArrayType\u0024\u0024\u0024BY08E* arrayTypeBy08EPtr2 = &arrayTypeBy08E; + byte num2 = 7; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + byte num3 = ^(byte&) ref \u003CModule\u003E.\u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDColor\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEE\u0040Z\u00404PAEA; + // ISSUE: cast to a reference type + // ISSUE: explicit reference operation + if ((byte) 7 >= ^(byte&) ref \u003CModule\u003E.\u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDColor\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEE\u0040Z\u00404PAEA) + { + while ((uint) num2 <= (uint) num3) + { + if (num1 == 1UL) + return true; + --num1; + ++arrayTypeBy08EPtr2; + ++arrayTypeBy08EPtr1; + num2 = *(byte*) arrayTypeBy08EPtr2; + num3 = *(byte*) arrayTypeBy08EPtr1; + if ((uint) num2 < (uint) num3) + break; + } + } + \u003CModule\u003E.\u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDColor\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEE\u0040Z\u00404PAEA = arrayTypeBy08E; + \u003CModule\u003E.CVGAAdaptor\u002ELogData(obj0, (sbyte*) &\u003CModule\u003E.\u003F\u003F_C\u0040_0BB\u0040MOBGKECJ\u0040Fake\u003F5I2C_Write\u003F3\u003F5\u0040, (byte*) &arrayTypeBy08E, 9); + return true; + } + + [return: MarshalAs(UnmanagedType.U1)] + internal static unsafe bool CVGAAdaptorIntel\u002EI2C_Write( + [In] CVGAAdaptorIntel* obj0, + int nOffset, + byte* pData, + int nDataSize, + [MarshalAs(UnmanagedType.U1)] bool bOutputDebug) + { + if (*(long*) ((IntPtr) obj0 + 1256L) == -1L && !\u003CModule\u003E.CVGAAdaptorIntel\u002EI2C_OpenDevice(obj0)) + return false; + \u0024ArrayType\u0024\u0024\u0024BY0IA\u0040D arrayTypeBy0IaD; + if (!\u003CModule\u003E.CVGAAdaptorIntel\u002EI2C_OpenTarget(obj0)) + { + \u003CModule\u003E.sprintf_s((sbyte*) &arrayTypeBy0IaD, 128UL, (sbyte*) &\u003CModule\u003E.\u003F\u003F_C\u0040_0CO\u0040GJJFMHGA\u0040DeviceIoControl\u003F\u0024CI\u003F\u0024CJ\u003F5to\u003F5devcie\u003F5FAI\u0040, __arglist ((int) \u003CModule\u003E.GetLastError())); + \u003CModule\u003E.OutputDebugStringA((sbyte*) &arrayTypeBy0IaD); + } + if (bOutputDebug) + \u003CModule\u003E.CVGAAdaptor\u002ELogData((CVGAAdaptor*) obj0, (sbyte*) &\u003CModule\u003E.\u003F\u003F_C\u0040_0M\u0040DGLNBELN\u0040I2C_Write\u003F3\u003F5\u0040, pData, nDataSize); + int num = \u003CModule\u003E.CVGAAdaptorIntel\u002EI2C_WriteTarget(obj0, pData, nDataSize) ? 1 : 0; + if (num == 0) + { + \u003CModule\u003E.sprintf_s((sbyte*) &arrayTypeBy0IaD, 128UL, (sbyte*) &\u003CModule\u003E.\u003F\u003F_C\u0040_0CI\u0040FFLBFBLK\u0040WriteFile\u003F\u0024CI\u003F\u0024CJ\u003F5to\u003F5devcie\u003F5FAILED\u003F4\u003F5h\u0040, __arglist ((int) \u003CModule\u003E.GetLastError())); + \u003CModule\u003E.OutputDebugStringA((sbyte*) &arrayTypeBy0IaD); + } + \u003CModule\u003E.CVGAAdaptorIntel\u002EI2C_CloseTarget(obj0); + return num != 0; + } + + + +__GENUS : 2 +__CLASS : Win32_PnPSignedDriver +__SUPERCLASS : CIM_Service +__DYNASTY : CIM_ManagedSystemElement +__RELPATH : +__PROPERTY_COUNT : 28 +__DERIVATION : {CIM_Service, CIM_LogicalElement, CIM_ManagedSystemElement} +__SERVER : SMOL-WHITE +__NAMESPACE : root\cimv2 +__PATH : +Caption : +ClassGuid : {4d36e97d-e325-11ce-bfc1-08002be10318} +CompatID : INTC#I2C +CreationClassName : +Description : Intel(R) NF I2C Host Controller +DeviceClass : SYSTEM +DeviceID : DISPLAY\INTC_I2C\7&3255D98A&0&UID26040 +DeviceName : Intel(R) NF I2C Host Controller +DevLoader : +DriverDate : 20220203000000.******+*** +DriverName : +DriverProviderName : Intel Corporation +DriverVersion : 31.100.2210.1 +FriendlyName : +HardWareID : VIDEO\VEN_8086&DEV_56A0&SUBSYS_38881025&REV_08&INTC_I2C +InfName : oem6.inf +InstallDate : +IsSigned : True +Location : +Manufacturer : Intel Corporation +Name : +PDO : \Device\00000078 +Signer : Microsoft Windows Hardware Compatibility Publisher +Started : +StartMode : +Status : +SystemCreationClassName : +SystemName : +PSComputerName : SMOL-WHITE \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6612712 --- /dev/null +++ b/build.rs @@ -0,0 +1,89 @@ +extern crate bindgen; + +use std::{env, path::PathBuf}; + +// From: https://rust-lang.github.io/rust-bindgen/tutorial-0.html + +fn main() { + // Tell cargo to look for shared libraries in the specified directory + println!("cargo:rustc-link-search=winring0"); + println!("cargo:rustc-link-search=IntelArc"); + + // Tell cargo to tell rustc to link the system 'WinRing0x64' shared library. + println!("cargo:rustc-link-lib=WinRing0x64"); + println!("cargo:rustc-link-lib=IntelArc"); + + // Tell cargo to invalidate the built crate whenever the header changes + println!("cargo:rerun-if-changed=OlsApi.h"); + println!("cargo:rerun-if-changed=IntelArc.h"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings_winring0 = bindgen::Builder::default() + // The input header we would like to generate bindings for. + .header("winring0/OlsApi.h") + // .clang_arg("-target") + // .clang_arg("i686-pc-windows-msvc") + .clang_arg("-x") + .clang_arg("c++") + .clang_arg("--std") + .clang_arg("c++14") + // Commented out: not needed. + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + //.parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings for winring0"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + + bindings_winring0 + .write_to_file(out_path.join("ols_api.rs")) + .expect("Couldn't write bindings for winring0!"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings_intel_arc = bindgen::Builder::default() + // The input header we would like to generate bindings for. + .header("IntelArc/IntelArc.h") + // .clang_arg("-target") + // .clang_arg("i686-pc-windows-msvc") + .clang_arg("-x") + .clang_arg("c++") + .clang_arg("--std") + .clang_arg("c++14") + // Commented out: not needed. + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + //.parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings for IntelArc"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + + bindings_intel_arc + .write_to_file(out_path.join("intel_arc.rs")) + .expect("Couldn't write bindings for intel arc!"); + + // let out_dir = env::var("CARGO_TARGET_DIR").unwrap(); + // println!("out_dir: {}", out_dir); + // TODO: How to properly get the (current) target directory? + copy_file("winring0/WinRing0x64.sys", "target/debug/WinRing0x64.sys"); + copy_file("winring0/WinRing0x64.dll", "target/debug/WinRing0x64.dll"); + copy_file("winring0/WinRing0x64.sys", "target/release/WinRing0x64.sys"); + copy_file("winring0/WinRing0x64.dll", "target/release/WinRing0x64.dll"); +} + +fn copy_file(from: &str, to: &str) { + if let Err(e) = std::fs::copy(from, to) { + println!("cargo:warning={e:?} (copy {from} to {to})") + }; +} diff --git a/src/a770.rs b/src/a770.rs new file mode 100644 index 0000000..b37d742 --- /dev/null +++ b/src/a770.rs @@ -0,0 +1,74 @@ +// use windows::{ +// core::w, +// Win32::{self, Storage::FileSystem}, +// }; +// use netcorehost::{nethost, pdcstr}; + +// pub fn set_rgb(r: u8, g: u8, b: u8) { +// unsafe { +// let lib = libloading::Library::new("IntelOCWrapper.dll").unwrap(); + +// let fun: libloading::Symbol bool> = lib.get(b"SetLEDColor").unwrap(); +// let ctlInit: libloading::Symbol std::ffi::c_void> = lib.get(b"ctlInit").unwrap(); +// let ctlInit: libloading::Symbol std::ffi::c_void> = lib.get(b"SetLEDColor").unwrap(); +// println!("ok"); +// } + +// let hostfxr = nethost::load_hostfxr().unwrap(); +// let context = hostfxr.initialize_for_dotnet_command_line(pdcstr!("IntelOCWrapper.dll")).unwrap(); +// let result = context.run_app().value(); + +// unsafe { +// let handle = FileSystem::CreateFileW( +// // w!("\\\\.\\Intel_NF_I2C"), +// w!("\\\\.\\VIDEO\\INTC_I2C"), +// // w!("\\\\.\\WinRing0_1_2_0"), +// 3221225472, +// FileSystem::FILE_SHARE_MODE(0), +// None, +// FileSystem::FILE_CREATION_DISPOSITION(3), +// FileSystem::FILE_FLAGS_AND_ATTRIBUTES(1073741824), +// Win32::Foundation::HANDLE::default(), +// ); + +// println!("handle: {:?}", handle); +// } + +//"\\\\.\\Intel_NF_I2C" +// } + +// internal static \u0024ArrayType\u0024\u0024\u0024BY08E \u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDBehavior\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEEEEEEE\u0040Z\u00404PAEA; +// public static __FnPtr<_ctl_result_t (_ctl_init_args_t*, _ctl_api_handle_t**)> __m2mep\u0040\u003FctlInit\u0040\u0040\u0024\u0024J0YA\u003FAW4_ctl_result_t\u0040\u0040PEAU_ctl_init_args_t\u0040\u0040PEAPEAU_ctl_api_handle_t\u0040\u0040\u0040Z; + +use std::{ + io::prelude::*, + net::TcpStream, + process::{Child, Command}, +}; + +pub struct A770 { + process: Child, + stream: TcpStream, +} + +impl A770 { + pub fn new() -> Self { + A770 { + process: Command::new(r"IntelOC.exe") + .spawn() + .expect("failed to execute process"), + stream: TcpStream::connect("127.0.0.1:6577").unwrap(), + } + } + + pub fn set_color(&mut self, r: u8, g: u8, b: u8) { + let buffer: [u8; 3] = [r, g, b]; + self.stream.write(&buffer).unwrap(); + } +} + +impl Drop for A770 { + fn drop(&mut self) { + self.process.kill().unwrap(); + } +} diff --git a/src/b650_e.rs b/src/b650_e.rs new file mode 100644 index 0000000..b571675 --- /dev/null +++ b/src/b650_e.rs @@ -0,0 +1,97 @@ +use std::str; + +use crate::rgb::RGB; + +/* + * Doc: + * - https://blog.inlart.com/post/openrgb-asus-x570/ + * - https://openrgb-wiki.readthedocs.io/en/latest/asus/ASUS-Aura-USB/ + */ + +const AURA_REQUEST_FIRMWARE_VERSION: u8 = 0x82; +const AURA_REQUEST_CONFIG_TABLE: u8 = 0xB0; + +const VID: u16 = 0x0B05; // Vendor ID: ASUS. +const PID: u16 = 0x19AF; // Product ID: AURA LED Controller. + +pub fn get_device(api: &hidapi::HidApi) -> hidapi::HidDevice { + api.open(VID, PID).unwrap() +} + +pub fn get_firmware_string(device: &hidapi::HidDevice) -> String { + let mut buffer = [0u8; 65]; + buffer[0] = 0xEC; + buffer[1] = AURA_REQUEST_FIRMWARE_VERSION; + let n_write = device.write(&buffer).unwrap(); + assert_eq!(n_write, 65); + + buffer.fill(0); + let n_read = device.read(&mut buffer).unwrap(); + assert_eq!(n_read, 65); + assert_eq!(buffer[0], 0xEC); + assert_eq!(buffer[1], 0x02); + + String::from(str::from_utf8(&buffer[2..17]).unwrap()) +} + +pub fn get_configuration_table(device: &hidapi::HidDevice) -> [u8; 60] { + let mut buffer = [0u8; 65]; + buffer[0] = 0xEC; + buffer[1] = AURA_REQUEST_CONFIG_TABLE; + let n_write = device.write(&buffer).unwrap(); + assert_eq!(n_write, 65); + + buffer.fill(0); + let n_read = device.read(&mut buffer).unwrap(); + assert_eq!(n_read, 65); + assert_eq!(buffer[0], 0xEC); + assert_eq!(buffer[1], 0x30); + + buffer[4..64] + .try_into() + .expect("slice with incorrect length") +} + +// TODO: it seems this doesn't work. +// The mode is set by OpenRGB prior launching temp2RGB for the moment. +pub fn set_fixed_mode(device: &hidapi::HidDevice) { + let mut buffer = [0u8; 65]; + buffer[0] = 0xEC; + buffer[1] = 0x35; + buffer[2] = 0x00; // Channel effect id = Fixed. + buffer[5] = 0x01; // Mode id = static. + + let n_write = device.write(&buffer).unwrap(); + assert_eq!(n_write, 65); +} + +pub fn set_color(device: &hidapi::HidDevice, color: &RGB) { + let mut buffer = [0u8; 65]; + buffer[0] = 0xEC; + buffer[1] = 0x36; + buffer[2] = 0x00; // 16 bits LED mask: first part. + buffer[3] = 0x02; // 16 bits LED mask: second part. + + // Don't know why the first LED isn't used. + // buffer[5] = color.red; + // buffer[6] = color.green; + // buffer[7] = color.blue; + + // // Set second LED. + buffer[8] = color.red; + buffer[9] = color.green; + buffer[10] = color.blue; + + let n_write = device.write(&buffer).unwrap(); + assert_eq!(n_write, 65); +} + +pub fn save_current_color(device: &hidapi::HidDevice) { + let mut buffer = [0u8; 65]; + buffer[0] = 0xEC; + buffer[1] = 0x3F; + buffer[2] = 0x55; + + let n_write = device.write(&buffer).unwrap(); + assert_eq!(n_write, 65); +} diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..20a7600 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,5 @@ +pub const FILE_CONF: &str = "config.ron"; +pub const FREQ_TEMP_POLLING: i32 = 2; +pub const FREQ_REFRESHING_RGB: i32 = 2; +pub const KERNEL_SIZE_SAMPLES: usize = 32; // Time frame: 16 s. +pub const SERVICE_NAME: &str = "Temp2RGB"; diff --git a/src/corsair_vengeance.rs b/src/corsair_vengeance.rs new file mode 100644 index 0000000..0c574f0 --- /dev/null +++ b/src/corsair_vengeance.rs @@ -0,0 +1,102 @@ +use std::time::Duration; + +use crate::{piix4_i2c, rgb::RGB, timer}; + +// use windows::{*, Win32::{System::LibraryLoader::*, Foundation::HCS_E_CONNECTION_CLOSED, Security::InitializeAcl}, Devices::I2c::*, core::HSTRING}; + +use crc::{Algorithm, Crc}; + +const CRC8_ALG: Algorithm = Algorithm { + width: 8, + poly: 0x7, + init: 0x0, + refin: false, + refout: false, + xorout: 0x00, + check: 0x00, + residue: 0x00, +}; + +const BUS: i32 = 0; +const BUS_ADDRESS: i32 = 0x0B00; + +// Called "device location" in 'CorsairDominatorPlatinumController' class. +const ADDRESS_DDR_1: i32 = 0x19; +const ADDRESS_DDR_2: i32 = 0x1B; + +const CORSAIR_LED_COUNT: usize = 12; + +pub struct Controller { + bus: piix4_i2c::I2c, + ddr_address: u8, +} + +impl Controller { + pub fn new(ddr_address: u8) -> Self { + Controller { + bus: piix4_i2c::I2c::new(0x0B00), + ddr_address, + } + } + + pub fn test(&self) { + self.bus.i2c_smbus_write_quick(self.ddr_address, 0); + } + + pub fn set_color(&self, color: &RGB) { + let mut data = [0u8; CORSAIR_LED_COUNT * 3 + 2]; + data[0] = 0xC; + + for i in 0..CORSAIR_LED_COUNT { + let offset = i * 3 + 1; + data[offset] = color.red; + data[offset + 1] = color.green; + data[offset + 2] = color.blue; + } + + let crc = Crc::::new(&CRC8_ALG); + let mut digest = crc.digest(); + digest.update(&data[0..data.len() - 1]); // '-1' to not take the last byte. + data[data.len() - 1] = digest.finalize(); + + let timer = timer::Sleep::new(); + + self.bus + .write_block_data(self.ddr_address, 0x31, &data[0..piix4_i2c::I2C_BLOCK_MAX]); + timer.wait(Duration::from_micros(800)); + + self.bus + .write_block_data(self.ddr_address, 0x32, &data[piix4_i2c::I2C_BLOCK_MAX..]); + timer.wait(Duration::from_micros(200)); + } +} + +// TESTS WITH I2C from winapi: + +// let connection_settings = I2cConnectionSettings::Create(ADDRESS_DDR_1).unwrap(); + +// // For A770: "DISPLAY\\INTC_I2C\\7&3255D98A&0&UID26040" +// // "PCI\\VEN_1022&DEV_790B&SUBSYS_88771043&REV_71\\3&11583659&0&A0" + +// let selector = I2cDevice::GetDeviceSelector().unwrap(); +// println!("{:?}", selector); + +// let devices_async = Devices::Enumeration::DeviceInformation::FindAllAsync().unwrap(); // Devices::Enumeration::DeviceInformation::FindAllAsyncAqsFilter(&selector).unwrap(); +// let devices = devices_async.get().unwrap(); + +// // println!("{:?}", devices.Size()); + +// for i in 0..devices.Size().unwrap() { +// let device = devices.GetAt(i).unwrap(); +// println!("Device Name: {:?}", device.Name().unwrap()); +// println!("Device Kind: {:?}", device.Kind().unwrap()); +// println!("Device ID: {:?}", device.Id().unwrap()); +// println!("-----------------") +// } + +// // let device_id = "PCI\\VEN_1022&DEV_790B"; + +// // let async_get_device = I2cDevice::FromIdAsync(&HSTRING::from(device_id), &connection_settings).unwrap(); +// // let device = async_get_device.get(); + +// // println!("{:?}", device); diff --git a/src/machine.rs b/src/machine.rs new file mode 100644 index 0000000..2c64735 --- /dev/null +++ b/src/machine.rs @@ -0,0 +1,50 @@ +use crate::{a770, b650_e, corsair_vengeance, rgb, sensors_jiji, winring0}; + +pub trait Machine { + fn set_color(&mut self, color: &rgb::RGB); + fn get_gpu_tmp(&self) -> f32; + fn get_cpu_tmp(&self) -> f32; +} + +pub struct MachineJiji { + ram: Vec, + b650e_device: hidapi::HidDevice, + a770: a770::A770, + sensors: sensors_jiji::Sensors, +} + +impl MachineJiji { + pub fn new() -> Self { + let api = hidapi::HidApi::new().unwrap(); + let machine = MachineJiji { + ram: vec![ + corsair_vengeance::Controller::new(0x19), + corsair_vengeance::Controller::new(0x1B), + ], + b650e_device: b650_e::get_device(&api), + a770: a770::A770::new(), + sensors: sensors_jiji::Sensors::new(), + }; + b650_e::set_fixed_mode(&machine.b650e_device); + machine + } +} + +impl Machine for MachineJiji { + fn set_color(&mut self, color: &rgb::RGB) { + for controller in &self.ram { + controller.set_color(&color); + } + b650_e::set_color(&self.b650e_device, &color); + self.a770.set_color(color.red, color.green, color.blue); + } + fn get_gpu_tmp(&self) -> f32 { + self.sensors.read_gpu_temp() + } + + fn get_cpu_tmp(&self) -> f32 { + self.sensors.read_cpu_temp() + } +} + +struct MachineLyssMetal {} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..432d51e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,347 @@ +#[macro_use] +extern crate windows_service; + +use std::{ + collections::HashMap, + env, + ffi::OsString, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread::sleep, + time::{self, Duration}, +}; + +use windows::Win32::Foundation::{ERROR_SERVICE_DOES_NOT_EXIST, WIN32_ERROR}; +use windows_service::{ + service::{ + ServiceAccess, ServiceControl, ServiceControlAccept, ServiceErrorControl, ServiceExitCode, + ServiceInfo, ServiceStartType, ServiceState, ServiceStatus, ServiceType, + }, + service_control_handler::{self, ServiceControlHandlerResult, ServiceStatusHandle}, + service_dispatcher, + service_manager::{ServiceManager, ServiceManagerAccess}, +}; +use wmi::{COMLibrary, Variant, WMIConnection}; + +use crate::rgb::RGB; + +define_windows_service!(ffi_service_main, service_main); + +mod winring0 { + #![allow(warnings, unused)] + include!(concat!(env!("OUT_DIR"), "/ols_api.rs")); +} + +mod intel_arc { + #![allow(warnings, unused)] + include!(concat!(env!("OUT_DIR"), "/intel_arc.rs")); +} + +mod a770; +mod b650_e; +mod machine; +mod main_loop; +// mod common; +mod consts; +mod corsair_vengeance; +mod piix4_i2c; +mod rgb; +// mod roccat; Disabled. +mod sensors_jiji; +mod settings; +mod timer; + +fn main() -> Result<(), windows_service::Error> { + let args: Vec = env::args().collect(); + + println!("Temperature to RGB"); + + if args.contains(&"--no-service".to_string()) { + let completed: Arc = Arc::new(AtomicBool::new(false)); + main_loop::main_loop(completed.clone()); + } else if args.contains(&"--tests".to_string()) { + tests(); + } else if args.contains(&"--install-service".to_string()) { + println!("Installing service..."); + install_service()?; + } else if args.contains(&"--uninstall-service".to_string()) { + println!("Uninstalling service..."); + uninstall_service()?; + } else { + service_dispatcher::start(consts::SERVICE_NAME, ffi_service_main)?; + } + + Ok(()) +} + +fn install_service() -> windows_service::Result<()> { + let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE; + let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; + + let service_binary_path = std::env::current_exe() + .unwrap() + .with_file_name("temp_2_rgb.exe"); + + println!("Installing service: {service_binary_path:?}"); + + let service_info = ServiceInfo { + name: OsString::from(consts::SERVICE_NAME), + display_name: OsString::from(consts::SERVICE_NAME), + service_type: ServiceType::OWN_PROCESS, + start_type: ServiceStartType::AutoStart, + error_control: ServiceErrorControl::Normal, + executable_path: service_binary_path, + launch_arguments: vec![], + dependencies: vec![], + account_name: None, // run as System + account_password: None, + }; + let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?; + service.set_description( + "A service to set the color of hardware according to the temperatur of GPU and CPU", + )?; + Ok(()) +} + +fn uninstall_service() -> windows_service::Result<()> { + let manager_access = ServiceManagerAccess::CONNECT; + let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; + + let service_access = ServiceAccess::QUERY_STATUS | ServiceAccess::STOP | ServiceAccess::DELETE; + let service = service_manager.open_service(consts::SERVICE_NAME, service_access)?; + + // The service will be marked for deletion as long as this function call succeeds. + // However, it will not be deleted from the database until it is stopped and all open handles to it are closed. + service.delete()?; + + // Our handle to it is not closed yet. So we can still query it. + if service.query_status()?.current_state != ServiceState::Stopped { + // If the service cannot be stopped, it will be deleted when the system restarts. + service.stop()?; + } + + // Explicitly close our open handle to the service. This is automatically called when `service` goes out of scope. + drop(service); + + // Win32 API does not give us a way to wait for service deletion. + // To check if the service is deleted from the database, we have to poll it ourselves. + let start = time::Instant::now(); + let timeout = Duration::from_secs(5); + while start.elapsed() < timeout { + if let Err(windows_service::Error::Winapi(e)) = + service_manager.open_service(consts::SERVICE_NAME, ServiceAccess::QUERY_STATUS) + { + let WIN32_ERROR(error_num) = ERROR_SERVICE_DOES_NOT_EXIST; + if e.raw_os_error() == Some(error_num as i32) { + println!("{} is deleted.", consts::SERVICE_NAME); + return Ok(()); + } + } + sleep(Duration::from_secs(1)); + } + println!("{} is marked for deletion.", consts::SERVICE_NAME); + + Ok(()) +} + +fn service_main(arguments: Vec) { + if let Err(error) = run_service(arguments) { + println!("Error: {error}"); + } +} + +fn run_service(arguments: Vec) -> Result<(), windows_service::Error> { + let completed: Arc = Arc::new(AtomicBool::new(false)); + + let completed_event_handler = Arc::clone(&completed); + let event_handler = move |control_event| -> ServiceControlHandlerResult { + match control_event { + ServiceControl::Stop => { + completed_event_handler.store(true, Ordering::Relaxed); + // Handle stop event and return control back to the system. + ServiceControlHandlerResult::NoError + } + // ServiceControl::Shutdown => { + // completed_event_handler.store(true, Ordering::Relaxed); + // // Handle stop event and return control back to the system. + // ServiceControlHandlerResult::NoError + // } + // ServiceControl::Preshutdown => { + // completed_event_handler.store(true, Ordering::Relaxed); + // ServiceControlHandlerResult::NoError + // } + // ServiceControl::PowerEvent(param) => { + // ServiceControlHandlerResult::NotImplemented + // } + // All services must accept Interrogate even if it's a no-op. + ServiceControl::Interrogate => ServiceControlHandlerResult::NoError, + _ => ServiceControlHandlerResult::NotImplemented, + } + }; + + // Register system service event handler + let status_handle = service_control_handler::register(consts::SERVICE_NAME, event_handler)?; + + let running_status = ServiceStatus { + // Should match the one from system service registry + service_type: ServiceType::OWN_PROCESS, + + // The new state + current_state: ServiceState::Running, + + // Accept stop events when running + controls_accepted: ServiceControlAccept::STOP, // | ServiceControlAccept::SHUTDOWN, + + // Used to report an error when starting or stopping only, otherwise must be zero + exit_code: ServiceExitCode::Win32(0), + + // Only used for pending states, otherwise must be zero + checkpoint: 0, + + // Only used for pending states, otherwise must be zero + wait_hint: Duration::default(), + + process_id: None, + }; + + status_handle.set_service_status(running_status)?; + + main_loop::main_loop(completed.clone()); + + status_handle.set_service_status(ServiceStatus { + service_type: ServiceType::OWN_PROCESS, + current_state: ServiceState::Stopped, + controls_accepted: ServiceControlAccept::empty(), + exit_code: ServiceExitCode::Win32(0), + checkpoint: 0, + wait_hint: Duration::default(), + process_id: None, + })?; + + Ok(()) +} + +fn tests() { + println!("Running some tests..."); + + // test_b650_e(); + // list_usb_devices(); + // test_roccat(); + // test_wmi(); + // test_corsair(); + test_a770(); + // test_read_temp(); + + println!("Press any key to continue..."); + std::io::stdin().read_line(&mut String::new()).unwrap(); +} + +fn test_wmi() { + let com_con = COMLibrary::new().unwrap(); + let wmi_con = WMIConnection::new(com_con.into()).unwrap(); + + //let results: Vec> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'").unwrap(); + //let results: Vec> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE 'Intel(R) NF I2C Host Controller'").unwrap(); + let results: Vec> = wmi_con + .raw_query("SELECT * FROM Win32_PnPSignedDriver") + .unwrap(); + //let results: Vec> = wmi_con.raw_query("SELECT * FROM Win32_PnPAllocatedResource").unwrap(); + + for os in results { + println!("-------------------"); + println!("{:#?}", os); + } +} +fn list_usb_devices() { + let api = hidapi::HidApi::new().unwrap(); + for device in api.device_list() { + println!("{:?}", device); + println!("name: {}", device.product_string().unwrap()); + println!("interface number: {}", device.interface_number()); + println!("page: {}", device.usage_page()); + println!("usage: {}", device.usage()); + println!("----"); + } +} + +// fn test_roccat() { +// let api = hidapi::HidApi::new().unwrap(); +// let roccat_device = roccat::get_device(&api); + +// let manufacturer = roccat_device.get_manufacturer_string().unwrap(); +// dbg!(manufacturer); + +// let product = roccat_device.get_product_string().unwrap(); +// dbg!(product); + +// let serial = roccat_device.get_serial_number_string().unwrap(); +// dbg!(serial); + +// roccat::init(&roccat_device); +// roccat::set_color( +// &roccat_device, +// &RGB { +// red: 0, +// green: 255, +// blue: 40, +// }, +// ); +// } + +fn test_b650_e() { + let api = hidapi::HidApi::new().unwrap(); + + let b650e_device = b650_e::get_device(&api); + + println!("Firmware: {}", b650_e::get_firmware_string(&b650e_device)); + + let configuration = b650_e::get_configuration_table(&b650e_device); + println!("Configuration:"); + for i in 0..60 { + print!("{:02X} ", configuration[i]); + if (i + 1) % 6 == 0 { + println!(""); + } + } + + // Only once, at start. + b650_e::set_fixed_mode(&b650e_device); + + b650_e::set_color( + &b650e_device, + &RGB { + red: 255, + green: 0, + blue: 0, + }, + ); + b650_e::save_current_color(&b650e_device); +} + +fn test_corsair() { + let corsair_controllers = [ + corsair_vengeance::Controller::new(0x19), + corsair_vengeance::Controller::new(0x1B), + ]; + for controller in corsair_controllers { + controller.set_color(&RGB { + red: 255, + green: 0, + blue: 0, + }); + } +} + +fn test_a770() { + // a770::set_rgb(255, 0, 0); + let mut a770 = a770::A770::new(); + a770.set_color(255, 0, 0); +} + +fn test_read_temp() { + let sensors = sensors_jiji::Sensors::new(); + println!("temp cpu: {}", sensors.read_cpu_temp()); + println!("temp gpu: {}", sensors.read_gpu_temp()); +} diff --git a/src/main_loop.rs b/src/main_loop.rs new file mode 100644 index 0000000..5c41bb9 --- /dev/null +++ b/src/main_loop.rs @@ -0,0 +1,95 @@ +use std::{ + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::{self, Duration}, +}; + +use crate::{consts, machine, rgb, settings, timer, winring0}; + +pub fn main_loop(completed: Arc) { + if consts::FREQ_REFRESHING_RGB > consts::FREQ_TEMP_POLLING { + panic!("Polling frequency must be greater or equal than RGB refresh frequency"); + } + + if consts::FREQ_TEMP_POLLING % consts::FREQ_REFRESHING_RGB != 0 { + panic!("Polling frequency must be a multiple of RGB refresh frequency"); + } + + init_winring0(); + + let sleep = timer::Sleep::new(); + let settings = settings::Settings::read(consts::FILE_CONF).expect("Cannot load settings"); + println!("Settings: {settings:?}"); + + let mut machine: &mut dyn machine::Machine = &mut machine::MachineJiji::new(); + + let mut kernel = [0f32; consts::KERNEL_SIZE_SAMPLES]; + let mut current_pos = 0usize; + + let mut tick = 0i64; + let period = Duration::from_micros(1_000_000u64 / consts::FREQ_TEMP_POLLING as u64); + + loop { + if completed.load(Ordering::Relaxed) { + break; + } + let time_beginning_loop = time::Instant::now(); + + let temp = (machine.get_cpu_tmp() + machine.get_gpu_tmp()) / 2f32; + kernel[current_pos] = temp; + current_pos = (current_pos + 1) % consts::KERNEL_SIZE_SAMPLES; + let mean_temp = { + let mut s = 0f32; + for t in kernel { + s += t; + } + s / kernel.len() as f32 + }; + + let normalized_temp = num::clamp( + (mean_temp - settings.cold_temperature) + / (settings.hot_temperature - settings.cold_temperature), + 0f32, + 1f32, + ); // Between 0 (cold) and 1 (hot). + + let color = + rgb::linear_interpolation(settings.cold_color, settings.hot_color, normalized_temp); + + // println!("normalized_temp: {normalized_temp}"); + + if tick % (consts::FREQ_TEMP_POLLING / consts::FREQ_REFRESHING_RGB) as i64 == 0 { + println!("Update RGB: {color:?}, temp: {mean_temp}"); + machine.set_color(&color); + } + + let elapsed = time::Instant::now() - time_beginning_loop; + if elapsed < period { + let to_wait = period - elapsed; + sleep.wait(to_wait); + } + tick += 1; + } + + // println!("Press any key to continue..."); + // std::io::stdin().read_line(&mut String::new()).unwrap(); + + unsafe { + winring0::DeinitializeOls(); + } +} + +fn init_winring0() { + unsafe { + let ols_ok = winring0::InitializeOls() != 0; + if !ols_ok { + panic!("Unable to initalize WingRing0"); + } + let dll_status = winring0::GetDllStatus(); + if dll_status != 0 { + panic!("WingRing0 DLL status error: {}", dll_status); + } + } +} diff --git a/src/piix4_i2c.rs b/src/piix4_i2c.rs new file mode 100644 index 0000000..2294a9f --- /dev/null +++ b/src/piix4_i2c.rs @@ -0,0 +1,274 @@ +// Partial implementation for PCI IDE ISA Xcelerator. + +use std::time::Duration; + +use crate::{timer, winring0}; + +pub const I2C_BLOCK_MAX: usize = 32; + +#[repr(u16)] +#[derive(Clone, Copy, Debug)] +enum TransactionType { + I2cSmbusQuick = 0, + I2cSmbusByte = 1, + I2cSmbusByteData = 2, + I2cSmbusWordData = 3, + I2cSmbusProcCall = 4, + I2cSmbusBlockData = 5, + I2cSmbusI2cBlockBroken = 6, + I2cSmbusBlockProcCall = 7, /* SMBus 2.0 */ + I2cSmbusI2cBlockData = 8, +} + +#[repr(u16)] +#[derive(Clone, Copy, Debug)] +enum Piix4TransactionType { + Piix4Quick = 0x00, + Piix4Byte = 0x04, + Piix4ByteData = 0x08, + Piix4WordData = 0x0C, + Piix4BlockData = 0x14, +} + +// PIIX4 SMBus address offsets + +#[repr(u16)] +#[derive(Clone, Copy, Debug)] +enum SMBusAddressOffsets { + Smbhststs = 0, + Smbhslvsts = 1, + Smbhstcnt = 2, + Smbhstcmd = 3, + Smbhstadd = 4, + Smbhstdat0 = 5, + Smbhstdat1 = 6, + Smbblkdat = 7, + Smbslvcnt = 8, + Smbshdwcmd = 9, + Smbslvevt = 0xA, + Smbslvdat = 0xC, +} + +#[repr(u8)] +#[derive(Clone, Copy)] +enum AccessType { + Write = 0, + Read = 1, +} + +pub struct I2c { + base_address: u16, +} + +enum XferResult { + Ok, + BlockData(Vec), +} + +#[derive(Debug)] +enum Error { + Busy, + Timeout, + IO, + Data, +} + +impl I2c { + pub fn new(base_address: u16) -> Self { + I2c { base_address } + } + + pub fn write_block_data(&self, addr: u8, command: u8, data: &[u8]) { + let l = data.len(); + assert!( + l <= I2C_BLOCK_MAX, + "Data length must not exceed {}", + I2C_BLOCK_MAX + ); + let mut data_block = [0u8; I2C_BLOCK_MAX + 2]; + data_block[0] = l as u8; + data_block[1..l + 1].copy_from_slice(&data); + + unsafe { + match self.i2c_smbus_xfer( + addr, + AccessType::Write, + command, + TransactionType::I2cSmbusBlockData, + Some(&data_block), + ) { + Err(error) => println!("Error when writing block (I2c): {error:?}"), + Ok(_) => (), + } + } + } + + pub fn i2c_smbus_write_quick(&self, addr: u8, value: u8) { + unsafe { + self.i2c_smbus_xfer( + addr, + AccessType::Write, + value, + TransactionType::I2cSmbusQuick, + None, + ) + .unwrap(); + } + } + + unsafe fn i2c_smbus_xfer( + &self, + addr: u8, + access_type: AccessType, + command: u8, + transaction_type: TransactionType, // Called 'size' in 'i2c_smbus\i2c_smbus_piix4.cpp'. + data: Option<&[u8]>, + ) -> Result { + let piix4_transaction_type = match transaction_type { + TransactionType::I2cSmbusQuick => { + self.write_io_port_byte( + SMBusAddressOffsets::Smbhstadd, + addr << 1 | access_type as u8, + ); + Piix4TransactionType::Piix4Quick + } + TransactionType::I2cSmbusByte => todo!(), + TransactionType::I2cSmbusByteData => todo!(), // Here 'data' should be a byte, maybe using a enum?. + TransactionType::I2cSmbusWordData => todo!(), // Here 'data' should be a u16, maybe using a enum?. + TransactionType::I2cSmbusBlockData => { + self.write_io_port_byte( + SMBusAddressOffsets::Smbhstadd, + addr << 1 | access_type as u8, + ); + self.write_io_port_byte(SMBusAddressOffsets::Smbhstcmd, command); + if let AccessType::Write = access_type { + let len = data.unwrap()[0]; + if len == 0 || len > I2C_BLOCK_MAX as u8 { + panic!("Invalid len value: {}", len); + } + + self.write_io_port_byte(SMBusAddressOffsets::Smbhstdat0, len); + self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt); // TODO: do something of the result!? + for i in 1..=len { + self.write_io_port_byte( + SMBusAddressOffsets::Smbblkdat, + data.unwrap()[i as usize], + ); + } + } + Piix4TransactionType::Piix4BlockData + } + _ => panic!("Not supported: {:?}", transaction_type), + }; + + self.write_io_port_byte( + SMBusAddressOffsets::Smbhstcnt, + piix4_transaction_type as u8 & 0x1C, + ); + + self.piix4_transaction()?; + + // if let (AccessType::Write, Piix4TransactionType::Piix4Quick) = (access_type, piix4_transaction_type) { + // return Ok(()) + // } + + match piix4_transaction_type { + Piix4TransactionType::Piix4Quick => Ok(XferResult::Ok), + Piix4TransactionType::Piix4Byte => todo!(), + Piix4TransactionType::Piix4ByteData => todo!(), + Piix4TransactionType::Piix4WordData => todo!(), + Piix4TransactionType::Piix4BlockData => { + let l = self.read_io_port_byte(SMBusAddressOffsets::Smbhstdat0) as usize; + if l == 0 || l > I2C_BLOCK_MAX { + return Err(Error::Data); + } + self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt); + let mut data = vec![0; l + 1]; + for i in 1..=l { + data[i] = self.read_io_port_byte(SMBusAddressOffsets::Smbblkdat); + } + return Ok(XferResult::BlockData(data)); + } + } + } + + unsafe fn piix4_transaction(&self) -> Result<(), Error> { + let timer = timer::Sleep::new(); + + // Make sure the SMBus is ready to start transmitting. + let mut res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs); + if res != 0x00 { + self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res); + res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs); + if res != 0x00 { + return Err(Error::Busy); + } + } + + // Start the transaction by setting bit 6. + res = self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt); + self.write_io_port_byte(SMBusAddressOffsets::Smbhstcnt, res | 0x40); + + // let duration: i64 = -2_500; // 250 us. + let mut n = 0; + loop { + timer.wait(Duration::from_micros(250)); + + res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs); + // println!("Res: {}", res); + if res > 0x01 { + break; + } + + if n >= 100 { + return Err(Error::Timeout); + } + n += 1; + } + // println!("-----"); + + if res & 0x10 != 0x00 || res & 0x08 != 0x0 || res & 0x04 != 0x0 { + return Err(Error::IO); + } + + res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs); + if res != 0x00 { + self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res); + } + + return Ok(()); + } + + unsafe fn write_io_port_byte(&self, op: SMBusAddressOffsets, value: u8) { + winring0::WriteIoPortByte(self.base_address + op as u16, value); + } + + unsafe fn read_io_port_byte(&self, op: SMBusAddressOffsets) -> u8 { + winring0::ReadIoPortByte(self.base_address + op as u16) + } +} + +/* +type ADL_MAIN_MALLOC_CALLBACK = unsafe fn(c_int) -> *mut c_void; +type ADL_CONTEXT_HANDLE = *mut c_void; + +type ADL2_MAIN_CONTROL_CREATE = unsafe extern "C" fn(ADL_MAIN_MALLOC_CALLBACK, c_int, *mut ADL_CONTEXT_HANDLE) -> c_int; +type ADL2_MAIN_CONTROL_DESTROY = unsafe extern "C" fn(ADL_CONTEXT_HANDLE) -> c_int; +type ADL2_ADAPTER_NUMBEROFADAPTERS_GET = unsafe extern "C" fn(ADL_CONTEXT_HANDLE, *mut c_int) -> c_int; + +pub fn test() { + unsafe { + let hDLL = LoadLibraryW(w!("atiadlxx.dll")).unwrap(); + println!("{:?}", hDLL); + + let ADL2_Main_Control_Create: ADL2_MAIN_CONTROL_CREATE = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Create")).unwrap()); + let ADL2_Main_Control_Destroy: ADL2_MAIN_CONTROL_DESTROY = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Destroy")).unwrap()); + let ADL2_Adapter_NumberOfAdapters_Get: ADL2_ADAPTER_NUMBEROFADAPTERS_GET = transmute(&GetProcAddress(hDLL, s!("ADL2_Adapter_NumberOfAdapters_Get")).unwrap()); + + + let m: *mut c_void = libc::malloc(4); + + + } +} +*/ diff --git a/src/rgb.rs b/src/rgb.rs new file mode 100644 index 0000000..de1161a --- /dev/null +++ b/src/rgb.rs @@ -0,0 +1,17 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] +pub struct RGB { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +// 'value' is between 0 and 1. +pub fn linear_interpolation(color1: RGB, color2: RGB, value: f32) -> RGB { + let red = (color1.red as f32 + (color2.red as f32 - color1.red as f32) * value) as u8; + let green = (color1.green as f32 + (color2.green as f32 - color1.green as f32) * value) as u8; + let blue = (color1.blue as f32 + (color2.blue as f32 - color1.blue as f32) * value) as u8; + + RGB { red, green, blue } +} diff --git a/src/roccat.rs b/src/roccat.rs new file mode 100644 index 0000000..d80b9fe --- /dev/null +++ b/src/roccat.rs @@ -0,0 +1,61 @@ +use crate::common::*; + +const VID: u16 = 0x1E7D; +const PID: u16 = 0x2E2C; +const INTERFACE: i32 = 0x00; +const PAGE: u16 = 0x0B; +const USAGE: u16 = 0x00; + +pub fn get_device(api: &hidapi::HidApi) -> hidapi::HidDevice { + let device_info = api + .device_list() + .find(|device| { + device.vendor_id() == VID + && device.product_id() == PID + && device.interface_number() == INTERFACE + && device.usage_page() == PAGE + && device.usage() == USAGE + }) + .unwrap(); + device_info.open_device(&api).unwrap() +} + +pub fn init(device: &hidapi::HidDevice) { + let mut buffer = [0u8; 6]; + + buffer[0x00] = 0x0E; + buffer[0x01] = 0x06; + buffer[0x02] = 0x01; + buffer[0x03] = 0x01; + buffer[0x04] = 0x00; + buffer[0x05] = 0xFF; + + device + .send_feature_report(&buffer) + .expect("Cannot send feature report during init"); +} + +pub fn set_color(device: &hidapi::HidDevice, color: &RGB) { + let mut buffer = [0u8; 46]; + buffer[0] = 0x0D; + buffer[1] = 0x2E; + + /* + * Leds: + * 0: Scroll wheel. + * 1-4: Strip left. + * 5-8: Strip right. + * 9: Lower left. + * 10: Lower right. + */ + for i in 0..=10 { + let offset = i * 4 + 2; + buffer[offset] = color.red; + buffer[offset + 1] = color.green; + buffer[offset + 2] = color.blue; + } + + device + .send_feature_report(&buffer) + .expect("Cannot send feature report during set color"); +} diff --git a/src/sensors_jiji.rs b/src/sensors_jiji.rs new file mode 100644 index 0000000..5e57005 --- /dev/null +++ b/src/sensors_jiji.rs @@ -0,0 +1,57 @@ +use crate::{intel_arc, winring0}; + +const OLS_TYPE: u32 = 40000; + +const F17H_M01H_THM_TCON_CUR_TMP: u32 = 0x00059800; +const F17H_TEMP_OFFSET_FLAG: u32 = 0x80000; +const FAMILY_17H_PCI_CONTROL_REGISTER: u32 = 0x60; + +pub struct Sensors { + gpu_devices: intel_arc::Devices, +} + +impl Sensors { + pub fn new() -> Self { + unsafe { + Sensors { + gpu_devices: intel_arc::GetDevices(), + } + } + } + + pub fn read_cpu_temp(&self) -> f32 { + unsafe { + winring0::WritePciConfigDwordEx( + 0x00, + FAMILY_17H_PCI_CONTROL_REGISTER, + F17H_M01H_THM_TCON_CUR_TMP, + ); + + let output: &mut u32 = &mut 0; + let ok = + winring0::ReadPciConfigDwordEx(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, output); + let offset_flag = *output & F17H_TEMP_OFFSET_FLAG != 0; + let mut temperature = ((*output >> 21) * 125) as f32 * 0.001; + if offset_flag { + temperature -= 49.; + } + + // dbg!(ok); + // dbg!(temperature); + + temperature + } + } + + pub fn read_gpu_temp(&self) -> f32 { + unsafe { intel_arc::GetTemperature(self.gpu_devices, 0) as f32 } + } +} + +impl Drop for Sensors { + fn drop(&mut self) { + unsafe { + intel_arc::FreeDevices(self.gpu_devices); + } + } +} diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..9939178 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,59 @@ +use std::fs::File; + +use ron::{ + de::from_reader, + ser::{to_writer_pretty, PrettyConfig}, +}; +use serde::{Deserialize, Serialize}; + +use crate::rgb::RGB; + +#[derive(Debug, Deserialize, Serialize)] +pub enum MachineName { + Jiji, + LyssMetal, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct Settings { + pub machine_name: MachineName, + pub cold_color: RGB, + pub hot_color: RGB, + // Average temperature between CPU and GPU. + pub cold_temperature: f32, + pub hot_temperature: f32, +} + +type Result = std::result::Result>; + +impl Settings { + fn default() -> Self { + Settings { + machine_name: MachineName::Jiji, + cold_color: RGB { + red: 0, + green: 255, + blue: 40, + }, + hot_color: RGB { + red: 255, + green: 0, + blue: 0, + }, + cold_temperature: 55., + hot_temperature: 75., + } + } + + pub fn read(file_path: &str) -> Result { + match File::open(file_path) { + Ok(file) => from_reader(file).map_err(|e| e.into()), + Err(_) => { + let file = File::create(file_path)?; + let default_config = Settings::default(); + to_writer_pretty(file, &default_config, PrettyConfig::new())?; + Ok(default_config) + } + } + } +} diff --git a/src/timer.rs b/src/timer.rs new file mode 100644 index 0000000..b44e0fb --- /dev/null +++ b/src/timer.rs @@ -0,0 +1,31 @@ +use std::time::Duration; + +use windows::Win32::{Foundation::HANDLE, System::Threading::*}; + +pub struct Sleep { + timer_handle: HANDLE, +} + +impl Sleep { + pub fn new() -> Self { + unsafe { + Sleep { + timer_handle: CreateWaitableTimerExW( + None, + windows::core::PCWSTR::null(), + CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, + TIMER_ALL_ACCESS.0, + ) + .unwrap(), + } + } + } + + pub fn wait(&self, d: Duration) { + let time = d.as_micros() as i64 * -10; + unsafe { + SetWaitableTimer(self.timer_handle, &time, 0, None, None, false).unwrap(); + WaitForSingleObject(self.timer_handle, INFINITE); + } + } +} diff --git a/winring0/OlsApi.h b/winring0/OlsApi.h new file mode 100644 index 0000000..81ebdfd --- /dev/null +++ b/winring0/OlsApi.h @@ -0,0 +1,638 @@ +//----------------------------------------------------------------------------- +// Author : hiyohiyo +// Mail : hiyohiyo@crystalmark.info +// Web : http://openlibsys.org/ +// License : The modified BSD license +// +// Copyright 2007-2009 OpenLibSys.org. All rights reserved. +//----------------------------------------------------------------------------- +// for WinRing0 1.3.x + +#pragma once + +typedef unsigned char BYTE; +typedef BYTE *PBYTE; +typedef int BOOL; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef WORD *PWORD; +typedef DWORD *PDWORD; +typedef unsigned __int64 ULONG_PTR; +typedef ULONG_PTR DWORD_PTR; +typedef DWORD_PTR *PDWORD_PTR; + +#define WINAPI __stdcall +#define VOID void + +/****************************************************************************** +** +** DLL Information +** +******************************************************************************/ + +//----------------------------------------------------------------------------- +// GetDllStatus +//----------------------------------------------------------------------------- +DWORD // DLL Status, defined OLS_DLL_**** +WINAPI GetDllStatus(); + +//----------------------------------------------------------------------------- +// GetDllVersion +//----------------------------------------------------------------------------- +DWORD // DLL Version, defined OLS_VERSION +WINAPI GetDllVersion( + PBYTE major, // major version + PBYTE minor, // minor version + PBYTE revision, // revision + PBYTE release // release/build +); + +//----------------------------------------------------------------------------- +// GetDriverVersion +//----------------------------------------------------------------------------- +DWORD // Device Driver Version, defined OLS_DRIVER_VERSION +WINAPI GetDriverVersion( + PBYTE major, // major version + PBYTE minor, // minor version + PBYTE revision, // revision + PBYTE release // release/build +); + +//----------------------------------------------------------------------------- +// GetDriverType +//----------------------------------------------------------------------------- +DWORD // Device Driver Type, defined OLS_DRIVER_TYPE_**** +WINAPI GetDriverType(); + +//----------------------------------------------------------------------------- +// InitializeOls +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI InitializeOls(); + +//----------------------------------------------------------------------------- +// DeinitializeOls +//----------------------------------------------------------------------------- +VOID WINAPI DeinitializeOls(); + +/****************************************************************************** +** +** CPU +** +******************************************************************************/ + +//----------------------------------------------------------------------------- +// IsCpuid +//----------------------------------------------------------------------------- +BOOL // TRUE: support CPUID instruction, FALSE: not support CPUID instruction +WINAPI IsCpuid(); + +//----------------------------------------------------------------------------- +// IsMsr +//----------------------------------------------------------------------------- +BOOL // TRUE: support MSR(Model-Specific Register), FALSE: not support MSR +WINAPI IsMsr(); + +//----------------------------------------------------------------------------- +// IsTsc +//----------------------------------------------------------------------------- +BOOL // TRUE: support TSC(Time Stamp Counter), FALSE: not support TSC +WINAPI IsTsc(); + +//----------------------------------------------------------------------------- +// Rdmsr +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Rdmsr( + DWORD index, // MSR index + PDWORD eax, // bit 0-31 + PDWORD edx // bit 32-63 +); + +//----------------------------------------------------------------------------- +// RdmsrTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdmsrTx( + DWORD index, // MSR index + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// RdmsrPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdmsrPx( + DWORD index, // MSR index + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR processAffinityMask +); + +//----------------------------------------------------------------------------- +// Wrmsr +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Wrmsr( + DWORD index, // MSR index + DWORD eax, // bit 0-31 + DWORD edx // bit 32-63 +); + +//----------------------------------------------------------------------------- +// WrmsrTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WrmsrTx( + DWORD index, // MSR index + DWORD eax, // bit 0-31 + DWORD edx, // bit 32-63 + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// WrmsrPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WrmsrPx( + DWORD index, // MSR index + DWORD eax, // bit 0-31 + DWORD edx, // bit 32-63 + DWORD_PTR processAffinityMask +); + +//----------------------------------------------------------------------------- +// Rdpmc +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Rdpmc( + DWORD index, // PMC index + PDWORD eax, // bit 0-31 + PDWORD edx // bit 32-63 +); + +//----------------------------------------------------------------------------- +// RdmsrTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdpmcTx( + DWORD index, // PMC index + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// RdmsrPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdpmcPx( + DWORD index, // PMC index + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR processAffinityMask +); + +//----------------------------------------------------------------------------- +// Cpuid +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Cpuid( + DWORD index, // CPUID index + PDWORD eax, + PDWORD ebx, + PDWORD ecx, + PDWORD edx +); + +//----------------------------------------------------------------------------- +// CpuidTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI CpuidTx( + DWORD index, // CPUID index + PDWORD eax, + PDWORD ebx, + PDWORD ecx, + PDWORD edx, + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// CpuidPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI CpuidPx( + DWORD index, // CPUID index + PDWORD eax, + PDWORD ebx, + PDWORD ecx, + PDWORD edx, + DWORD_PTR processAffinityMask +); + +//----------------------------------------------------------------------------- +// Rdtsc +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Rdtsc( + PDWORD eax, // bit 0-31 + PDWORD edx // bit 32-63 +); + +//----------------------------------------------------------------------------- +// RdmsrTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdtscTx( + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// RdmsrPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI RdtscPx( + PDWORD eax, // bit 0-31 + PDWORD edx, // bit 32-63 + DWORD_PTR processAffinityMask +); + +//----------------------------------------------------------------------------- +// Hlt +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI Hlt(); + +//----------------------------------------------------------------------------- +// HltTx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI HltTx( + DWORD_PTR threadAffinityMask +); + +//----------------------------------------------------------------------------- +// HltPx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI HltTx( + DWORD_PTR processAffinityMask +); + +/****************************************************************************** +** +** I/O +** +******************************************************************************/ + +//----------------------------------------------------------------------------- +// ReadIoPortByte +//----------------------------------------------------------------------------- +BYTE // Read Value +WINAPI ReadIoPortByte( + WORD port // I/O port address +); + +//----------------------------------------------------------------------------- +// ReadIoPortWord +//----------------------------------------------------------------------------- +WORD // Read Value +WINAPI ReadIoPortWord( + WORD port // I/O port address +); + +//----------------------------------------------------------------------------- +// ReadIoPortDword +//----------------------------------------------------------------------------- +DWORD // Read Value +WINAPI ReadIoPortDword( + WORD port // I/O port address +); + +//----------------------------------------------------------------------------- +// ReadIoPortByteEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadIoPortByteEx( + WORD port, // I/O port address + PBYTE value // Read Value +); +//----------------------------------------------------------------------------- +// ReadIoPortWordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadIoPortWordEx( + WORD port, // I/O port address + PWORD value // Read Value +); +//----------------------------------------------------------------------------- +// ReadIoPortDwordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadIoPortDwordEx( + WORD port, // I/O port address + PDWORD value // Read Value +); + +//----------------------------------------------------------------------------- +// WriteIoPortByte +//----------------------------------------------------------------------------- +VOID +WINAPI WriteIoPortByte( + WORD port, // I/O port address + BYTE value // Write Value +); + +//----------------------------------------------------------------------------- +// WriteIoPortDword +//----------------------------------------------------------------------------- +VOID +WINAPI WriteIoPortDword( + WORD port, // I/O port address + DWORD value // Write Value +); + + +//----------------------------------------------------------------------------- +// WriteIoPortWord +//----------------------------------------------------------------------------- +VOID +WINAPI WriteIoPortWord( + WORD port, // I/O port address + WORD value // Write Value +); + +//----------------------------------------------------------------------------- +// WriteIoPortByteEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WriteIoPortByteEx( + WORD port, // I/O port address + BYTE value // Write Value +); + +//----------------------------------------------------------------------------- +// WriteIoPortWordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WriteIoPortWordEx( + WORD port, // I/O port address + WORD value // Write Value +); + + +//----------------------------------------------------------------------------- +// WriteIoPortDwordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WriteIoPortDwordEx( + WORD port, // I/O port address + DWORD value // Write Value +); + +/****************************************************************************** +** +** PCI +** +******************************************************************************/ +// pciAddress +// 0- 2: Function Number +// 3- 7: Device Number +// 8-15: PCI Bus Number +// 16-31: Reserved +// 0xFFFFFFFF : Error + +//----------------------------------------------------------------------------- +// SetPciMaxBusNo +//----------------------------------------------------------------------------- +VOID +WINAPI SetPciMaxBusIndex( + BYTE max // Max PCI Bus to Scan +); + +//----------------------------------------------------------------------------- +// ReadPciConfigByte +//----------------------------------------------------------------------------- +BYTE // Read Value +WINAPI ReadPciConfigByte( + DWORD pciAddress, // PCI Device Address + BYTE regAddress // Configuration Address 0-255 +); + +//----------------------------------------------------------------------------- +// ReadPciConfigWord +//----------------------------------------------------------------------------- +WORD // Read Value +WINAPI ReadPciConfigWord( + DWORD pciAddress, // PCI Device Address + BYTE regAddress // Configuration Address 0-255 +); + +//----------------------------------------------------------------------------- +// ReadPciConfigDword +//----------------------------------------------------------------------------- +DWORD // Read Value +WINAPI ReadPciConfigDword( + DWORD pciAddress, // PCI Device Address + BYTE regAddress // Configuration Address 0-255 +); + +//----------------------------------------------------------------------------- +// ReadPciConfigPByte +//----------------------------------------------------------------------------- +BOOL // Read Value +WINAPI ReadPciConfigPByte( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + PBYTE value, // Read Value + DWORD size +); + +//----------------------------------------------------------------------------- +// ReadPciConfigByteEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadPciConfigByteEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + PBYTE value // Read Value +); + +//----------------------------------------------------------------------------- +// ReadPciConfigWordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadPciConfigWordEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + PWORD value // Read Value +); + +//----------------------------------------------------------------------------- +// ReadPciConfigDwordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadPciConfigDwordEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + PDWORD value // Read Value +); + +//----------------------------------------------------------------------------- +// ReadPciConfigPByteEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI ReadPciConfigPByteEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + PBYTE value, // Read Value + DWORD size +); + +//----------------------------------------------------------------------------- +// WritePciConfigByte +//----------------------------------------------------------------------------- +VOID +WINAPI WritePciConfigByte( + DWORD pciAddress, // PCI Device Address + BYTE regAddress, // Configuration Address 0-255 + BYTE value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigWord +//----------------------------------------------------------------------------- +VOID +WINAPI WritePciConfigWord( + DWORD pciAddress, // PCI Device Address + BYTE regAddress, // Configuration Address 0-255 + WORD value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigDword +//----------------------------------------------------------------------------- +VOID +WINAPI WritePciConfigDword( + DWORD pciAddress, // PCI Device Address + BYTE regAddress, // Configuration Address 0-255 + DWORD value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigPByte +//----------------------------------------------------------------------------- +VOID +WINAPI WritePciConfigPByte( + DWORD pciAddress, // PCI Device Address + BYTE regAddress, // Configuration Address 0-255 + PBYTE value, // Write Value + DWORD size +); + +//----------------------------------------------------------------------------- +// WritePciConfigByteEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WritePciConfigByteEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + BYTE value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigWordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WritePciConfigWordEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + WORD value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigDwordEx +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WritePciConfigDwordEx( + DWORD pciAddress, // PCI Device Address + DWORD regAddress, // Configuration Address 0-whatever + DWORD value // Write Value +); + +//----------------------------------------------------------------------------- +// WritePciConfigPByte +//----------------------------------------------------------------------------- +BOOL // TRUE: success, FALSE: failure +WINAPI WritePciConfigPByteEx( + DWORD pciAddress, // PCI Device Address + BYTE regAddress, // Configuration Address 0-255 + PBYTE value, // Write Value + DWORD size +); + +//----------------------------------------------------------------------------- +// FindPciDeviceById +//----------------------------------------------------------------------------- +DWORD // pciAddress, 0xFFFFFFFF: failure +WINAPI FindPciDeviceById( + WORD vendorId, // Vendor ID + WORD deviceId, // Device ID + BYTE index // Index +); + +//----------------------------------------------------------------------------- +// FindPciDeviceByClass +//----------------------------------------------------------------------------- +DWORD // pciAddress, 0xFFFFFFFF: failure +WINAPI FindPciDeviceByClass( + BYTE baseClass, // Base Class + BYTE subClass, // Sub Class + BYTE programIf, // Program Interface + BYTE index // Index +); + +/****************************************************************************** +** +** Memory (Special API) +** +******************************************************************************/ + +#ifdef _PHYSICAL_MEMORY_SUPPORT +//----------------------------------------------------------------------------- +// ReadDmiMemory +//----------------------------------------------------------------------------- +DWORD // Read size(byte), 0: failure +WINAPI ReadDmiMemory( + PBYTE buffer, // Buffer + DWORD count, // Count + DWORD unitSize // Unit Size (BYTE, WORD, DWORD) +); + +//----------------------------------------------------------------------------- +// ReadPhysicalMemory +//----------------------------------------------------------------------------- +DWORD // Read size(byte), 0: failure +WINAPI ReadPhysicalMemory( + DWORD_PTR address, // Physical Memory Address + PBYTE buffer, // Buffer + DWORD count, // Count + DWORD unitSize // Unit Size (BYTE, WORD, DWORD) +); + +//----------------------------------------------------------------------------- +// WritePhysicalMemory +//----------------------------------------------------------------------------- +DWORD // Write size(byte), 0: failure +WINAPI WritePhysicalMemory( + DWORD_PTR address, // Physical Memory Address + PBYTE buffer, // Buffer + DWORD count, // Count + DWORD unitSize // Unit Size (BYTE, WORD, DWORD) +); +#endif \ No newline at end of file diff --git a/winring0/WinRing0x64.dll b/winring0/WinRing0x64.dll new file mode 100644 index 0000000000000000000000000000000000000000..2027ee6706702c9f6f840ce5bc6e34b412ec0606 GIT binary patch literal 29696 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 literal 0 HcmV?d00001 -- 2.45.2