From 2575c6adf4ff0b66eebf2ee2c0b5e885eb444052 Mon Sep 17 00:00:00 2001 From: Nexrem Date: Mon, 6 Mar 2023 22:39:48 +0000 Subject: [PATCH] Rework TUF WMI Laptop, implementing additional brightness and persistent saving --- .../AsusTUFLaptopController.cpp | 111 ++++++++++ .../AsusTUFLaptopController.h | 60 ++++++ .../AsusTUFLaptopWMIDetect.cpp | 6 +- .../RGBController_AsusTUFLaptopWMI.cpp | 199 ++++++++++-------- .../RGBController_AsusTUFLaptopWMI.h | 30 ++- OpenRGB.pro | 2 + 6 files changed, 310 insertions(+), 98 deletions(-) create mode 100644 Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp create mode 100644 Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp new file mode 100644 index 00000000..8f422ea2 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp @@ -0,0 +1,111 @@ +#ifdef _WIN32 + +#include "AsusTUFLaptopController.h" +#include "acpiwmi.h" + +AsusTUFLaptopController::AsusTUFLaptopController() +{ + /*---------------------------------------------------*\ + | Call AsWMI_Open at least once during initialization.| + | Since it's part of the firmware it's guaranteed to | + | always be there. This is necessary to issue further | + | commands. | + \*---------------------------------------------------*/ + AsWMI_Open(); +} + +AsusTUFLaptopController::~AsusTUFLaptopController() +{ + +} + +void AsusTUFLaptopController::SetMode(unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char mode, + unsigned char speed, + bool save) +{ + + /*--------------------------------------------------------*\ + | Use switch case since our speed values are magic numbers | + | Default to Medium/Normal speed | + \*--------------------------------------------------------*/ + unsigned char speed_val; + + switch(speed) + { + case(1): + speed_val = ASUS_WMI_KEYBOARD_SPEED_SLOW; + break; + default: + case(2): + speed_val = ASUS_WMI_KEYBOARD_SPEED_NORMAL; + break; + case(3): + speed_val = ASUS_WMI_KEYBOARD_SPEED_FAST; + break; + } + + + /*----------------------------------------------------------*\ + | We need to use a magic value to save to firmware in order | + | To persist reboots. Save is normal op with different magic | + \*---------------------------------------------------------*/ + unsigned char save_val = ASUS_WMI_KEYBOARD_MAGIC_USE; + + if (save) + { + save_val = ASUS_WMI_KEYBOARD_MAGIC_SAVE; + } + + // B3 is store value + unsigned int high = save_val | (mode<<8) | (red<<16) | (green<<24); + unsigned int low = blue | (speed_val<<8); + + AsWMI_NB_DeviceControl_2arg(ASUS_WMI_DEVID_TUF_RGB_MODE, high, low); + +} + +unsigned char AsusTUFLaptopController::GetBrightness() +{ + int backlight_state = 0; + AsWMI_NB_GetDeviceStatus(ASUS_WMI_DEVID_KBD_BACKLIGHT, &backlight_state); + + /*----------------------------------------------*\ + | Only lowest two bits indicate brightness level | + \*----------------------------------------------*/ + return backlight_state & 0x7F; +} + +void AsusTUFLaptopController::SetBrightness(unsigned char brightness) +{ + /*-----------------------------------------------------*\ + | Only calls in this format persistently set brightness | + \*-----------------------------------------------------*/ + int ctrl_param = 0x80 | (brightness & 0x7F); + AsWMI_NB_DeviceControl(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param); +} + +/*-----------------------------------------------------------*\ +| These settings will not persist a reboot unless save is set | +\*-----------------------------------------------------------*/ +void AsusTUFLaptopController::SetPowerState(bool boot, + bool awake, + bool sleep, + bool shutdown, + bool save) +{ + unsigned int state = 0xBD; + + if (boot) state = state | ASUS_WMI_KEYBOARD_POWER_BOOT; + if (awake) state = state | ASUS_WMI_KEYBOARD_POWER_AWAKE; + if (sleep) state = state | ASUS_WMI_KEYBOARD_POWER_SLEEP; + if (shutdown) state = state | ASUS_WMI_KEYBOARD_POWER_SHUTDOWN; + + if (save) state = state | ASUS_WMI_KEYBOARD_POWER_SAVE; + + AsWMI_NB_DeviceControl(ASUS_WMI_DEVID_TUF_RGB_STATE, state); +} + +#endif // _WIN32 diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h new file mode 100644 index 00000000..74147c19 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h @@ -0,0 +1,60 @@ +#ifdef _WIN32 + +#ifndef ASUSTUFLAPTOPCONTROLLER_H +#define ASUSTUFLAPTOPCONTROLLER_H + +#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 +#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 +#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 + +#define ASUS_WMI_KEYBOARD_SPEED_SLOW 0xE1 +#define ASUS_WMI_KEYBOARD_SPEED_NORMAL 0xEB +#define ASUS_WMI_KEYBOARD_SPEED_FAST 0xF5 + +#define ASUS_WMI_KEYBOARD_SPEED_MIN 1 +#define ASUS_WMI_KEYBOARD_SPEED_MAX 3 + +#define ASUS_WMI_KEYBOARD_MODE_STATIC 0x00 +#define ASUS_WMI_KEYBOARD_MODE_BREATHING 0x01 +#define ASUS_WMI_KEYBOARD_MODE_COLORCYCLE 0x02 +#define ASUS_WMI_KEYBOARD_MODE_STROBING 0x0A + +#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN 0 +#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX 3 + +#define ASUS_WMI_KEYBOARD_MAGIC_USE 0xB3 +#define ASUS_WMI_KEYBOARD_MAGIC_SAVE 0xB4 + +#define ASUS_WMI_KEYBOARD_POWER_BOOT 0x03<<16 +#define ASUS_WMI_KEYBOARD_POWER_AWAKE 0x0C<<16 +#define ASUS_WMI_KEYBOARD_POWER_SLEEP 0x30<<16 +#define ASUS_WMI_KEYBOARD_POWER_SHUTDOWN 0xC0<<16 + +#define ASUS_WMI_KEYBOARD_POWER_SAVE 0x01<<8 + +class AsusTUFLaptopController +{ +public: + AsusTUFLaptopController(); + ~AsusTUFLaptopController(); + + void SetMode(unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char mode, + unsigned char speed, + bool save); + + unsigned char GetBrightness(); + void SetBrightness(unsigned char brightness); + + void SetPowerState(bool boot, + bool awake, + bool sleep, + bool shutdown, + bool save); +}; + +#endif // ASUSTUFLAPTOPCONTROLLER_H + +#endif // _WIN32 diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp index db9ff7f8..71d0fc43 100644 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp @@ -1,5 +1,6 @@ #ifdef _WIN32 +#include "AsusTUFLaptopController.h" #include "RGBController_AsusTUFLaptopWMI.h" #include "acpiwmi.h" @@ -29,6 +30,7 @@ static void DetectAsusTUFLaptopWMIControllers() return; } std::string& name = systemProduct[0]["Name"]; + if(name.find("TUF Gaming") == name.npos) { return; @@ -36,7 +38,9 @@ static void DetectAsusTUFLaptopWMIControllers() if(AsWMI_Open()) { - RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(); + AsusTUFLaptopController* asus_wmi_controller = new AsusTUFLaptopController(); + RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(asus_wmi_controller); + ResourceManager::get()->RegisterRGBController(new_controller); // Success! No more if's } diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp index 52cf0955..0353f299 100644 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp @@ -2,12 +2,6 @@ #include "RGBController_AsusTUFLaptopWMI.h" -#include "acpiwmi.h" -#include "ResourceManager.h" -#include "Detector.h" -#include "wmi.h" -#include - using namespace std::chrono_literals; /**------------------------------------------------------------------*\ @@ -21,72 +15,91 @@ using namespace std::chrono_literals; @comment \*-------------------------------------------------------------------*/ -RGBController_AsusTUFLaptopWMI::RGBController_AsusTUFLaptopWMI() +RGBController_AsusTUFLaptopWMI::RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr) { - name = "ASUS TUF Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "WMI Device"; - location = "\\\\.\\ATKACPI"; + name = "ASUS TUF Keyboard"; + vendor = "ASUS"; + 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; + mode Static; + Static.name = "Static"; + Static.value = ASUS_WMI_KEYBOARD_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Static.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Static.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Static); - 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; + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ASUS_WMI_KEYBOARD_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; + Breathing.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; + Breathing.speed = 2; + Breathing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Breathing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Breathing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Breathing); - 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; + mode ColorCycle; + ColorCycle.name = "Color Cycle"; + ColorCycle.value = ASUS_WMI_KEYBOARD_MODE_COLORCYCLE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorCycle.color_mode = MODE_COLORS_NONE; + ColorCycle.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; + ColorCycle.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; + ColorCycle.speed = 2; + ColorCycle.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + ColorCycle.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + ColorCycle.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(ColorCycle); - 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; + mode Strobing; + Strobing.name = "Strobing"; + Strobing.value = ASUS_WMI_KEYBOARD_MODE_STROBING; + Strobing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Strobing.color_mode = MODE_COLORS_PER_LED; + Strobing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Strobing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Strobing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Strobing); SetupZones(); + + controller = controller_ptr; + + ReadConfiguration(); } RGBController_AsusTUFLaptopWMI::~RGBController_AsusTUFLaptopWMI() { - AsWMI_Close(); + delete controller; } void RGBController_AsusTUFLaptopWMI::SetupZones() { /*---------------------------------------------------------*\ - | Set up zone | + | Device only has one zone and one led | \*---------------------------------------------------------*/ - 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; + zone* new_zone = new zone(); + led* new_led = new led(); - /*---------------------------------------------------------*\ - | Set up LED | - \*---------------------------------------------------------*/ - leds.resize(1); - leds[0].name = "Keyboard Backlight LED"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->name = "Keyboard Backlight zone"; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + + new_led->name = "Keyboard Backlight LED"; + + zones.push_back(*new_zone); + leds.push_back(*new_led); SetupColors(); } @@ -98,52 +111,66 @@ void RGBController_AsusTUFLaptopWMI::ResizeZone(int /*zone*/, int /*new_size*/) \*---------------------------------------------------------*/ } +/*---------------------------------------------------------*\ +| Break this function off since we have to call save in the | + same operation as doing everything else. | +\*---------------------------------------------------------*/ +void RGBController_AsusTUFLaptopWMI::ControllerSetMode(bool save) +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char green = RGBGetGValue(colors[0]); + unsigned char blue = RGBGetBValue(colors[0]); + + unsigned char mode = (unsigned char)modes[(unsigned int)active_mode].value; + + /*------------------------------------------------------------*\ + | Use speed only if the mode supports it. Otherwise set normal | + \*------------------------------------------------------------*/ + unsigned char speed = ASUS_WMI_KEYBOARD_SPEED_NORMAL; + + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_SPEED) + { + speed = (unsigned char)modes[(unsigned int)active_mode].speed; + } + + controller->SetMode(red, green, blue, mode, speed, save); +} + 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); - } + ControllerSetMode(false); } void RGBController_AsusTUFLaptopWMI::UpdateZoneLEDs(int /*zone*/) { - DeviceUpdateLEDs(); + ControllerSetMode(false); } void RGBController_AsusTUFLaptopWMI::UpdateSingleLED(int /*led*/) { - DeviceUpdateLEDs(); + ControllerSetMode(false); } void RGBController_AsusTUFLaptopWMI::DeviceUpdateMode() { - DeviceUpdateLEDs(); + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + controller->SetBrightness((unsigned char)modes[(unsigned int)active_mode].brightness); + } + ControllerSetMode(false); +} + +void RGBController_AsusTUFLaptopWMI::ReadConfiguration() +{ + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + modes[(unsigned int)active_mode].brightness = controller->GetBrightness(); + } +} + +void RGBController_AsusTUFLaptopWMI::DeviceSaveMode() +{ + ControllerSetMode(true); } #endif diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h index ca164fb8..a6387c10 100644 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h @@ -1,27 +1,35 @@ +#ifdef _WIN32 + #ifndef RGBCONTROLLER_ASUSTUFLAPTOPWMI_H #define RGBCONTROLLER_ASUSTUFLAPTOPWMI_H -#ifdef _WIN32 - +#include "AsusTUFLaptopController.h" #include "RGBController.h" class RGBController_AsusTUFLaptopWMI : public RGBController { public: - RGBController_AsusTUFLaptopWMI(); + RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr); virtual ~RGBController_AsusTUFLaptopWMI(); - void SetupZones() override; + void SetupZones(); - void ResizeZone(int zone, int new_size) override; + void ResizeZone(int zone, int new_size); - void DeviceUpdateLEDs() override; - void UpdateZoneLEDs(int zone) override; - void UpdateSingleLED(int led) override; + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); - void DeviceUpdateMode() override; + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AsusTUFLaptopController* controller; + + void ReadConfiguration(); + void ControllerSetMode(bool save); }; -#endif - #endif // RGBCONTROLLER_ASUSTUFLAPTOPWMI_H + +#endif // _WIN32 diff --git a/OpenRGB.pro b/OpenRGB.pro index edfe790c..2b735af4 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -1506,6 +1506,7 @@ win32:SOURCES += wmi/wmi.cpp \ wmi/acpiwmi.cpp \ AutoStart/AutoStart-Windows.cpp \ + Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp \ Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp \ Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp \ Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp \ @@ -1530,6 +1531,7 @@ win32:HEADERS += wmi/wmi.h \ wmi/acpiwmi.h \ AutoStart/AutoStart-Windows.h \ + Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h \ Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h \ Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h \ Controllers/NVIDIAIlluminationController/nvapi_accessor.h \