1f164dd0bSKurt Borja.. SPDX-License-Identifier: GPL-2.0-or-later 2f164dd0bSKurt Borja 3f164dd0bSKurt Borja============================================== 4f164dd0bSKurt BorjaDell AWCC WMI interface driver (alienware-wmi) 5f164dd0bSKurt Borja============================================== 6f164dd0bSKurt Borja 7f164dd0bSKurt BorjaIntroduction 8f164dd0bSKurt Borja============ 9f164dd0bSKurt Borja 10f164dd0bSKurt BorjaThe WMI device WMAX has been implemented for many Alienware and Dell's G-Series 11f164dd0bSKurt Borjamodels. Throughout these models, two implementations have been identified. The 12f164dd0bSKurt Borjafirst one, used by older systems, deals with HDMI, brightness, RGB, amplifier 13f164dd0bSKurt Borjaand deep sleep control. The second one used by newer systems deals primarily 14a56d188aSKurt Borjawith thermal control and overclocking. 15f164dd0bSKurt Borja 16f164dd0bSKurt BorjaIt is suspected that the latter is used by Alienware Command Center (AWCC) to 17f164dd0bSKurt Borjamanage manufacturer predefined thermal profiles. The alienware-wmi driver 18f164dd0bSKurt Borjaexposes Thermal_Information and Thermal_Control methods through the Platform 19f164dd0bSKurt BorjaProfile API to mimic AWCC's behavior. 20f164dd0bSKurt Borja 21f164dd0bSKurt BorjaThis newer interface, named AWCCMethodFunction has been reverse engineered, as 22f164dd0bSKurt BorjaDell has not provided any official documentation. We will try to describe to the 23f164dd0bSKurt Borjabest of our ability its discovered inner workings. 24f164dd0bSKurt Borja 25f164dd0bSKurt Borja.. note:: 26f164dd0bSKurt Borja The following method description may be incomplete and some operations have 27f164dd0bSKurt Borja different implementations between devices. 28f164dd0bSKurt Borja 29f164dd0bSKurt BorjaWMI interface description 30f164dd0bSKurt Borja------------------------- 31f164dd0bSKurt Borja 32f164dd0bSKurt BorjaThe WMI interface description can be decoded from the embedded binary MOF (bmof) 33f164dd0bSKurt Borjadata using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 34f164dd0bSKurt Borja 35f164dd0bSKurt Borja:: 36f164dd0bSKurt Borja 37f164dd0bSKurt Borja [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{A70591CE-A997-11DA-B012-B622A1EF5492}")] 38f164dd0bSKurt Borja class AWCCWmiMethodFunction { 39f164dd0bSKurt Borja [key, read] string InstanceName; 40f164dd0bSKurt Borja [read] boolean Active; 41f164dd0bSKurt Borja 42f164dd0bSKurt Borja [WmiMethodId(13), Implemented, read, write, Description("Return Overclocking Report.")] void Return_OverclockingReport([out] uint32 argr); 43f164dd0bSKurt Borja [WmiMethodId(14), Implemented, read, write, Description("Set OCUIBIOS Control.")] void Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr); 44f164dd0bSKurt Borja [WmiMethodId(15), Implemented, read, write, Description("Clear OC FailSafe Flag.")] void Clear_OCFailSafeFlag([out] uint32 argr); 45f164dd0bSKurt Borja [WmiMethodId(19), Implemented, read, write, Description("Get Fan Sensors.")] void GetFanSensors([in] uint32 arg2, [out] uint32 argr); 46f164dd0bSKurt Borja [WmiMethodId(20), Implemented, read, write, Description("Thermal Information.")] void Thermal_Information([in] uint32 arg2, [out] uint32 argr); 47f164dd0bSKurt Borja [WmiMethodId(21), Implemented, read, write, Description("Thermal Control.")] void Thermal_Control([in] uint32 arg2, [out] uint32 argr); 48f164dd0bSKurt Borja [WmiMethodId(23), Implemented, read, write, Description("MemoryOCControl.")] void MemoryOCControl([in] uint32 arg2, [out] uint32 argr); 49f164dd0bSKurt Borja [WmiMethodId(26), Implemented, read, write, Description("System Information.")] void SystemInformation([in] uint32 arg2, [out] uint32 argr); 50f164dd0bSKurt Borja [WmiMethodId(28), Implemented, read, write, Description("Power Information.")] void PowerInformation([in] uint32 arg2, [out] uint32 argr); 51f164dd0bSKurt Borja [WmiMethodId(32), Implemented, read, write, Description("FW Update GPIO toggle.")] void FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr); 52f164dd0bSKurt Borja [WmiMethodId(33), Implemented, read, write, Description("Read Total of GPIOs.")] void ReadTotalofGPIOs([out] uint32 argr); 53f164dd0bSKurt Borja [WmiMethodId(34), Implemented, read, write, Description("Read GPIO pin Status.")] void ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr); 54f164dd0bSKurt Borja [WmiMethodId(35), Implemented, read, write, Description("Read Chassis Color.")] void ReadChassisColor([out] uint32 argr); 55f164dd0bSKurt Borja [WmiMethodId(36), Implemented, read, write, Description("Read Platform Properties.")] void ReadPlatformProperties([out] uint32 argr); 56f164dd0bSKurt Borja [WmiMethodId(37), Implemented, read, write, Description("Game Shift Status.")] void GameShiftStatus([in] uint32 arg2, [out] uint32 argr); 57f164dd0bSKurt Borja [WmiMethodId(128), Implemented, read, write, Description("Caldera SW installation.")] void CalderaSWInstallation([out] uint32 argr); 58f164dd0bSKurt Borja [WmiMethodId(129), Implemented, read, write, Description("Caldera SW is released.")] void CalderaSWReleased([out] uint32 argr); 59f164dd0bSKurt Borja [WmiMethodId(130), Implemented, read, write, Description("Caldera Connection Status.")] void CalderaConnectionStatus([in] uint32 arg2, [out] uint32 argr); 60f164dd0bSKurt Borja [WmiMethodId(131), Implemented, read, write, Description("Surprise Unplugged Flag Status.")] void SurpriseUnpluggedFlagStatus([out] uint32 argr); 61f164dd0bSKurt Borja [WmiMethodId(132), Implemented, read, write, Description("Clear Surprise Unplugged Flag.")] void ClearSurpriseUnpluggedFlag([out] uint32 argr); 62f164dd0bSKurt Borja [WmiMethodId(133), Implemented, read, write, Description("Cancel Undock Request.")] void CancelUndockRequest([out] uint32 argr); 63f164dd0bSKurt Borja [WmiMethodId(135), Implemented, read, write, Description("Devices in Caldera.")] void DevicesInCaldera([in] uint32 arg2, [out] uint32 argr); 64f164dd0bSKurt Borja [WmiMethodId(136), Implemented, read, write, Description("Notify BIOS for SW ready to disconnect Caldera.")] void NotifyBIOSForSWReadyToDisconnectCaldera([out] uint32 argr); 65f164dd0bSKurt Borja [WmiMethodId(160), Implemented, read, write, Description("Tobii SW installation.")] void TobiiSWinstallation([out] uint32 argr); 66f164dd0bSKurt Borja [WmiMethodId(161), Implemented, read, write, Description("Tobii SW Released.")] void TobiiSWReleased([out] uint32 argr); 67f164dd0bSKurt Borja [WmiMethodId(162), Implemented, read, write, Description("Tobii Camera Power Reset.")] void TobiiCameraPowerReset([out] uint32 argr); 68f164dd0bSKurt Borja [WmiMethodId(163), Implemented, read, write, Description("Tobii Camera Power On.")] void TobiiCameraPowerOn([out] uint32 argr); 69f164dd0bSKurt Borja [WmiMethodId(164), Implemented, read, write, Description("Tobii Camera Power Off.")] void TobiiCameraPowerOff([out] uint32 argr); 70f164dd0bSKurt Borja }; 71f164dd0bSKurt Borja 72f164dd0bSKurt BorjaMethods not described in the following document have unknown behavior. 73f164dd0bSKurt Borja 74f164dd0bSKurt BorjaArgument Structure 75f164dd0bSKurt Borja------------------ 76f164dd0bSKurt Borja 77f164dd0bSKurt BorjaAll input arguments have type **uint32** and their structure is very similar 78f164dd0bSKurt Borjabetween methods. Usually, the first byte corresponds to a specific *operation* 79f164dd0bSKurt Borjathe method performs, and the subsequent bytes correspond to *arguments* passed 80f164dd0bSKurt Borjato this *operation*. For example, if an operation has code 0x01 and requires an 81f164dd0bSKurt BorjaID 0xA0, the argument you would pass to the method is 0xA001. 82f164dd0bSKurt Borja 83f164dd0bSKurt Borja 84f164dd0bSKurt BorjaThermal Methods 85f164dd0bSKurt Borja=============== 86f164dd0bSKurt Borja 87a56d188aSKurt BorjaWMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr) 88a56d188aSKurt Borja------------------------------------------------------------- 89a56d188aSKurt Borja 90a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 91a56d188aSKurt Borja| Operation (Byte 0) | Description | Arguments | 92a56d188aSKurt Borja+====================+====================================+====================+ 93a56d188aSKurt Borja| 0x01 | Get the number of temperature | - Byte 1: Fan ID | 94a56d188aSKurt Borja| | sensors related with a fan ID | | 95a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 96a56d188aSKurt Borja| 0x02 | Get the temperature sensor IDs | - Byte 1: Fan ID | 97a56d188aSKurt Borja| | related to a fan sensor ID | - Byte 2: Index | 98a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 99a56d188aSKurt Borja 100f164dd0bSKurt BorjaWMI method Thermal_Information([in] uint32 arg2, [out] uint32 argr) 101f164dd0bSKurt Borja------------------------------------------------------------------- 102f164dd0bSKurt Borja 103a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 104a56d188aSKurt Borja| Operation (Byte 0) | Description | Arguments | 105a56d188aSKurt Borja+====================+====================================+====================+ 106a56d188aSKurt Borja| 0x01 | Unknown. | - None | 107a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 108a56d188aSKurt Borja| 0x02 | Get system description number with | - None | 109a56d188aSKurt Borja| | the following structure: | | 110a56d188aSKurt Borja| | | | 111a56d188aSKurt Borja| | - Byte 0: Number of fans | | 112a56d188aSKurt Borja| | - Byte 1: Number of temperature | | 113a56d188aSKurt Borja| | sensors | | 114a56d188aSKurt Borja| | - Byte 2: Unknown | | 115a56d188aSKurt Borja| | - Byte 3: Number of thermal | | 116a56d188aSKurt Borja| | profiles | | 117a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 118a56d188aSKurt Borja| 0x03 | List an ID or resource at a given | - Byte 1: Index | 119a56d188aSKurt Borja| | index. Fan IDs, temperature IDs, | | 120a56d188aSKurt Borja| | unknown IDs and thermal profile | | 121a56d188aSKurt Borja| | IDs are listed in that exact | | 122a56d188aSKurt Borja| | order. | | 123a56d188aSKurt Borja| | | | 124a56d188aSKurt Borja| | Operation 0x02 is used to know | | 125a56d188aSKurt Borja| | which indexes map to which | | 126a56d188aSKurt Borja| | resources. | | 127a56d188aSKurt Borja| | | | 128a56d188aSKurt Borja| | **Returns:** ID at a given index | | 129a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 130a56d188aSKurt Borja| 0x04 | Get the current temperature for a | - Byte 1: Sensor | 131a56d188aSKurt Borja| | given temperature sensor. | ID | 132a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 133a56d188aSKurt Borja| 0x05 | Get the current RPM for a given | - Byte 1: Fan ID | 134a56d188aSKurt Borja| | fan. | | 135a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 136a56d188aSKurt Borja| 0x06 | Get fan speed percentage. (not | - Byte 1: Fan ID | 137a56d188aSKurt Borja| | implemented in every model) | | 138a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 139a56d188aSKurt Borja| 0x07 | Unknown. | - Unknown | 140a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 141a56d188aSKurt Borja| 0x08 | Get minimum RPM for a given FAN | - Byte 1: Fan ID | 142a56d188aSKurt Borja| | ID. | | 143a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 144a56d188aSKurt Borja| 0x09 | Get maximum RPM for a given FAN | - Byte 1: Fan ID | 145a56d188aSKurt Borja| | ID. | | 146a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 147a56d188aSKurt Borja| 0x0A | Get balanced thermal profile ID. | - None | 148a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 149a56d188aSKurt Borja| 0x0B | Get current thermal profile ID. | - None | 150a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 151a56d188aSKurt Borja| 0x0C | Get current `boost` value for a | - Byte 1: Fan ID | 152a56d188aSKurt Borja| | given fan ID. | | 153a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 154f164dd0bSKurt Borja 155f164dd0bSKurt BorjaWMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr) 156f164dd0bSKurt Borja--------------------------------------------------------------- 157f164dd0bSKurt Borja 158a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 159a56d188aSKurt Borja| Operation (Byte 0) | Description | Arguments | 160a56d188aSKurt Borja+====================+====================================+====================+ 161a56d188aSKurt Borja| 0x01 | Activate a given thermal profile. | - Byte 1: Thermal | 162a56d188aSKurt Borja| | | profile ID | 163a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 164a56d188aSKurt Borja| 0x02 | Set a `boost` value for a given | - Byte 1: Fan ID | 165a56d188aSKurt Borja| | fan ID. | - Byte 2: Boost | 166a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 167f164dd0bSKurt Borja 168f164dd0bSKurt BorjaThese are the known thermal profile codes: 169f164dd0bSKurt Borja 170a56d188aSKurt Borja+------------------------------+----------+------+ 171a56d188aSKurt Borja| Thermal Profile | Type | ID | 172a56d188aSKurt Borja+==============================+==========+======+ 173a56d188aSKurt Borja| Custom | Special | 0x00 | 174a56d188aSKurt Borja+------------------------------+----------+------+ 175a56d188aSKurt Borja| G-Mode | Special | 0xAB | 176a56d188aSKurt Borja+------------------------------+----------+------+ 177a56d188aSKurt Borja| Quiet | Legacy | 0x96 | 178a56d188aSKurt Borja+------------------------------+----------+------+ 179a56d188aSKurt Borja| Balanced | Legacy | 0x97 | 180a56d188aSKurt Borja+------------------------------+----------+------+ 181a56d188aSKurt Borja| Balanced Performance | Legacy | 0x98 | 182a56d188aSKurt Borja+------------------------------+----------+------+ 183a56d188aSKurt Borja| Performance | Legacy | 0x99 | 184a56d188aSKurt Borja+------------------------------+----------+------+ 185a56d188aSKurt Borja| Balanced | USTT | 0xA0 | 186a56d188aSKurt Borja+------------------------------+----------+------+ 187a56d188aSKurt Borja| Balanced Performance | USTT | 0xA1 | 188a56d188aSKurt Borja+------------------------------+----------+------+ 189a56d188aSKurt Borja| Cool | USTT | 0xA2 | 190a56d188aSKurt Borja+------------------------------+----------+------+ 191a56d188aSKurt Borja| Quiet | USTT | 0xA3 | 192a56d188aSKurt Borja+------------------------------+----------+------+ 193a56d188aSKurt Borja| Performance | USTT | 0xA4 | 194a56d188aSKurt Borja+------------------------------+----------+------+ 195a56d188aSKurt Borja| Low Power | USTT | 0xA5 | 196a56d188aSKurt Borja+------------------------------+----------+------+ 197f164dd0bSKurt Borja 198a56d188aSKurt BorjaIf a model supports the User Selectable Thermal Tables (USTT) profiles, it will 199a56d188aSKurt Borjanot support the Legacy profiles and vice-versa. 200f164dd0bSKurt Borja 201a56d188aSKurt BorjaEvery model supports the CUSTOM (0x00) thermal profile. GMODE replaces 202a56d188aSKurt BorjaPERFORMANCE in G-Series laptops. 203f164dd0bSKurt Borja 204f164dd0bSKurt BorjaWMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr) 205f164dd0bSKurt Borja--------------------------------------------------------------- 206f164dd0bSKurt Borja 207a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 208a56d188aSKurt Borja| Operation (Byte 0) | Description | Arguments | 209a56d188aSKurt Borja+====================+====================================+====================+ 210a56d188aSKurt Borja| 0x01 | Toggle *Game Shift*. | - None | 211a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 212a56d188aSKurt Borja| 0x02 | Get *Game Shift* status. | - None | 213a56d188aSKurt Borja+--------------------+------------------------------------+--------------------+ 214f164dd0bSKurt Borja 215f164dd0bSKurt BorjaGame Shift Status does not change the fan speed profile but it could be some 216f164dd0bSKurt Borjasort of CPU/GPU power profile. Benchmarks have not been done. 217f164dd0bSKurt Borja 218f164dd0bSKurt BorjaThis method is only present on Dell's G-Series laptops and it's implementation 219f164dd0bSKurt Borjaimplies GMODE thermal profile is available, even if operation 0x03 of 220f164dd0bSKurt BorjaThermal_Information does not list it. 221f164dd0bSKurt Borja 222f164dd0bSKurt BorjaG-key on Dell's G-Series laptops also changes Game Shift status, so both are 223f164dd0bSKurt Borjadirectly related. 224f164dd0bSKurt Borja 225f164dd0bSKurt BorjaOverclocking Methods 226f164dd0bSKurt Borja==================== 227f164dd0bSKurt Borja 228f164dd0bSKurt BorjaWMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) 229f164dd0bSKurt Borja--------------------------------------------------------------- 230f164dd0bSKurt Borja 231f164dd0bSKurt BorjaAWCC supports memory overclocking, but this method is very intricate and has 232f164dd0bSKurt Borjanot been deciphered yet. 233f164dd0bSKurt Borja 234*df6061c2SKurt BorjaGPIO control Methods 235*df6061c2SKurt Borja==================== 236*df6061c2SKurt Borja 237*df6061c2SKurt BorjaAlienware and Dell G Series devices with the AWCC interface usually have an 238*df6061c2SKurt Borjaembedded STM32 RGB lighting controller with USB/HID capabilities. It's vendor ID 239*df6061c2SKurt Borjais ``187c`` while it's product ID may vary from model to model. 240*df6061c2SKurt Borja 241*df6061c2SKurt BorjaThe control of two GPIO pins of this MCU is exposed as WMI methods for debugging 242*df6061c2SKurt Borjapurposes. 243*df6061c2SKurt Borja 244*df6061c2SKurt Borja+--------------+--------------------------------------------------------------+ 245*df6061c2SKurt Borja| Pin | Description | 246*df6061c2SKurt Borja+==============+===============================+==============================+ 247*df6061c2SKurt Borja| 0 | Device Firmware Update (DFU) | **HIGH**: Enables DFU mode | 248*df6061c2SKurt Borja| | mode pin. | on next MCU boot. | 249*df6061c2SKurt Borja| | +------------------------------+ 250*df6061c2SKurt Borja| | | **LOW**: Disables DFU mode | 251*df6061c2SKurt Borja| | | on next MCU boot. | 252*df6061c2SKurt Borja+--------------+-------------------------------+------------------------------+ 253*df6061c2SKurt Borja| 1 | Negative Reset (NRST) pin. | **HIGH**: MCU is ON. | 254*df6061c2SKurt Borja| | | | 255*df6061c2SKurt Borja| | +------------------------------+ 256*df6061c2SKurt Borja| | | **LOW**: MCU is OFF. | 257*df6061c2SKurt Borja| | | | 258*df6061c2SKurt Borja+--------------+-------------------------------+------------------------------+ 259*df6061c2SKurt Borja 260*df6061c2SKurt BorjaSee :ref:`acknowledgements` for more information on this MCU. 261*df6061c2SKurt Borja 262*df6061c2SKurt Borja.. note:: 263*df6061c2SKurt Borja Some GPIO control methods break the usual argument structure and take a 264*df6061c2SKurt Borja **Pin number** instead of an operation on the first byte. 265*df6061c2SKurt Borja 266*df6061c2SKurt BorjaWMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) 267*df6061c2SKurt Borja------------------------------------------------------------------ 268*df6061c2SKurt Borja 269*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 270*df6061c2SKurt Borja| Operation (Byte 0) | Description | Arguments | 271*df6061c2SKurt Borja+====================+====================================+====================+ 272*df6061c2SKurt Borja| Pin number | Set the pin status | - Byte 1: Pin | 273*df6061c2SKurt Borja| | | status | 274*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 275*df6061c2SKurt Borja 276*df6061c2SKurt BorjaWMI method ReadTotalofGPIOs([out] uint32 argr) 277*df6061c2SKurt Borja---------------------------------------------- 278*df6061c2SKurt Borja 279*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 280*df6061c2SKurt Borja| Operation (Byte 0) | Description | Arguments | 281*df6061c2SKurt Borja+====================+====================================+====================+ 282*df6061c2SKurt Borja| N/A | Get the total number of GPIOs | - None | 283*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 284*df6061c2SKurt Borja 285*df6061c2SKurt Borja.. note:: 286*df6061c2SKurt Borja Due to how WMI methods are implemented on the firmware level, this method 287*df6061c2SKurt Borja requires a dummy uint32 input argument when invoked. 288*df6061c2SKurt Borja 289*df6061c2SKurt BorjaWMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) 290*df6061c2SKurt Borja------------------------------------------------------------------ 291*df6061c2SKurt Borja 292*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 293*df6061c2SKurt Borja| Operation (Byte 0) | Description | Arguments | 294*df6061c2SKurt Borja+====================+====================================+====================+ 295*df6061c2SKurt Borja| Pin number | Get the pin status | - None | 296*df6061c2SKurt Borja+--------------------+------------------------------------+--------------------+ 297*df6061c2SKurt Borja 298*df6061c2SKurt Borja.. note:: 299*df6061c2SKurt Borja There known firmware bug in some laptops where reading the status of a pin 300*df6061c2SKurt Borja also flips it. 301*df6061c2SKurt Borja 302f164dd0bSKurt BorjaOther information Methods 303f164dd0bSKurt Borja========================= 304f164dd0bSKurt Borja 305f164dd0bSKurt BorjaWMI method ReadChassisColor([out] uint32 argr) 306f164dd0bSKurt Borja---------------------------------------------- 307f164dd0bSKurt Borja 308a56d188aSKurt BorjaReturns the chassis color internal ID. 309f164dd0bSKurt Borja 310*df6061c2SKurt Borja.. _acknowledgements: 311*df6061c2SKurt Borja 312f164dd0bSKurt BorjaAcknowledgements 313f164dd0bSKurt Borja================ 314f164dd0bSKurt Borja 315*df6061c2SKurt BorjaKudos to 316*df6061c2SKurt Borja 317*df6061c2SKurt Borja* `AlexIII <https://github.com/AlexIII/tcc-g15>`_ 318*df6061c2SKurt Borja* `T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ 319*df6061c2SKurt Borja* `Gabriel Marcano <https://gabriel.marcanobrady.family/blog/2024/12/16/dell-g5-5505-se-acpi-or-figuring-out-how-to-reset-the-rgb-controller/>`_ 320*df6061c2SKurt Borja 321*df6061c2SKurt Borjafor documenting and testing some of this device's functionality, making it 322*df6061c2SKurt Borjapossible to generalize this driver. 323