1.. SPDX-License-Identifier: GPL-2.0-or-later 2 3============================================== 4Dell AWCC WMI interface driver (alienware-wmi) 5============================================== 6 7Introduction 8============ 9 10The WMI device WMAX has been implemented for many Alienware and Dell's G-Series 11models. Throughout these models, two implementations have been identified. The 12first one, used by older systems, deals with HDMI, brightness, RGB, amplifier 13and deep sleep control. The second one used by newer systems deals primarily 14with thermal, overclocking, and GPIO control. 15 16It is suspected that the latter is used by Alienware Command Center (AWCC) to 17manage manufacturer predefined thermal profiles. The alienware-wmi driver 18exposes Thermal_Information and Thermal_Control methods through the Platform 19Profile API to mimic AWCC's behavior. 20 21This newer interface, named AWCCMethodFunction has been reverse engineered, as 22Dell has not provided any official documentation. We will try to describe to the 23best of our ability its discovered inner workings. 24 25.. note:: 26 The following method description may be incomplete and some operations have 27 different implementations between devices. 28 29WMI interface description 30------------------------- 31 32The WMI interface description can be decoded from the embedded binary MOF (bmof) 33data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 34 35:: 36 37 [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{A70591CE-A997-11DA-B012-B622A1EF5492}")] 38 class AWCCWmiMethodFunction { 39 [key, read] string InstanceName; 40 [read] boolean Active; 41 42 [WmiMethodId(13), Implemented, read, write, Description("Return Overclocking Report.")] void Return_OverclockingReport([out] uint32 argr); 43 [WmiMethodId(14), Implemented, read, write, Description("Set OCUIBIOS Control.")] void Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr); 44 [WmiMethodId(15), Implemented, read, write, Description("Clear OC FailSafe Flag.")] void Clear_OCFailSafeFlag([out] uint32 argr); 45 [WmiMethodId(19), Implemented, read, write, Description("Get Fan Sensors.")] void GetFanSensors([in] uint32 arg2, [out] uint32 argr); 46 [WmiMethodId(20), Implemented, read, write, Description("Thermal Information.")] void Thermal_Information([in] uint32 arg2, [out] uint32 argr); 47 [WmiMethodId(21), Implemented, read, write, Description("Thermal Control.")] void Thermal_Control([in] uint32 arg2, [out] uint32 argr); 48 [WmiMethodId(23), Implemented, read, write, Description("MemoryOCControl.")] void MemoryOCControl([in] uint32 arg2, [out] uint32 argr); 49 [WmiMethodId(26), Implemented, read, write, Description("System Information.")] void SystemInformation([in] uint32 arg2, [out] uint32 argr); 50 [WmiMethodId(28), Implemented, read, write, Description("Power Information.")] void PowerInformation([in] uint32 arg2, [out] uint32 argr); 51 [WmiMethodId(32), Implemented, read, write, Description("FW Update GPIO toggle.")] void FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr); 52 [WmiMethodId(33), Implemented, read, write, Description("Read Total of GPIOs.")] void ReadTotalofGPIOs([out] uint32 argr); 53 [WmiMethodId(34), Implemented, read, write, Description("Read GPIO pin Status.")] void ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr); 54 [WmiMethodId(35), Implemented, read, write, Description("Read Chassis Color.")] void ReadChassisColor([out] uint32 argr); 55 [WmiMethodId(36), Implemented, read, write, Description("Read Platform Properties.")] void ReadPlatformProperties([out] uint32 argr); 56 [WmiMethodId(37), Implemented, read, write, Description("Game Shift Status.")] void GameShiftStatus([in] uint32 arg2, [out] uint32 argr); 57 [WmiMethodId(128), Implemented, read, write, Description("Caldera SW installation.")] void CalderaSWInstallation([out] uint32 argr); 58 [WmiMethodId(129), Implemented, read, write, Description("Caldera SW is released.")] void CalderaSWReleased([out] uint32 argr); 59 [WmiMethodId(130), Implemented, read, write, Description("Caldera Connection Status.")] void CalderaConnectionStatus([in] uint32 arg2, [out] uint32 argr); 60 [WmiMethodId(131), Implemented, read, write, Description("Surprise Unplugged Flag Status.")] void SurpriseUnpluggedFlagStatus([out] uint32 argr); 61 [WmiMethodId(132), Implemented, read, write, Description("Clear Surprise Unplugged Flag.")] void ClearSurpriseUnpluggedFlag([out] uint32 argr); 62 [WmiMethodId(133), Implemented, read, write, Description("Cancel Undock Request.")] void CancelUndockRequest([out] uint32 argr); 63 [WmiMethodId(135), Implemented, read, write, Description("Devices in Caldera.")] void DevicesInCaldera([in] uint32 arg2, [out] uint32 argr); 64 [WmiMethodId(136), Implemented, read, write, Description("Notify BIOS for SW ready to disconnect Caldera.")] void NotifyBIOSForSWReadyToDisconnectCaldera([out] uint32 argr); 65 [WmiMethodId(160), Implemented, read, write, Description("Tobii SW installation.")] void TobiiSWinstallation([out] uint32 argr); 66 [WmiMethodId(161), Implemented, read, write, Description("Tobii SW Released.")] void TobiiSWReleased([out] uint32 argr); 67 [WmiMethodId(162), Implemented, read, write, Description("Tobii Camera Power Reset.")] void TobiiCameraPowerReset([out] uint32 argr); 68 [WmiMethodId(163), Implemented, read, write, Description("Tobii Camera Power On.")] void TobiiCameraPowerOn([out] uint32 argr); 69 [WmiMethodId(164), Implemented, read, write, Description("Tobii Camera Power Off.")] void TobiiCameraPowerOff([out] uint32 argr); 70 }; 71 72Some of these methods get quite intricate so we will describe them using 73pseudo-code that vaguely resembles the original ASL code. 74 75Methods not described in the following document have unknown behavior. 76 77Argument Structure 78------------------ 79 80All input arguments have type **uint32** and their structure is very similar 81between methods. Usually, the first byte corresponds to a specific *operation* 82the method performs, and the subsequent bytes correspond to *arguments* passed 83to this *operation*. For example, if an operation has code 0x01 and requires an 84ID 0xA0, the argument you would pass to the method is 0xA001. 85 86 87Thermal Methods 88=============== 89 90WMI method Thermal_Information([in] uint32 arg2, [out] uint32 argr) 91------------------------------------------------------------------- 92 93:: 94 95 if BYTE_0(arg2) == 0x01: 96 argr = 1 97 98 if BYTE_0(arg2) == 0x02: 99 argr = UNKNOWN_CONSTANT 100 101 if BYTE_0(arg2) == 0x03: 102 if BYTE_1(arg2) == 0x00: 103 argr = FAN_ID_0 104 105 if BYTE_1(arg2) == 0x01: 106 argr = FAN_ID_1 107 108 if BYTE_1(arg2) == 0x02: 109 argr = FAN_ID_2 110 111 if BYTE_1(arg2) == 0x03: 112 argr = FAN_ID_3 113 114 if BYTE_1(arg2) == 0x04: 115 argr = SENSOR_ID_CPU | 0x0100 116 117 if BYTE_1(arg2) == 0x05: 118 argr = SENSOR_ID_GPU | 0x0100 119 120 if BYTE_1(arg2) == 0x06: 121 argr = THERMAL_MODE_QUIET_ID 122 123 if BYTE_1(arg2) == 0x07: 124 argr = THERMAL_MODE_BALANCED_ID 125 126 if BYTE_1(arg2) == 0x08: 127 argr = THERMAL_MODE_BALANCED_PERFORMANCE_ID 128 129 if BYTE_1(arg2) == 0x09: 130 argr = THERMAL_MODE_PERFORMANCE_ID 131 132 if BYTE_1(arg2) == 0x0A: 133 argr = THERMAL_MODE_LOW_POWER_ID 134 135 if BYTE_1(arg2) == 0x0B: 136 argr = THERMAL_MODE_GMODE_ID 137 138 else: 139 argr = 0xFFFFFFFF 140 141 if BYTE_0(arg2) == 0x04: 142 if is_valid_sensor(BYTE_1(arg2)): 143 argr = SENSOR_TEMP_C 144 else: 145 argr = 0xFFFFFFFF 146 147 if BYTE_0(arg2) == 0x05: 148 if is_valid_fan(BYTE_1(arg2)): 149 argr = FAN_RPM() 150 151 if BYTE_0(arg2) == 0x06: 152 skip 153 154 if BYTE_0(arg2) == 0x07: 155 argr = 0 156 157 If BYTE_0(arg2) == 0x08: 158 if is_valid_fan(BYTE_1(arg2)): 159 argr = 0 160 else: 161 argr = 0xFFFFFFFF 162 163 if BYTE_0(arg2) == 0x09: 164 if is_valid_fan(BYTE_1(arg2)): 165 argr = FAN_UNKNOWN_STAT_0() 166 167 else: 168 argr = 0xFFFFFFFF 169 170 if BYTE_0(arg2) == 0x0A: 171 argr = THERMAL_MODE_BALANCED_ID 172 173 if BYTE_0(arg2) == 0x0B: 174 argr = CURRENT_THERMAL_MODE() 175 176 if BYTE_0(arg2) == 0x0C: 177 if is_valid_fan(BYTE_1(arg2)): 178 argr = FAN_UNKNOWN_STAT_1() 179 else: 180 argr = 0xFFFFFFFF 181 182Operation 0x03 list all available fan IDs, sensor IDs and thermal profile 183codes in order, but different models may have different number of fans and 184thermal profiles. These are the known ranges: 185 186* Fan IDs: from 2 up to 4 187* Sensor IDs: 2 188* Thermal profile codes: from 1 up to 7 189 190In total BYTE_1(ARG2) may range from 0x5 up to 0xD depending on the model. 191 192WMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr) 193--------------------------------------------------------------- 194 195:: 196 197 if BYTE_0(arg2) == 0x01: 198 if is_valid_thermal_profile(BYTE_1(arg2)): 199 SET_THERMAL_PROFILE(BYTE_1(arg2)) 200 argr = 0 201 202 if BYTE_0(arg2) == 0x02: 203 if is_valid_fan(BYTE_1(arg2)): 204 SET_FAN_SPEED_MULTIPLIER(BYTE_2(arg2)) 205 argr = 0 206 else: 207 argr = 0xFFFFFFFF 208 209.. note:: 210 While you can manually change the fan speed multiplier with this method, 211 Dell's BIOS tends to overwrite this changes anyway. 212 213These are the known thermal profile codes: 214 215:: 216 217 CUSTOM 0x00 218 219 BALANCED_USTT 0xA0 220 BALANCED_PERFORMANCE_USTT 0xA1 221 COOL_USTT 0xA2 222 QUIET_USTT 0xA3 223 PERFORMANCE_USTT 0xA4 224 LOW_POWER_USTT 0xA5 225 226 QUIET 0x96 227 BALANCED 0x97 228 BALANCED_PERFORMANCE 0x98 229 PERFORMANCE 0x99 230 231 GMODE 0xAB 232 233Usually if a model doesn't support the first four profiles they will support 234the User Selectable Thermal Tables (USTT) profiles and vice-versa. 235 236GMODE replaces PERFORMANCE in G-Series laptops. 237 238WMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr) 239--------------------------------------------------------------- 240 241:: 242 243 if BYTE_0(arg2) == 0x1: 244 TOGGLE_GAME_SHIFT() 245 argr = GET_GAME_SHIFT_STATUS() 246 247 if BYTE_0(arg2) == 0x2: 248 argr = GET_GAME_SHIFT_STATUS() 249 250Game Shift Status does not change the fan speed profile but it could be some 251sort of CPU/GPU power profile. Benchmarks have not been done. 252 253This method is only present on Dell's G-Series laptops and it's implementation 254implies GMODE thermal profile is available, even if operation 0x03 of 255Thermal_Information does not list it. 256 257G-key on Dell's G-Series laptops also changes Game Shift status, so both are 258directly related. 259 260WMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr) 261------------------------------------------------------------- 262 263:: 264 265 if BYTE_0(arg2) == 0x1: 266 if is_valid_fan(BYTE_1(arg2)): 267 argr = 1 268 else: 269 argr = 0 270 271 if BYTE_0(arg2) == 0x2: 272 if is_valid_fan(BYTE_1(arg2)): 273 if BYTE_2(arg2) == 0: 274 argr == SENSOR_ID 275 else 276 argr == 0xFFFFFFFF 277 else: 278 argr = 0 279 280Overclocking Methods 281==================== 282 283.. warning:: 284 These methods have not been tested and are only partially reverse 285 engineered. 286 287WMI method Return_OverclockingReport([out] uint32 argr) 288------------------------------------------------------- 289 290:: 291 292 CSMI (0xE3, 0x99) 293 argr = 0 294 295CSMI is an unknown operation. 296 297WMI method Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr) 298------------------------------------------------------------------- 299 300:: 301 302 CSMI (0xE3, 0x99) 303 argr = 0 304 305CSMI is an unknown operation. 306 307WMI method Clear_OCFailSafeFlag([out] uint32 argr) 308-------------------------------------------------- 309 310:: 311 312 CSMI (0xE3, 0x99) 313 argr = 0 314 315CSMI is an unknown operation. 316 317 318WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) 319--------------------------------------------------------------- 320 321AWCC supports memory overclocking, but this method is very intricate and has 322not been deciphered yet. 323 324GPIO methods 325============ 326 327These methods are probably related to some kind of firmware update system, 328through a GPIO device. 329 330.. warning:: 331 These methods have not been tested and are only partially reverse 332 engineered. 333 334WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) 335------------------------------------------------------------------ 336 337:: 338 339 if BYTE_0(arg2) == 0: 340 if BYTE_1(arg2) == 1: 341 SET_PIN_A_HIGH() 342 else: 343 SET_PIN_A_LOW() 344 345 if BYTE_0(arg2) == 1: 346 if BYTE_1(arg2) == 1: 347 SET_PIN_B_HIGH() 348 349 else: 350 SET_PIN_B_LOW() 351 352 else: 353 argr = 1 354 355WMI method ReadTotalofGPIOs([out] uint32 argr) 356---------------------------------------------- 357 358:: 359 360 argr = 0x02 361 362WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) 363------------------------------------------------------------------ 364 365:: 366 367 if BYTE_0(arg2) == 0: 368 argr = PIN_A_STATUS 369 370 if BYTE_0(arg2) == 1: 371 argr = PIN_B_STATUS 372 373Other information Methods 374========================= 375 376WMI method ReadChassisColor([out] uint32 argr) 377---------------------------------------------- 378 379:: 380 381 argr = CHASSIS_COLOR_ID 382 383Acknowledgements 384================ 385 386Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ for documenting 387and testing available thermal profile codes. 388