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 = SYSTEM_DESCRIPTION 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 0x02 returns a *system description* buffer with the following 183structure: 184 185:: 186 187 out[0] -> Number of fans 188 out[1] -> Number of sensors 189 out[2] -> 0x00 190 out[3] -> Number of thermal modes 191 192Operation 0x03 list all available fan IDs, sensor IDs and thermal profile 193codes in order, but different models may have different number of fans and 194thermal profiles. These are the known ranges: 195 196* Fan IDs: from 2 up to 4 197* Sensor IDs: 2 198* Thermal profile codes: from 1 up to 7 199 200In total BYTE_1(ARG2) may range from 0x5 up to 0xD depending on the model. 201 202WMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr) 203--------------------------------------------------------------- 204 205:: 206 207 if BYTE_0(arg2) == 0x01: 208 if is_valid_thermal_profile(BYTE_1(arg2)): 209 SET_THERMAL_PROFILE(BYTE_1(arg2)) 210 argr = 0 211 212 if BYTE_0(arg2) == 0x02: 213 if is_valid_fan(BYTE_1(arg2)): 214 SET_FAN_SPEED_MULTIPLIER(BYTE_2(arg2)) 215 argr = 0 216 else: 217 argr = 0xFFFFFFFF 218 219.. note:: 220 While you can manually change the fan speed multiplier with this method, 221 Dell's BIOS tends to overwrite this changes anyway. 222 223These are the known thermal profile codes: 224 225:: 226 227 CUSTOM 0x00 228 229 BALANCED_USTT 0xA0 230 BALANCED_PERFORMANCE_USTT 0xA1 231 COOL_USTT 0xA2 232 QUIET_USTT 0xA3 233 PERFORMANCE_USTT 0xA4 234 LOW_POWER_USTT 0xA5 235 236 QUIET 0x96 237 BALANCED 0x97 238 BALANCED_PERFORMANCE 0x98 239 PERFORMANCE 0x99 240 241 GMODE 0xAB 242 243Usually if a model doesn't support the first four profiles they will support 244the User Selectable Thermal Tables (USTT) profiles and vice-versa. 245 246GMODE replaces PERFORMANCE in G-Series laptops. 247 248WMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr) 249--------------------------------------------------------------- 250 251:: 252 253 if BYTE_0(arg2) == 0x1: 254 TOGGLE_GAME_SHIFT() 255 argr = GET_GAME_SHIFT_STATUS() 256 257 if BYTE_0(arg2) == 0x2: 258 argr = GET_GAME_SHIFT_STATUS() 259 260Game Shift Status does not change the fan speed profile but it could be some 261sort of CPU/GPU power profile. Benchmarks have not been done. 262 263This method is only present on Dell's G-Series laptops and it's implementation 264implies GMODE thermal profile is available, even if operation 0x03 of 265Thermal_Information does not list it. 266 267G-key on Dell's G-Series laptops also changes Game Shift status, so both are 268directly related. 269 270WMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr) 271------------------------------------------------------------- 272 273:: 274 275 if BYTE_0(arg2) == 0x1: 276 if is_valid_fan(BYTE_1(arg2)): 277 argr = 1 278 else: 279 argr = 0 280 281 if BYTE_0(arg2) == 0x2: 282 if is_valid_fan(BYTE_1(arg2)): 283 if BYTE_2(arg2) == 0: 284 argr == SENSOR_ID 285 else 286 argr == 0xFFFFFFFF 287 else: 288 argr = 0 289 290Overclocking Methods 291==================== 292 293.. warning:: 294 These methods have not been tested and are only partially reverse 295 engineered. 296 297WMI method Return_OverclockingReport([out] uint32 argr) 298------------------------------------------------------- 299 300:: 301 302 CSMI (0xE3, 0x99) 303 argr = 0 304 305CSMI is an unknown operation. 306 307WMI method Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr) 308------------------------------------------------------------------- 309 310:: 311 312 CSMI (0xE3, 0x99) 313 argr = 0 314 315CSMI is an unknown operation. 316 317WMI method Clear_OCFailSafeFlag([out] uint32 argr) 318-------------------------------------------------- 319 320:: 321 322 CSMI (0xE3, 0x99) 323 argr = 0 324 325CSMI is an unknown operation. 326 327 328WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) 329--------------------------------------------------------------- 330 331AWCC supports memory overclocking, but this method is very intricate and has 332not been deciphered yet. 333 334GPIO methods 335============ 336 337These methods are probably related to some kind of firmware update system, 338through a GPIO device. 339 340.. warning:: 341 These methods have not been tested and are only partially reverse 342 engineered. 343 344WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) 345------------------------------------------------------------------ 346 347:: 348 349 if BYTE_0(arg2) == 0: 350 if BYTE_1(arg2) == 1: 351 SET_PIN_A_HIGH() 352 else: 353 SET_PIN_A_LOW() 354 355 if BYTE_0(arg2) == 1: 356 if BYTE_1(arg2) == 1: 357 SET_PIN_B_HIGH() 358 359 else: 360 SET_PIN_B_LOW() 361 362 else: 363 argr = 1 364 365WMI method ReadTotalofGPIOs([out] uint32 argr) 366---------------------------------------------- 367 368:: 369 370 argr = 0x02 371 372WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) 373------------------------------------------------------------------ 374 375:: 376 377 if BYTE_0(arg2) == 0: 378 argr = PIN_A_STATUS 379 380 if BYTE_0(arg2) == 1: 381 argr = PIN_B_STATUS 382 383Other information Methods 384========================= 385 386WMI method ReadChassisColor([out] uint32 argr) 387---------------------------------------------- 388 389:: 390 391 argr = CHASSIS_COLOR_ID 392 393Acknowledgements 394================ 395 396Kudos to `AlexIII <https://github.com/AlexIII/tcc-g15>`_ for documenting 397and testing available thermal profile codes. 398