162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci============================================ 462306a36Sopenharmony_ciDell DDV WMI interface driver (dell-wmi-ddv) 562306a36Sopenharmony_ci============================================ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciIntroduction 862306a36Sopenharmony_ci============ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciMany Dell notebooks made after ~2020 support a WMI-based interface for 1162306a36Sopenharmony_ciretrieving various system data like battery temperature, ePPID, diagostic data 1262306a36Sopenharmony_ciand fan/thermal sensor data. 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciThis interface is likely used by the `Dell Data Vault` software on Windows, 1562306a36Sopenharmony_ciso it was called `DDV`. Currently the ``dell-wmi-ddv`` driver supports 1662306a36Sopenharmony_civersion 2 and 3 of the interface, with support for new interface versions 1762306a36Sopenharmony_cieasily added. 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci.. warning:: The interface is regarded as internal by Dell, so no vendor 2062306a36Sopenharmony_ci documentation is available. All knowledge was thus obtained by 2162306a36Sopenharmony_ci trial-and-error, please keep that in mind. 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciDell ePPID (electronic Piece Part Identification) 2462306a36Sopenharmony_ci================================================= 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciThe Dell ePPID is used to uniquely identify components in Dell machines, 2762306a36Sopenharmony_ciincluding batteries. It has a form similar to `CC-PPPPPP-MMMMM-YMD-SSSS-FFF` 2862306a36Sopenharmony_ciand contains the following information: 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci* Country code of origin (CC). 3162306a36Sopenharmony_ci* Part number with the first character being a filling number (PPPPPP). 3262306a36Sopenharmony_ci* Manufacture Identification (MMMMM). 3362306a36Sopenharmony_ci* Manufacturing Year/Month/Date (YMD) in base 36, with Y being the last digit 3462306a36Sopenharmony_ci of the year. 3562306a36Sopenharmony_ci* Manufacture Sequence Number (SSSS). 3662306a36Sopenharmony_ci* Optional Firmware Version/Revision (FFF). 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciThe `eppidtool <https://pypi.org/project/eppidtool>`_ python utility can be used 3962306a36Sopenharmony_cito decode and display this information. 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciAll information regarding the Dell ePPID was gathered using Dell support 4262306a36Sopenharmony_cidocumentation and `this website <https://telcontar.net/KBK/Dell/date_codes>`_. 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciWMI interface description 4562306a36Sopenharmony_ci========================= 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciThe WMI interface description can be decoded from the embedded binary MOF (bmof) 4862306a36Sopenharmony_cidata using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci:: 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{8A42EA14-4F2A-FD45-6422-0087F7A7E608}")] 5362306a36Sopenharmony_ci class DDVWmiMethodFunction { 5462306a36Sopenharmony_ci [key, read] string InstanceName; 5562306a36Sopenharmony_ci [read] boolean Active; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci [WmiMethodId(1), Implemented, read, write, Description("Return Battery Design Capacity.")] void BatteryDesignCapacity([in] uint32 arg2, [out] uint32 argr); 5862306a36Sopenharmony_ci [WmiMethodId(2), Implemented, read, write, Description("Return Battery Full Charge Capacity.")] void BatteryFullChargeCapacity([in] uint32 arg2, [out] uint32 argr); 5962306a36Sopenharmony_ci [WmiMethodId(3), Implemented, read, write, Description("Return Battery Manufacture Name.")] void BatteryManufactureName([in] uint32 arg2, [out] string argr); 6062306a36Sopenharmony_ci [WmiMethodId(4), Implemented, read, write, Description("Return Battery Manufacture Date.")] void BatteryManufactureDate([in] uint32 arg2, [out] uint32 argr); 6162306a36Sopenharmony_ci [WmiMethodId(5), Implemented, read, write, Description("Return Battery Serial Number.")] void BatterySerialNumber([in] uint32 arg2, [out] uint32 argr); 6262306a36Sopenharmony_ci [WmiMethodId(6), Implemented, read, write, Description("Return Battery Chemistry Value.")] void BatteryChemistryValue([in] uint32 arg2, [out] string argr); 6362306a36Sopenharmony_ci [WmiMethodId(7), Implemented, read, write, Description("Return Battery Temperature.")] void BatteryTemperature([in] uint32 arg2, [out] uint32 argr); 6462306a36Sopenharmony_ci [WmiMethodId(8), Implemented, read, write, Description("Return Battery Current.")] void BatteryCurrent([in] uint32 arg2, [out] uint32 argr); 6562306a36Sopenharmony_ci [WmiMethodId(9), Implemented, read, write, Description("Return Battery Voltage.")] void BatteryVoltage([in] uint32 arg2, [out] uint32 argr); 6662306a36Sopenharmony_ci [WmiMethodId(10), Implemented, read, write, Description("Return Battery Manufacture Access(MA code).")] void BatteryManufactureAceess([in] uint32 arg2, [out] uint32 argr); 6762306a36Sopenharmony_ci [WmiMethodId(11), Implemented, read, write, Description("Return Battery Relative State-Of-Charge.")] void BatteryRelativeStateOfCharge([in] uint32 arg2, [out] uint32 argr); 6862306a36Sopenharmony_ci [WmiMethodId(12), Implemented, read, write, Description("Return Battery Cycle Count")] void BatteryCycleCount([in] uint32 arg2, [out] uint32 argr); 6962306a36Sopenharmony_ci [WmiMethodId(13), Implemented, read, write, Description("Return Battery ePPID")] void BatteryePPID([in] uint32 arg2, [out] string argr); 7062306a36Sopenharmony_ci [WmiMethodId(14), Implemented, read, write, Description("Return Battery Raw Analytics Start")] void BatteryeRawAnalyticsStart([in] uint32 arg2, [out] uint32 argr); 7162306a36Sopenharmony_ci [WmiMethodId(15), Implemented, read, write, Description("Return Battery Raw Analytics")] void BatteryeRawAnalytics([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 7262306a36Sopenharmony_ci [WmiMethodId(16), Implemented, read, write, Description("Return Battery Design Voltage.")] void BatteryDesignVoltage([in] uint32 arg2, [out] uint32 argr); 7362306a36Sopenharmony_ci [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[]); 7462306a36Sopenharmony_ci [WmiMethodId(18), Implemented, read, write, Description("Return Version.")] void ReturnVersion([in] uint32 arg2, [out] uint32 argr); 7562306a36Sopenharmony_ci [WmiMethodId(32), Implemented, read, write, Description("Return Fan Sensor Information")] void FanSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 7662306a36Sopenharmony_ci [WmiMethodId(34), Implemented, read, write, Description("Return Thermal Sensor Information")] void ThermalSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); 7762306a36Sopenharmony_ci }; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciEach WMI method takes an ACPI buffer containing a 32-bit index as input argument, 8062306a36Sopenharmony_ciwith the first 8 bit being used to specify the battery when using battery-related 8162306a36Sopenharmony_ciWMI methods. Other WMI methods may ignore this argument or interpret it 8262306a36Sopenharmony_cidifferently. The WMI method output format varies: 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci* if the function has only a single output, then an ACPI object 8562306a36Sopenharmony_ci of the corresponding type is returned 8662306a36Sopenharmony_ci* if the function has multiple outputs, when an ACPI package 8762306a36Sopenharmony_ci containing the outputs in the same order is returned 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciThe format of the output should be thoroughly checked, since many methods can 9062306a36Sopenharmony_cireturn malformed data in case of an error. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciThe data format of many battery-related methods seems to be based on the 9362306a36Sopenharmony_ci`Smart Battery Data Specification`, so unknown battery-related methods are 9462306a36Sopenharmony_cilikely to follow this standard in some way. 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciWMI method GetBatteryDesignCapacity() 9762306a36Sopenharmony_ci------------------------------------- 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciReturns the design capacity of the battery in mAh as an u16. 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciWMI method BatteryFullCharge() 10262306a36Sopenharmony_ci------------------------------ 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciReturns the full charge capacity of the battery in mAh as an u16. 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ciWMI method BatteryManufactureName() 10762306a36Sopenharmony_ci----------------------------------- 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciReturns the manufacture name of the battery as an ASCII string. 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciWMI method BatteryManufactureDate() 11262306a36Sopenharmony_ci----------------------------------- 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciReturns the manufacture date of the battery as an u16. 11562306a36Sopenharmony_ciThe date is encoded in the following manner: 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci- bits 0 to 4 contain the manufacture day. 11862306a36Sopenharmony_ci- bits 5 to 8 contain the manufacture month. 11962306a36Sopenharmony_ci- bits 9 to 15 contain the manufacture year biased by 1980. 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci.. note:: 12262306a36Sopenharmony_ci The data format needs to be verified on more machines. 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciWMI method BatterySerialNumber() 12562306a36Sopenharmony_ci-------------------------------- 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciReturns the serial number of the battery as an u16. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciWMI method BatteryChemistryValue() 13062306a36Sopenharmony_ci---------------------------------- 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciReturns the chemistry of the battery as an ASCII string. 13362306a36Sopenharmony_ciKnown values are: 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci- "Li-I" for Li-Ion 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ciWMI method BatteryTemperature() 13862306a36Sopenharmony_ci------------------------------- 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciReturns the temperature of the battery in tenth degree kelvin as an u16. 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciWMI method BatteryCurrent() 14362306a36Sopenharmony_ci--------------------------- 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciReturns the current flow of the battery in mA as an s16. 14662306a36Sopenharmony_ciNegative values indicate discharging. 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciWMI method BatteryVoltage() 14962306a36Sopenharmony_ci--------------------------- 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciReturns the voltage flow of the battery in mV as an u16. 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciWMI method BatteryManufactureAccess() 15462306a36Sopenharmony_ci------------------------------------- 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciReturns a manufacture-defined value as an u16. 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciWMI method BatteryRelativeStateOfCharge() 15962306a36Sopenharmony_ci----------------------------------------- 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciReturns the capacity of the battery in percent as an u16. 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciWMI method BatteryCycleCount() 16462306a36Sopenharmony_ci------------------------------ 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciReturns the cycle count of the battery as an u16. 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciWMI method BatteryePPID() 16962306a36Sopenharmony_ci------------------------- 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciReturns the ePPID of the battery as an ASCII string. 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciWMI method BatteryeRawAnalyticsStart() 17462306a36Sopenharmony_ci-------------------------------------- 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciPerforms an analysis of the battery and returns a status code: 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci- ``0x0``: Success 17962306a36Sopenharmony_ci- ``0x1``: Interface not supported 18062306a36Sopenharmony_ci- ``0xfffffffe``: Error/Timeout 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci.. note:: 18362306a36Sopenharmony_ci The meaning of this method is still largely unknown. 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciWMI method BatteryeRawAnalytics() 18662306a36Sopenharmony_ci--------------------------------- 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ciReturns a buffer usually containing 12 blocks of analytics data. 18962306a36Sopenharmony_ciThose blocks contain: 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci- a block number starting with 0 (u8) 19262306a36Sopenharmony_ci- 31 bytes of unknown data 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci.. note:: 19562306a36Sopenharmony_ci The meaning of this method is still largely unknown. 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciWMI method BatteryDesignVoltage() 19862306a36Sopenharmony_ci--------------------------------- 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciReturns the design voltage of the battery in mV as an u16. 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciWMI method BatteryeRawAnalyticsABlock() 20362306a36Sopenharmony_ci--------------------------------------- 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciReturns a single block of analytics data, with the second byte 20662306a36Sopenharmony_ciof the index being used for selecting the block number. 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci*Supported since WMI interface version 3!* 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci.. note:: 21162306a36Sopenharmony_ci The meaning of this method is still largely unknown. 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ciWMI method ReturnVersion() 21462306a36Sopenharmony_ci-------------------------- 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ciReturns the WMI interface version as an u32. 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciWMI method FanSensorInformation() 21962306a36Sopenharmony_ci--------------------------------- 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciReturns a buffer containing fan sensor entries, terminated 22262306a36Sopenharmony_ciwith a single ``0xff``. 22362306a36Sopenharmony_ciThose entries contain: 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci- fan type (u8) 22662306a36Sopenharmony_ci- fan speed in RPM (little endian u16) 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ciWMI method ThermalSensorInformation() 22962306a36Sopenharmony_ci------------------------------------- 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciReturns a buffer containing thermal sensor entries, terminated 23262306a36Sopenharmony_ciwith a single ``0xff``. 23362306a36Sopenharmony_ciThose entries contain: 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci- thermal type (u8) 23662306a36Sopenharmony_ci- current temperature (s8) 23762306a36Sopenharmony_ci- min. temperature (s8) 23862306a36Sopenharmony_ci- max. temperature (s8) 23962306a36Sopenharmony_ci- unknown field (u8) 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci.. note:: 24262306a36Sopenharmony_ci TODO: Find out what the meaning of the last byte is. 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ciACPI battery matching algorithm 24562306a36Sopenharmony_ci=============================== 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciThe algorithm used to match ACPI batteries to indices is based on information 24862306a36Sopenharmony_ciwhich was found inside the logging messages of the OEM software. 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciBasically for each new ACPI battery, the serial numbers of the batteries behind 25162306a36Sopenharmony_ciindices 1 till 3 are compared with the serial number of the ACPI battery. 25262306a36Sopenharmony_ciSince the serial number of the ACPI battery can either be encoded as a normal 25362306a36Sopenharmony_ciinteger or as a hexadecimal value, both cases need to be checked. The first 25462306a36Sopenharmony_ciindex with a matching serial number is then selected. 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciA serial number of 0 indicates that the corresponding index is not associated 25762306a36Sopenharmony_ciwith an actual battery, or that the associated battery is not present. 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ciSome machines like the Dell Inspiron 3505 only support a single battery and thus 26062306a36Sopenharmony_ciignore the battery index. Because of this the driver depends on the ACPI battery 26162306a36Sopenharmony_cihook mechanism to discover batteries. 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci.. note:: 26462306a36Sopenharmony_ci The ACPI battery matching algorithm currently used inside the driver is 26562306a36Sopenharmony_ci outdated and does not match the algorithm described above. The reasons for 26662306a36Sopenharmony_ci this are differences in the handling of the ToHexString() ACPI opcode between 26762306a36Sopenharmony_ci Linux and Windows, which distorts the serial number of ACPI batteries on many 26862306a36Sopenharmony_ci machines. Until this issue is resolved, the driver cannot use the above 26962306a36Sopenharmony_ci algorithm. 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciReverse-Engineering the DDV WMI interface 27262306a36Sopenharmony_ci========================================= 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci1. Find a supported Dell notebook, usually made after ~2020. 27562306a36Sopenharmony_ci2. Dump the ACPI tables and search for the WMI device (usually called "ADDV"). 27662306a36Sopenharmony_ci3. Decode the corresponding bmof data and look at the ASL code. 27762306a36Sopenharmony_ci4. Try to deduce the meaning of a certain WMI method by comparing the control 27862306a36Sopenharmony_ci flow with other ACPI methods (_BIX or _BIF for battery related methods 27962306a36Sopenharmony_ci for example). 28062306a36Sopenharmony_ci5. Use the built-in UEFI diagostics to view sensor types/values for fan/thermal 28162306a36Sopenharmony_ci related methods (sometimes overwriting static ACPI data fields can be used 28262306a36Sopenharmony_ci to test different sensor type values, since on some machines this data is 28362306a36Sopenharmony_ci not reinitialized upon a warm reset). 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciAlternatively: 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci1. Load the ``dell-wmi-ddv`` driver, use the ``force`` module param 28862306a36Sopenharmony_ci if necessary. 28962306a36Sopenharmony_ci2. Use the debugfs interface to access the raw fan/thermal sensor buffer data. 29062306a36Sopenharmony_ci3. Compare the data with the built-in UEFI diagnostics. 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciIn case the DDV WMI interface version available on your Dell notebook is not 29362306a36Sopenharmony_cisupported or you are seeing unknown fan/thermal sensors, please submit a 29462306a36Sopenharmony_cibugreport on `bugzilla <https://bugzilla.kernel.org>`_ so they can be added 29562306a36Sopenharmony_cito the ``dell-wmi-ddv`` driver. 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciSee Documentation/admin-guide/reporting-issues.rst for further information. 298