From e4a819913a3db33ef35b4f53e1feebfddbcfefa8 Mon Sep 17 00:00:00 2001 From: k1-801 Date: Wed, 9 Sep 2020 16:04:30 +0400 Subject: [PATCH] ASUS TUF Aura Core port (WMI) Commit amended to move files to Windows-specific section of Qt project by Adam Honse --- .../AsusTUFLaptopWMIDetect.cpp | 48 +++ .../RGBController_AsusTUFLaptopWMI.cpp | 142 +++++++++ .../RGBController_AsusTUFLaptopWMI.h | 29 ++ .../RGBController_Faustus.cpp | 7 +- OpenRGB.pro | 6 + wmi/acpiwmi.cpp | 278 ++++++++++++++++++ wmi/acpiwmi.h | 17 ++ 7 files changed, 522 insertions(+), 5 deletions(-) create mode 100644 Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp create mode 100644 Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp create mode 100644 Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h create mode 100644 wmi/acpiwmi.cpp create mode 100644 wmi/acpiwmi.h diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp new file mode 100644 index 00000000..04077a92 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp @@ -0,0 +1,48 @@ +#ifdef _WIN32 + +#include "RGBController_AsusTUFLaptopWMI.h" + +#include "acpiwmi.h" +#include "Detector.h" +#include "wmi.h" +#include + +static void DetectAsusTUFLaptopWMIControllers(std::vector&) +{ + // Try to retrieve ProductID / Device name from WMI; Possibly can be rewritten to use wmi.cpp + // IF you encounter false detection ( e.g. if your laptop keyboard backlight uses USB interface + // instead of ACPI WMI) please add a WHITELIST by checking the + // `name` variable for model substrings like "FX505DU" + // For now, checking for "TUF Gaming" should suffice + + Wmi wmi; + wmi.init(); + + std::vector systemProduct; + if (wmi.query("SELECT * FROM Win32_ComputerSystemProduct", systemProduct)) + { + return; + } + + // There should only be one, a cycle is a precaution + if(systemProduct.size() != 1) + { + return; + } + std::string& name = systemProduct[0]["Name"]; + if(name.find("TUF Gaming") == name.npos) + { + return; + } + + if(AsWMI_Open()) + { + RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(); + ResourceManager::get()->RegisterRGBController(new_controller); + // Success! No more if's + } +} /* DetectFaustusControllers() */ + +REGISTER_DETECTOR("TUF Laptop WMI", DetectAsusTUFLaptopWMIControllers); + +#endif diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp new file mode 100644 index 00000000..272da4c9 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp @@ -0,0 +1,142 @@ +#ifdef _WIN32 + +#include "RGBController_AsusTUFLaptopWMI.h" + +#include "acpiwmi.h" +#include "ResourceManager.h" +#include "Detector.h" +#include "wmi.h" +#include + +using namespace std::chrono_literals; + +RGBController_AsusTUFLaptopWMI::RGBController_AsusTUFLaptopWMI() +{ + name = "ASUS TUF Keyboard"; + type = DEVICE_TYPE_KEYBOARD; + description = "WMI Device"; + location = "\\\\.\\ATKACPI"; + + modes.resize(5); + modes[0].name = "Direct"; + modes[0].value = 4; + modes[0].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[0].color_mode = MODE_COLORS_PER_LED; + + modes[1].name = "Static"; + modes[1].value = 0; + modes[1].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[1].color_mode = MODE_COLORS_PER_LED; + + modes[2].name = "Breathing"; + modes[2].value = 1; + modes[2].flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + modes[2].speed_min = 0; + modes[2].speed_max = 2; + modes[2].color_mode = MODE_COLORS_PER_LED; + modes[2].speed = 1; + + modes[3].name = "Color Cycle"; + modes[3].value = 2; + modes[3].flags = MODE_FLAG_HAS_SPEED; + modes[3].speed_min = 0; + modes[3].speed_max = 2; + modes[3].color_mode = MODE_COLORS_NONE; + modes[3].speed = 1; + + modes[4].name = "Strobe"; + modes[4].value = 0x0A; + modes[4].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[4].color_mode = MODE_COLORS_PER_LED; + + SetupZones(); +} + +RGBController_AsusTUFLaptopWMI::~RGBController_AsusTUFLaptopWMI() +{ + AsWMI_Close(); +} + +void RGBController_AsusTUFLaptopWMI::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zones.resize(1); + zones[0].type = ZONE_TYPE_SINGLE; + zones[0].name = "Keyboard Backlight zone"; + zones[0].leds_min = 1; + zones[0].leds_max = 1; + zones[0].leds_count = 1; + zones[0].matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + leds.resize(1); + leds[0].name = "Keyboard Backlight LED"; + + SetupColors(); +} + +void RGBController_AsusTUFLaptopWMI::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AsusTUFLaptopWMI::DeviceUpdateLEDs() +{ + uint8_t red = RGBGetRValue(colors[0]); + uint8_t green = RGBGetGValue(colors[0]); + uint8_t blue = RGBGetBValue(colors[0]); + uint8_t speed_byte = 0; + uint8_t mode = modes[active_mode].value; + uint8_t inv = 0; + if(mode == 4) + { + mode = 1; + inv = 4; // Any invalid mode, i.e. anything other than 0, 1, 2 and 10 + } + if(mode == 1 || mode == 2) + { + switch(modes[active_mode].speed) + { + case 0: speed_byte = 0xE1; break; + case 1: speed_byte = 0xEB; break; + case 2: speed_byte = 0xF5; break; + } + } + int high = ((mode | ((red | (green << 8)) << 8)) << 8) | 0xB3; + int low = blue | (speed_byte << 8); + AsWMI_NB_DeviceControl_2arg(0x100056, high, low); + if(inv) + { + //std::this_thread::sleep_for(10ms); + high = ((inv | ((red | (green << 8)) << 8)) << 8) | 0xB3; + AsWMI_NB_DeviceControl_2arg(0x100056, high, low); + } +} + +void RGBController_AsusTUFLaptopWMI::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusTUFLaptopWMI::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusTUFLaptopWMI::SetCustomMode() +{ + SetMode(0); +} + +void RGBController_AsusTUFLaptopWMI::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +#endif diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h new file mode 100644 index 00000000..611e5d9d --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h @@ -0,0 +1,29 @@ +#ifndef RGBCONTROLLER_ASUSTUFLAPTOPWMI_H +#define RGBCONTROLLER_ASUSTUFLAPTOPWMI_H + +#ifdef _WIN32 + +#include "RGBController.h" + +class RGBController_AsusTUFLaptopWMI : public RGBController +{ +public: + RGBController_AsusTUFLaptopWMI(); + virtual ~RGBController_AsusTUFLaptopWMI(); + + void SetupZones() override; + + void ResizeZone(int zone, int new_size) override; + + void DeviceUpdateLEDs() override; + void UpdateZoneLEDs(int zone) override; + void UpdateSingleLED(int led) override; + + void DeviceUpdateMode() override; + + void SetCustomMode() override; +}; + +#endif + +#endif // RGBCONTROLLER_ASUSTUFLAPTOPWMI_H diff --git a/Controllers/FaustusController/RGBController_Faustus.cpp b/Controllers/FaustusController/RGBController_Faustus.cpp index a8a476c3..a6874735 100644 --- a/Controllers/FaustusController/RGBController_Faustus.cpp +++ b/Controllers/FaustusController/RGBController_Faustus.cpp @@ -33,11 +33,8 @@ RGBController_Faustus::RGBController_Faustus(const std::string& dev_path) modes[3].name = "Strobe"; modes[3].value = FAUSTUS_MODE_STROBE; - modes[3].flags = MODE_FLAG_HAS_SPEED; - modes[3].speed_min = FAUSTUS_SPEED_SLOWEST; - modes[3].speed_max = FAUSTUS_SPEED_FASTEST; - modes[3].color_mode = MODE_COLORS_NONE; - modes[3].speed = FAUSTUS_SPEED_NORMAL; + modes[3].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[3].color_mode = MODE_COLORS_PER_LED; SetupZones(); diff --git a/OpenRGB.pro b/OpenRGB.pro index a9966271..75a2199f 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -524,6 +524,7 @@ win32:INCLUDEPATH += dependencies/NVFC \ dependencies/openrazer-win32 \ wmi/ \ + Controllers/AsusTUFLaptopController \ win32:SOURCES += \ # dependencies/hidapi/hidapi.c \ @@ -535,6 +536,9 @@ win32:SOURCES += i2c_smbus/i2c_smbus_piix4.cpp \ serial_port/find_usb_serial_port_win.cpp \ wmi/wmi.cpp \ + wmi/acpiwmi.cpp \ + Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp \ + Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp \ Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp \ Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp \ @@ -549,6 +553,8 @@ win32:HEADERS += i2c_smbus/i2c_smbus_nvapi.h \ i2c_smbus/i2c_smbus_piix4.h \ wmi/wmi.h \ + wmi/acpiwmi.h \ + Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h \ Controllers/OpenRazerController/RGBController_OpenRazerWindows.h \ win32:contains(QMAKE_TARGET.arch, x86_64) { diff --git a/wmi/acpiwmi.cpp b/wmi/acpiwmi.cpp new file mode 100644 index 00000000..6a1c0eeb --- /dev/null +++ b/wmi/acpiwmi.cpp @@ -0,0 +1,278 @@ +#ifdef _WIN32 + +#include +#include +#include +#include +#include + +#include +#include +#include + +static bool IsWOW64 = false; +static HANDLE hDevice = 0; +static bool WMI_Notebook = 0; +static bool coInitialized = 0; + +static GUID CLSID_GUID_DEVCLASS_SYSTEM = { 0x4D36E97D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } }; + +static int CheckWMIType() +{ + int n; + signed int v3; + int v4; + signed int v5; + int v6; + int result; + struct _SP_DEVINFO_DATA DeviceInfoData; + wchar_t PropertyBuffer[260]; + + HDEVINFO devinfo = SetupDiGetClassDevsW(&CLSID_GUID_DEVCLASS_SYSTEM, 0, 0, 2u); + if ( devinfo == HDEVINFO(-1) ) + { + return 0; + } + n = 0; + DeviceInfoData.cbSize = sizeof(DeviceInfoData); + v3 = 1; + result = 0; + while ( SetupDiEnumDeviceInfo(devinfo, n, &DeviceInfoData) ) // Invalid buffer + { + if ( !SetupDiGetDeviceRegistryPropertyW(devinfo, &DeviceInfoData, 0x16u, 0, PBYTE(PropertyBuffer), 0x208u, 0) ) + { + v5 = 0; + v4 = wcscmp(PropertyBuffer, L"ACPI"); + if ( v4 ) + { + v4 = -(v4 < 0) | 1; + v5 = 0; + } + else + { + v5 = 1; + } + } + if ( v5 ) + { + memset(PropertyBuffer, 0, 0x208u); + if ( SetupDiGetDeviceInstanceIdW(devinfo, &DeviceInfoData, PropertyBuffer, 0x104u, 0) ) + { + _wcsupr_s(PropertyBuffer, 0x104u); + if ( wcsstr(PropertyBuffer, L"ACPI\\ATK0100") ) + { + result = 1; + break; + } + v6 = wcscmp(PropertyBuffer, L"ACPI\\PNP0C14\\ATK"); + if ( v6 ) + v6 = -(v6 < 0) | 1; + if ( !v6 ) + { + result = 2; + v3 = 0; + } + } + } + ++n; + if ( !v3 ) + break; + } + SetupDiDestroyDeviceInfoList(devinfo); + return result; +} + +static bool OpenNotebook() +{ + HMODULE kernelHandler; // eax + void (__stdcall *IsWow64Process)(HANDLE, int *); // esi + int wow64; // [esp+4h] [ebp-4h] + + wow64 = 0; + kernelHandler = GetModuleHandleW(L"kernel32"); + IsWow64Process = (void (__stdcall *)(HANDLE, int *))GetProcAddress(kernelHandler, "IsWow64Process"); + if ( IsWow64Process ) + { + int iswow; + IsWow64Process(GetCurrentProcess(), &iswow); + IsWOW64 = iswow; + } + hDevice = CreateFileW(L"\\\\.\\ATKACPI", 0xC0000000, 3u, 0, 3u, 0, 0); + return (hDevice != HANDLE(-1)); +} + +bool AsWMI_Open() +{ + HRESULT init = CoInitializeEx(0, 2u); + if ( init < 0 && init != -2147417850 ) + return 0; + coInitialized = 1; + int type = CheckWMIType(); + if ( type == 2 ) + { + OpenNotebook(); + WMI_Notebook = 1; + return 1; + } + return 0; +} + +void AsWMI_Close() +{ + if ( WMI_Notebook ) + { + if ( hDevice && hDevice != (HANDLE)-1 ) + { + CloseHandle(hDevice); + hDevice = 0; + } + } + if ( coInitialized ) + { + CoUninitialize(); + coInitialized = 0; + } + +} + +static bool DeviceIoControlWrapper(const void *dataIn, int commandIndex, int dataSizeIn, void *dataOut, int *dataSizeOut) +{ + size_t BytesReturned; + char OutBuffer[1024]; + + LPDWORD inBuffer = (LPDWORD)(malloc(dataSizeIn + 8)); + inBuffer[0] = commandIndex; + inBuffer[1] = dataSizeIn; + memmove(inBuffer + 2, dataIn, dataSizeIn); + memset(OutBuffer, 0, 0x400u); + BytesReturned = 0; + bool result = DeviceIoControl( + hDevice, + 0x22240Cu, + inBuffer, + dataSizeIn + 8, + OutBuffer, + 0x400u, + LPDWORD(&BytesReturned), + 0); + if ( result ) + { + if ( *dataSizeOut < BytesReturned ) + BytesReturned = *dataSizeOut; + memmove(dataOut, OutBuffer, BytesReturned); + } + free(inBuffer); + return result; +} + +bool AsWMI_NB_DeviceControl(int a1, int a2) +{ + unsigned int data[2]; + + if ( WMI_Notebook ) + { + if ( hDevice ) + { + if ( hDevice != (HANDLE)-1 ) + { + data[0] = a1; + data[1] = a2; + int result; + int outBufSize = 4; + if ( DeviceIoControlWrapper(&data, 1398162756, 8, &result, &outBufSize) ) + { + if(outBufSize < 4) + { + result = 0; + } + if ( result == 1 ) + { + return 1; + } + } + } + } + } + return 0; +} + +bool AsWMI_NB_DeviceControl_2arg(int a1, int a2, int a3) +{ + unsigned int data[3]; + data[0] = a1; + data[1] = a2; + data[2] = a3; + int outBuf; + int outBufSize = 4; + + if ( WMI_Notebook ) + { + if ( hDevice ) + { + if ( hDevice != (HANDLE)-1 ) + { + if ( DeviceIoControlWrapper(data, 0x53564544, 12, &outBuf, &outBufSize) ) + { + if(outBufSize < 4) + { + outBuf = 0; + } + if ( outBuf == 1 ) + { + return 1; + } + } + } + } + } + return 0; +} + +char AsWMI_NB_GetDeviceStatus(int a1, int *out) +{ + int status; + int statusSize = 4; + + if ( !WMI_Notebook ) + { + return 0; + } + if ( !hDevice || hDevice == HANDLE(-1) || (!DeviceIoControlWrapper(&a1, 1398035268, 4, &status, &statusSize)) ) + { + return 0; + } + if(statusSize < 4) + { + status = 0; + } + *out = status; + return 1; +} + +bool AsWMI_NB_GetDeviceStatus_MoreBYTE(int a1, int a2, int *status1, int *status2, int* status3) +{ + if ( !WMI_Notebook ) + { + return 0; + } + int commandData[2]; + commandData[0] = a1; + commandData[1] = a2; + int statusBuffer[3]; + int statusSize = 12; + if ( hDevice + && hDevice != HANDLE(-1) + && DeviceIoControlWrapper(commandData, 1398035268, 8, statusBuffer, &statusSize) ) + { + *status1 = statusBuffer[0]; + *status2 = statusBuffer[1]; + *status3 = statusBuffer[2]; + return 1; + } + else + { + return 0; + } +} + +#endif diff --git a/wmi/acpiwmi.h b/wmi/acpiwmi.h new file mode 100644 index 00000000..0484b1a0 --- /dev/null +++ b/wmi/acpiwmi.h @@ -0,0 +1,17 @@ +#ifndef ACPIWMI_H +#define ACPIWMI_H + +#ifdef _WIN32 + +bool AsWMI_CheckSupport(); +bool AsWMI_Open(); +void AsWMI_Close(); +bool AsWMI_NB_RegisterEvent(); +bool AsWMI_NB_DeviceControl(int a1, int a2); +bool AsWMI_NB_DeviceControl_2arg(int a1, int a2, int a3); +char AsWMI_NB_GetDeviceStatus(int a1, int *out); +bool AsWMI_NB_GetDeviceStatus_MoreBYTE(int a1, int a2, int *status1, int *status2, int* status3); + +#endif + +#endif // ACPIWMI_H