1.. SPDX-License-Identifier: GPL-2.0-or-later 2 3============================================ 4Dell DDV WMI interface driver (dell-wmi-ddv) 5============================================ 6 7Introduction 8============ 9 10Many Dell notebooks made after ~2020 support a WMI-based interface for 11retrieving various system data like battery temperature, ePPID, diagnostic data 12and fan/thermal sensor data. 13 14This interface is likely used by the `Dell Data Vault` software on Windows, 15so it was called `DDV`. Currently the ``dell-wmi-ddv`` driver supports 16version 2 and 3 of the interface, with support for new interface versions 17easily added. 18 19.. warning:: The interface is regarded as internal by Dell, so no vendor 20 documentation is available. All knowledge was thus obtained by 21 trial-and-error, please keep that in mind. 22 23Dell ePPID (electronic Piece Part Identification) 24================================================= 25 26The Dell ePPID is used to uniquely identify components in Dell machines, 27including batteries. It has a form similar to `CC-PPPPPP-MMMMM-YMD-SSSS-FFF` 28and contains the following information: 29 30* Country code of origin (CC). 31* Part number with the first character being a filling number (PPPPPP). 32* Manufacture Identification (MMMMM). 33* Manufacturing Year/Month/Date (YMD) in base 36, with Y being the last digit 34 of the year. 35* Manufacture Sequence Number (SSSS). 36* Optional Firmware Version/Revision (FFF). 37 38The `eppidtool <https://pypi.org/project/eppidtool>`_ python utility can be used 39to decode and display this information. 40 41All information regarding the Dell ePPID was gathered using Dell support 42documentation and `this website <https://telcontar.net/KBK/Dell/date_codes>`_. 43 44WMI interface description 45========================= 46 47The WMI interface description can be decoded from the embedded binary MOF (bmof) 48data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 49 50:: 51 52 [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{8A42EA14-4F2A-FD45-6422-0087F7A7E608}")] 53 class DDVWmiMethodFunction { 54 [key, read] string InstanceName; 55 [read] boolean Active; 56 57 [WmiMethodId(1), Implemented, read, write, Description("Return Battery Design Capacity.")] void BatteryDesignCapacity([in] uint32 arg2, [out] uint32 argr); 58 [WmiMethodId(2), Implemented, read, write, Description("Return Battery Full Charge Capacity.")] void BatteryFullChargeCapacity([in] uint32 arg2, [out] uint32 argr); 59 [WmiMethodId(3), Implemented, read, write, Description("Return Battery Manufacture Name.")] void BatteryManufactureName([in] uint32 arg2, [out] string argr); 60 [WmiMethodId(4), Implemented, read, write, Description("Return Battery Manufacture Date.")] void BatteryManufactureDate([in] uint32 arg2, [out] uint32 argr); 61 [WmiMethodId(5), Implemented, read, write, Description("Return Battery Serial Number.")] void BatterySerialNumber([in] uint32 arg2, [out] uint32 argr); 62 [WmiMethodId(6), Implemented, read, write, Description("Return Battery Chemistry Value.")] void BatteryChemistryValue([in] uint32 arg2, [out] string argr); 63 [WmiMethodId(7), Implemented, read, write, Description("Return Battery Temperature.")] void BatteryTemperature([in] uint32 arg2, [out] uint32 argr); 64 [WmiMethodId(8), Implemented, read, write, Description("Return Battery Current.")] void BatteryCurrent([in] uint32 arg2, [out] uint32 argr); 65 [WmiMethodId(9), Implemented, read, write, Description("Return Battery Voltage.")] void BatteryVoltage([in] uint32 arg2, [out] uint32 argr); 66 [WmiMethodId(10), Implemented, read, write, Description("Return Battery Manufacture Access(MA code).")] void BatteryManufactureAceess([in] uint32 arg2, [out] uint32 argr); 67 [WmiMethodId(11), Implemented, read, write, Description("Return Battery Relative State-Of-Charge.")] void BatteryRelativeStateOfCharge([in] uint32 arg2, [out] uint32 argr); 68 [WmiMethodId(12), Implemented, read, write, Description("Return Battery Cycle Count")] void BatteryCycleCount([in] uint32 arg2, [out] uint32 argr); 69 [WmiMethodId(13), Implemented, read, write, Description("Return Battery ePPID")] void BatteryePPID([in] uint32 arg2, [out] string argr); 70 [WmiMethodId(14), Implemented, read, write, Description("Return Battery Raw Analytics Start")] void BatteryeRawAnalyticsStart([in] uint32 arg2, [out] uint32 argr); 71 [WmiMethodId(15), Implemented, read, write, Description("Return Battery Raw Analytics")] void BatteryeRawAnalytics([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 72 [WmiMethodId(16), Implemented, read, write, Description("Return Battery Design Voltage.")] void BatteryDesignVoltage([in] uint32 arg2, [out] uint32 argr); 73 [WmiMethodId(17), Implemented, read, write, Description("Return Battery Raw Analytics A Block")] void BatteryeRawAnalyticsABlock([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 74 [WmiMethodId(18), Implemented, read, write, Description("Return Version.")] void ReturnVersion([in] uint32 arg2, [out] uint32 argr); 75 [WmiMethodId(32), Implemented, read, write, Description("Return Fan Sensor Information")] void FanSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 76 [WmiMethodId(34), Implemented, read, write, Description("Return Thermal Sensor Information")] void ThermalSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 77 }; 78 79Each WMI method takes an ACPI buffer containing a 32-bit index as input argument, 80with the first 8 bit being used to specify the battery when using battery-related 81WMI methods. Other WMI methods may ignore this argument or interpret it 82differently. The WMI method output format varies: 83 84* if the function has only a single output, then an ACPI object 85 of the corresponding type is returned 86* if the function has multiple outputs, when an ACPI package 87 containing the outputs in the same order is returned 88 89The format of the output should be thoroughly checked, since many methods can 90return malformed data in case of an error. 91 92The data format of many battery-related methods seems to be based on the 93`Smart Battery Data Specification`, so unknown battery-related methods are 94likely to follow this standard in some way. 95 96WMI method GetBatteryDesignCapacity() 97------------------------------------- 98 99Returns the design capacity of the battery in mAh as an u16. 100 101WMI method BatteryFullCharge() 102------------------------------ 103 104Returns the full charge capacity of the battery in mAh as an u16. 105 106WMI method BatteryManufactureName() 107----------------------------------- 108 109Returns the manufacture name of the battery as an ASCII string. 110 111WMI method BatteryManufactureDate() 112----------------------------------- 113 114Returns the manufacture date of the battery as an u16. 115The date is encoded in the following manner: 116 117- bits 0 to 4 contain the manufacture day. 118- bits 5 to 8 contain the manufacture month. 119- bits 9 to 15 contain the manufacture year biased by 1980. 120 121WMI method BatterySerialNumber() 122-------------------------------- 123 124Returns the serial number of the battery as an u16. 125 126WMI method BatteryChemistryValue() 127---------------------------------- 128 129Returns the chemistry of the battery as an ASCII string. 130Known values are: 131 132- "Li-I" for Li-Ion 133 134WMI method BatteryTemperature() 135------------------------------- 136 137Returns the temperature of the battery in tenth degree kelvin as an u16. 138 139WMI method BatteryCurrent() 140--------------------------- 141 142Returns the current flow of the battery in mA as an s16. 143Negative values indicate discharging. 144 145WMI method BatteryVoltage() 146--------------------------- 147 148Returns the voltage flow of the battery in mV as an u16. 149 150WMI method BatteryManufactureAccess() 151------------------------------------- 152 153Returns the health status of the battery as a u16. 154The health status encoded in the following manner: 155 156 - the third nibble contains the general failure mode 157 - the fourth nibble contains the specific failure code 158 159Valid failure modes are: 160 161 - permanent failure (``0x9``) 162 - overheat failure (``0xa``) 163 - overcurrent failure (``0xb``) 164 165All other failure modes are to be considered normal. 166 167The following failure codes are valid for a permanent failure: 168 169 - fuse blown (``0x0``) 170 - cell imbalance (``0x1``) 171 - overvoltage (``0x2``) 172 - fet failure (``0x3``) 173 174The last two bits of the failure code are to be ignored when the battery 175signals a permanent failure. 176 177The following failure codes a valid for a overheat failure: 178 179 - overheat at start of charging (``0x5``) 180 - overheat during charging (``0x7``) 181 - overheat during discharging (``0x8``) 182 183The following failure codes are valid for a overcurrent failure: 184 185 - overcurrent during charging (``0x6``) 186 - overcurrent during discharging (``0xb``) 187 188WMI method BatteryRelativeStateOfCharge() 189----------------------------------------- 190 191Returns the capacity of the battery in percent as an u16. 192 193WMI method BatteryCycleCount() 194------------------------------ 195 196Returns the cycle count of the battery as an u16. 197 198WMI method BatteryePPID() 199------------------------- 200 201Returns the ePPID of the battery as an ASCII string. 202 203WMI method BatteryeRawAnalyticsStart() 204-------------------------------------- 205 206Performs an analysis of the battery and returns a status code: 207 208- ``0x0``: Success 209- ``0x1``: Interface not supported 210- ``0xfffffffe``: Error/Timeout 211 212.. note:: 213 The meaning of this method is still largely unknown. 214 215WMI method BatteryeRawAnalytics() 216--------------------------------- 217 218Returns a buffer usually containing 12 blocks of analytics data. 219Those blocks contain: 220 221- a block number starting with 0 (u8) 222- 31 bytes of unknown data 223 224.. note:: 225 The meaning of this method is still largely unknown. 226 227WMI method BatteryDesignVoltage() 228--------------------------------- 229 230Returns the design voltage of the battery in mV as an u16. 231 232WMI method BatteryeRawAnalyticsABlock() 233--------------------------------------- 234 235Returns a single block of analytics data, with the second byte 236of the index being used for selecting the block number. 237 238*Supported since WMI interface version 3!* 239 240.. note:: 241 The meaning of this method is still largely unknown. 242 243WMI method ReturnVersion() 244-------------------------- 245 246Returns the WMI interface version as an u32. 247 248WMI method FanSensorInformation() 249--------------------------------- 250 251Returns a buffer containing fan sensor entries, terminated 252with a single ``0xff``. 253Those entries contain: 254 255- fan type (u8) 256- fan speed in RPM (little endian u16) 257 258WMI method ThermalSensorInformation() 259------------------------------------- 260 261Returns a buffer containing thermal sensor entries, terminated 262with a single ``0xff``. 263Those entries contain: 264 265- thermal type (u8) 266- current temperature (s8) 267- min. temperature (s8) 268- max. temperature (s8) 269- unknown field (u8) 270 271.. note:: 272 TODO: Find out what the meaning of the last byte is. 273 274ACPI battery matching algorithm 275=============================== 276 277The algorithm used to match ACPI batteries to indices is based on information 278which was found inside the logging messages of the OEM software. 279 280Basically for each new ACPI battery, the serial numbers of the batteries behind 281indices 1 till 3 are compared with the serial number of the ACPI battery. 282Since the serial number of the ACPI battery can either be encoded as a normal 283integer or as a hexadecimal value, both cases need to be checked. The first 284index with a matching serial number is then selected. 285 286A serial number of 0 indicates that the corresponding index is not associated 287with an actual battery, or that the associated battery is not present. 288 289Some machines like the Dell Inspiron 3505 only support a single battery and thus 290ignore the battery index. Because of this the driver depends on the ACPI battery 291hook mechanism to discover batteries. 292 293Reverse-Engineering the DDV WMI interface 294========================================= 295 2961. Find a supported Dell notebook, usually made after ~2020. 2972. Dump the ACPI tables and search for the WMI device (usually called "ADDV"). 2983. Decode the corresponding bmof data and look at the ASL code. 2994. Try to deduce the meaning of a certain WMI method by comparing the control 300 flow with other ACPI methods (_BIX or _BIF for battery related methods 301 for example). 3025. Use the built-in UEFI diagnostics to view sensor types/values for fan/thermal 303 related methods (sometimes overwriting static ACPI data fields can be used 304 to test different sensor type values, since on some machines this data is 305 not reinitialized upon a warm reset). 306 307Alternatively: 308 3091. Load the ``dell-wmi-ddv`` driver, use the ``force`` module param 310 if necessary. 3112. Use the debugfs interface to access the raw fan/thermal sensor buffer data. 3123. Compare the data with the built-in UEFI diagnostics. 313 314In case the DDV WMI interface version available on your Dell notebook is not 315supported or you are seeing unknown fan/thermal sensors, please submit a 316bugreport on `bugzilla <https://bugzilla.kernel.org>`_ so they can be added 317to the ``dell-wmi-ddv`` driver. 318 319See Documentation/admin-guide/reporting-issues.rst for further information. 320