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