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