€•ŒŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ0/translations/zh_CN/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/zh_TW/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/it_IT/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ja_JP/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/ko_KR/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/pt_BR/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ0/translations/sp_SP/wmi/driver-development-guide”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ)SPDX-License-Identifier: GPL-2.0-or-later”h]”hŒ)SPDX-License-Identifier: GPL-2.0-or-later”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒJ/var/lib/git/docbuild/linux/Documentation/wmi/driver-development-guide.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒWMI driver development guide”h]”hŒWMI driver development guide”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hXaThe WMI subsystem provides a rich driver API for implementing WMI drivers, documented at Documentation/driver-api/wmi.rst. This document will serve as an introductory guide for WMI driver writers using this API. It is supposed to be a successor to the original LWN article [1]_ which deals with WMI drivers using the deprecated GUID-based WMI interface.”h]”(hXThe WMI subsystem provides a rich driver API for implementing WMI drivers, documented at Documentation/driver-api/wmi.rst. This document will serve as an introductory guide for WMI driver writers using this API. It is supposed to be a successor to the original LWN article ”…””}”(hhßh²hh³Nh´NubhŒfootnote_reference”“”)”}”(hŒ[1]_”h]”hŒ1”…””}”(hhéh²hh³Nh´Nubah}”(h]”Œid1”ah ]”h"]”h$]”h&]”Œrefid”Œid2”Œdocname”Œwmi/driver-development-guide”uh1hçhhߌresolved”KubhŒL which deals with WMI drivers using the deprecated GUID-based WMI interface.”…””}”(hhßh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Obtaining WMI device information”h]”hŒ Obtaining WMI device information”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KubhÞ)”}”(hŒéBefore developing an WMI driver, information about the WMI device in question must be obtained. The `lswmi `_ utility can be used to extract detailed WMI device information using the following command:”h]”(hŒdBefore developing an WMI driver, information about the WMI device in question must be obtained. The ”…””}”(hjh²hh³Nh´NubhŒ reference”“”)”}”(hŒ)`lswmi `_”h]”hŒlswmi”…””}”(hj"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œlswmi”Œrefuri”Œhttps://pypi.org/project/lswmi”uh1j hjubhŒtarget”“”)”}”(hŒ! ”h]”h}”(h]”Œlswmi”ah ]”h"]”Œlswmi”ah$]”h&]”Œrefuri”j3uh1j4Œ referenced”KhjubhŒ\ utility can be used to extract detailed WMI device information using the following command:”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhŒ literal_block”“”)”}”(hŒlswmi -V”h]”hŒlswmi -V”…””}”hjPsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jNh³hÇh´Khjh²hubhÞ)”}”(hŒ~The resulting output will contain information about all WMI devices available on a given machine, plus some extra information.”h]”hŒ~The resulting output will contain information about all WMI devices available on a given machine, plus some extra information.”…””}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhÞ)”}”(hX_In order to find out more about the interface used to communicate with a WMI device, the `bmfdec `_ utilities can be used to decode the Binary MOF (Managed Object Format) information used to describe WMI devices. The ``wmi-bmof`` driver exposes this information to userspace, see Documentation/wmi/devices/wmi-bmof.rst.”h]”(hŒYIn order to find out more about the interface used to communicate with a WMI device, the ”…””}”(hjlh²hh³Nh´Nubj!)”}”(hŒ*`bmfdec `_”h]”hŒbmfdec”…””}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œbmfdec”j2Œhttps://github.com/pali/bmfdec”uh1j hjlubj5)”}”(hŒ! ”h]”h}”(h]”Œbmfdec”ah ]”h"]”Œbmfdec”ah$]”h&]”Œrefuri”j„uh1j4jCKhjlubhŒv utilities can be used to decode the Binary MOF (Managed Object Format) information used to describe WMI devices. The ”…””}”(hjlh²hh³Nh´NubhŒliteral”“”)”}”(hŒ ``wmi-bmof``”h]”hŒwmi-bmof”…””}”(hj˜h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hjlubhŒZ driver exposes this information to userspace, see Documentation/wmi/devices/wmi-bmof.rst.”…””}”(hjlh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhÞ)”}”(hŒcIn order to retrieve the decoded Binary MOF information, use the following command (requires root):”h]”hŒcIn order to retrieve the decoded Binary MOF information, use the following command (requires root):”…””}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K!hjh²hubjO)”}”(hŒL./bmf2mof /sys/bus/wmi/devices/05901221-D566-11D1-B2F0-00A0C9062910[-X]/bmof”h]”hŒL./bmf2mof /sys/bus/wmi/devices/05901221-D566-11D1-B2F0-00A0C9062910[-X]/bmof”…””}”hj¾sbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jNh³hÇh´K%hjh²hubhÞ)”}”(hXSometimes, looking at the disassembled ACPI tables used to describe the WMI device helps in understanding how the WMI device is supposed to work. The path of the ACPI method associated with a given WMI device can be retrieved using the ``lswmi`` utility as mentioned above.”h]”(hŒìSometimes, looking at the disassembled ACPI tables used to describe the WMI device helps in understanding how the WMI device is supposed to work. The path of the ACPI method associated with a given WMI device can be retrieved using the ”…””}”(hjÌh²hh³Nh´Nubj—)”}”(hŒ ``lswmi``”h]”hŒlswmi”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hjÌubhŒ utility as mentioned above.”…””}”(hjÌh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K'hjh²hubhÞ)”}”(hŒÚIf you are attempting to port a driver to Linux and are working on a Windows system, `WMIExplorer `_ can be useful for inspecting available WMI methods and invoking them directly.”h]”(hŒUIf you are attempting to port a driver to Linux and are working on a Windows system, ”…””}”(hjìh²hh³Nh´Nubj!)”}”(hŒ6`WMIExplorer `_”h]”hŒ WMIExplorer”…””}”(hjôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œ WMIExplorer”j2Œ%https://github.com/vinaypamnani/wmie2”uh1j hjìubj5)”}”(hŒ( ”h]”h}”(h]”Œ wmiexplorer”ah ]”h"]”Œ wmiexplorer”ah$]”h&]”Œrefuri”juh1j4jCKhjìubhŒO can be useful for inspecting available WMI methods and invoking them directly.”…””}”(hjìh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K,hjh²hubeh}”(h]”Œ obtaining-wmi-device-information”ah ]”h"]”Œ obtaining wmi device information”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒBasic WMI driver structure”h]”hŒBasic WMI driver structure”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj$h²hh³hÇh´K1ubhÞ)”}”(hŒ‹The basic WMI driver is build around the struct wmi_driver, which is then bound to matching WMI devices using a struct wmi_device_id table:”h]”hŒ‹The basic WMI driver is build around the struct wmi_driver, which is then bound to matching WMI devices using a struct wmi_device_id table:”…””}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K3hj$h²hubjO)”}”(hX¦static const struct wmi_device_id foo_id_table[] = { /* Only use uppercase letters! */ { "936DA01F-9ABD-4D9D-80C7-02AF85C822A8", NULL }, { } }; MODULE_DEVICE_TABLE(wmi, foo_id_table); static struct wmi_driver foo_driver = { .driver = { .name = "foo", .probe_type = PROBE_PREFER_ASYNCHRONOUS, /* recommended */ .pm = pm_sleep_ptr(&foo_dev_pm_ops), /* optional */ }, .id_table = foo_id_table, .probe = foo_probe, .remove = foo_remove, /* optional, devres is preferred */ .shutdown = foo_shutdown, /* optional, called during shutdown */ .notify_new = foo_notify, /* optional, for event handling */ .min_event_size = X, /* optional, simplifies event payload size verification */ .no_singleton = true, /* required for new WMI drivers */ }; module_wmi_driver(foo_driver);”h]”hX¦static const struct wmi_device_id foo_id_table[] = { /* Only use uppercase letters! */ { "936DA01F-9ABD-4D9D-80C7-02AF85C822A8", NULL }, { } }; MODULE_DEVICE_TABLE(wmi, foo_id_table); static struct wmi_driver foo_driver = { .driver = { .name = "foo", .probe_type = PROBE_PREFER_ASYNCHRONOUS, /* recommended */ .pm = pm_sleep_ptr(&foo_dev_pm_ops), /* optional */ }, .id_table = foo_id_table, .probe = foo_probe, .remove = foo_remove, /* optional, devres is preferred */ .shutdown = foo_shutdown, /* optional, called during shutdown */ .notify_new = foo_notify, /* optional, for event handling */ .min_event_size = X, /* optional, simplifies event payload size verification */ .no_singleton = true, /* required for new WMI drivers */ }; module_wmi_driver(foo_driver);”…””}”hjCsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jNh³hÇh´K8hj$h²hubhÞ)”}”(hŒáThe probe() callback is called when the WMI driver is bound to a matching WMI device. Allocating driver-specific data structures and initialising interfaces to other kernel subsystems should normally be done in this function.”h]”hŒáThe probe() callback is called when the WMI driver is bound to a matching WMI device. Allocating driver-specific data structures and initialising interfaces to other kernel subsystems should normally be done in this function.”…””}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KOhj$h²hubhÞ)”}”(hX`The remove() callback is then called when the WMI driver is unbound from a WMI device. In order to unregister interfaces to other kernel subsystems and release resources, devres should be used. This simplifies error handling during probe and often allows to omit this callback entirely, see Documentation/driver-api/driver-model/devres.rst for details.”h]”hX`The remove() callback is then called when the WMI driver is unbound from a WMI device. In order to unregister interfaces to other kernel subsystems and release resources, devres should be used. This simplifies error handling during probe and often allows to omit this callback entirely, see Documentation/driver-api/driver-model/devres.rst for details.”…””}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KShj$h²hubhÞ)”}”(hX!The shutdown() callback is called during shutdown, reboot or kexec. Its sole purpose is to disable the WMI device and put it in a well-known state for the WMI driver to pick up later after reboot or kexec. Most WMI drivers need no special shutdown handling and can thus omit this callback.”h]”hX!The shutdown() callback is called during shutdown, reboot or kexec. Its sole purpose is to disable the WMI device and put it in a well-known state for the WMI driver to pick up later after reboot or kexec. Most WMI drivers need no special shutdown handling and can thus omit this callback.”…””}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KXhj$h²hubhÞ)”}”(hX5Please note that new WMI drivers are required to be able to be instantiated multiple times, and are forbidden from using any deprecated GUID-based or ACPI-based WMI functions. This means that the WMI driver should be prepared for the scenario that multiple matching WMI devices are present on a given machine.”h]”hX5Please note that new WMI drivers are required to be able to be instantiated multiple times, and are forbidden from using any deprecated GUID-based or ACPI-based WMI functions. This means that the WMI driver should be prepared for the scenario that multiple matching WMI devices are present on a given machine.”…””}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K\hj$h²hubhÞ)”}”(hŒ•Because of this, WMI drivers should use the state container design pattern as described in Documentation/driver-api/driver-model/design-patterns.rst.”h]”hŒ•Because of this, WMI drivers should use the state container design pattern as described in Documentation/driver-api/driver-model/design-patterns.rst.”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kahj$h²hubhŒwarning”“”)”}”(hŒÜUsing both GUID-based and non-GUID-based functions for querying WMI data blocks and handling WMI events simultaneously on the same device is guaranteed to corrupt the WMI device state and might lead to erratic behaviour.”h]”hÞ)”}”(hŒÜUsing both GUID-based and non-GUID-based functions for querying WMI data blocks and handling WMI events simultaneously on the same device is guaranteed to corrupt the WMI device state and might lead to erratic behaviour.”h]”hŒÜUsing both GUID-based and non-GUID-based functions for querying WMI data blocks and handling WMI events simultaneously on the same device is guaranteed to corrupt the WMI device state and might lead to erratic behaviour.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kdhj™ubah}”(h]”h ]”h"]”h$]”h&]”uh1j—hj$h²hh³hÇh´Nubeh}”(h]”Œbasic-wmi-driver-structure”ah ]”h"]”Œbasic wmi driver structure”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K1ubhÉ)”}”(hhh]”(hÎ)”}”(hŒWMI method drivers”h]”hŒWMI method drivers”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¹h²hh³hÇh´KiubhÞ)”}”(hXlWMI drivers can call WMI device methods using wmidev_invoke_method(). For each WMI method invocation the WMI driver needs to provide the instance number and the method ID, as well as a buffer with the method arguments and optionally a buffer for the results. When calling WMI methods that do not return any values, wmidev_invoke_procedure() should be used instead.”h]”hXlWMI drivers can call WMI device methods using wmidev_invoke_method(). For each WMI method invocation the WMI driver needs to provide the instance number and the method ID, as well as a buffer with the method arguments and optionally a buffer for the results. When calling WMI methods that do not return any values, wmidev_invoke_procedure() should be used instead.”…””}”(hjÊh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kkhj¹h²hubhÞ)”}”(hXÊThe layout of said buffers is device-specific and described by the Binary MOF data associated with a given WMI device. Said Binary MOF data also describes the method ID of a given WMI method with the ``WmiMethodId`` qualifier. WMI devices exposing WMI methods usually expose only a single instance (instance number 0), but in theory can expose multiple instances as well. In such a case the number of instances can be retrieved using wmidev_instance_count().”h]”(hŒÈThe layout of said buffers is device-specific and described by the Binary MOF data associated with a given WMI device. Said Binary MOF data also describes the method ID of a given WMI method with the ”…””}”(hjØh²hh³Nh´Nubj—)”}”(hŒ``WmiMethodId``”h]”hŒ WmiMethodId”…””}”(hjàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hjØubhŒó qualifier. WMI devices exposing WMI methods usually expose only a single instance (instance number 0), but in theory can expose multiple instances as well. In such a case the number of instances can be retrieved using wmidev_instance_count().”…””}”(hjØh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kphj¹h²hubhÞ)”}”(hŒ]Take a look at drivers/platform/x86/intel/wmi/thunderbolt.c for an example WMI method driver.”h]”hŒ]Take a look at drivers/platform/x86/intel/wmi/thunderbolt.c for an example WMI method driver.”…””}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kvhj¹h²hubeh}”(h]”Œwmi-method-drivers”ah ]”h"]”Œwmi method drivers”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KiubhÉ)”}”(hhh]”(hÎ)”}”(hŒWMI data block drivers”h]”hŒWMI data block drivers”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KyubhÞ)”}”(hXLWMI drivers can query WMI data blocks using wmidev_query_block(), the layout of the returned buffer is again device-specific and described by the Binary MOF data. Some WMI data blocks are also writeable and can be set using wmidev_set_block(). The number of data block instances can again be retrieved using wmidev_instance_count().”h]”hXLWMI drivers can query WMI data blocks using wmidev_query_block(), the layout of the returned buffer is again device-specific and described by the Binary MOF data. Some WMI data blocks are also writeable and can be set using wmidev_set_block(). The number of data block instances can again be retrieved using wmidev_instance_count().”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K{hjh²hubhÞ)”}”(hŒcTake a look at drivers/platform/x86/intel/wmi/sbl-fw-update.c for an example WMI data block driver.”h]”hŒcTake a look at drivers/platform/x86/intel/wmi/sbl-fw-update.c for an example WMI data block driver.”…””}”(hj-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K€hjh²hubeh}”(h]”Œwmi-data-block-drivers”ah ]”h"]”Œwmi data block drivers”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KyubhÉ)”}”(hhh]”(hÎ)”}”(hŒWMI event drivers”h]”hŒWMI event drivers”…””}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjCh²hh³hÇh´KƒubhÞ)”}”(hXRWMI drivers can receive WMI events via the notify_new() callback inside the struct wmi_driver. The WMI subsystem will then take care of setting up the WMI event accordingly. Please note that the layout of the buffer passed to this callback is device-specific, and freeing of the buffer is done by the WMI subsystem itself, not the driver.”h]”hXRWMI drivers can receive WMI events via the notify_new() callback inside the struct wmi_driver. The WMI subsystem will then take care of setting up the WMI event accordingly. Please note that the layout of the buffer passed to this callback is device-specific, and freeing of the buffer is done by the WMI subsystem itself, not the driver.”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K…hjCh²hubhÞ)”}”(hŒùThe WMI driver core will take care that the notify_new() callback will only be called after the probe() callback has been called, and that no events are being received by the driver right before and after calling its remove() or shutdown() callback.”h]”hŒùThe WMI driver core will take care that the notify_new() callback will only be called after the probe() callback has been called, and that no events are being received by the driver right before and after calling its remove() or shutdown() callback.”…””}”(hjbh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KŠhjCh²hubhÞ)”}”(hŒ±However WMI driver developers should be aware that multiple WMI events can be received concurrently, so any locking (if necessary) needs to be provided by the WMI driver itself.”h]”hŒ±However WMI driver developers should be aware that multiple WMI events can be received concurrently, so any locking (if necessary) needs to be provided by the WMI driver itself.”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KŽhjCh²hubhÞ)”}”(hX4The WMI driver can furthermore instruct the WMI driver core to automatically reject WMI events that contain a undersized event payload by populating the ``min_event_size`` field inside struct wmi_driver. Setting this field to 0 will thus enable the WMI driver to receive WMI events without any event payload.”h]”(hŒ™The WMI driver can furthermore instruct the WMI driver core to automatically reject WMI events that contain a undersized event payload by populating the ”…””}”(hj~h²hh³Nh´Nubj—)”}”(hŒ``min_event_size``”h]”hŒmin_event_size”…””}”(hj†h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hj~ubhŒ‰ field inside struct wmi_driver. Setting this field to 0 will thus enable the WMI driver to receive WMI events without any event payload.”…””}”(hj~h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K‘hjCh²hubhÞ)”}”(hŒQTake a look at drivers/platform/x86/xiaomi-wmi.c for an example WMI event driver.”h]”hŒQTake a look at drivers/platform/x86/xiaomi-wmi.c for an example WMI event driver.”…””}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K–hjCh²hubeh}”(h]”Œwmi-event-drivers”ah ]”h"]”Œwmi event drivers”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KƒubhÉ)”}”(hhh]”(hÎ)”}”(hŒ(Exchanging data with the WMI driver core”h]”hŒ(Exchanging data with the WMI driver core”…””}”(hj·h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj´h²hh³hÇh´K™ubhÞ)”}”(hX#WMI drivers can exchange data with the WMI driver core using struct wmi_buffer. The internal structure of those buffers is device-specific and only known by the WMI driver. Because of this the WMI driver itself is responsible for parsing and validating the data received from its WMI device.”h]”hX#WMI drivers can exchange data with the WMI driver core using struct wmi_buffer. The internal structure of those buffers is device-specific and only known by the WMI driver. Because of this the WMI driver itself is responsible for parsing and validating the data received from its WMI device.”…””}”(hjÅh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K›hj´h²hubhÞ)”}”(hX¬The structure of said buffers is described by the MOF data associated with the WMI device in question. When such a buffer contains multiple data items it usually makes sense to define a C structure and use it during parsing. Since the WMI driver core guarantees that all buffers received from a WMI device are aligned on an 8-byte boundary, WMI drivers can simply perform a cast between the WMI buffer data and this C structure.”h]”hX¬The structure of said buffers is described by the MOF data associated with the WMI device in question. When such a buffer contains multiple data items it usually makes sense to define a C structure and use it during parsing. Since the WMI driver core guarantees that all buffers received from a WMI device are aligned on an 8-byte boundary, WMI drivers can simply perform a cast between the WMI buffer data and this C structure.”…””}”(hjÓh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hj´h²hubhÞ)”}”(hXYThis however should only be done after the size of the buffer was verified to be large enough to hold the whole C structure. WMI drivers should reject undersized buffers as they are usually sent by the WMI device to signal an internal error. Oversized buffers however should be accepted to emulate the behavior of the Windows WMI implementation.”h]”hXYThis however should only be done after the size of the buffer was verified to be large enough to hold the whole C structure. WMI drivers should reject undersized buffers as they are usually sent by the WMI device to signal an internal error. Oversized buffers however should be accepted to emulate the behavior of the Windows WMI implementation.”…””}”(hjáh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¦hj´h²hubhÞ)”}”(hX}When defining a C structure for parsing WMI buffers the alignment of the data items should be respected. This is especially important for 64-bit integers as those have different alignments on 64-bit (8-byte alignment) and 32-bit (4-byte alignment) architectures. It is thus a good idea to manually specify the alignment of such data items or mark the whole structure as packed when appropriate. Integer data items in general are little-endian integers and should be marked as such using ``__le64`` and friends. When parsing WMI string data items the struct wmi_string should be used as WMI strings have a different layout than C strings.”h]”(hXçWhen defining a C structure for parsing WMI buffers the alignment of the data items should be respected. This is especially important for 64-bit integers as those have different alignments on 64-bit (8-byte alignment) and 32-bit (4-byte alignment) architectures. It is thus a good idea to manually specify the alignment of such data items or mark the whole structure as packed when appropriate. Integer data items in general are little-endian integers and should be marked as such using ”…””}”(hjïh²hh³Nh´Nubj—)”}”(hŒ ``__le64``”h]”hŒ__le64”…””}”(hj÷h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j–hjïubhŒŒ and friends. When parsing WMI string data items the struct wmi_string should be used as WMI strings have a different layout than C strings.”…””}”(hjïh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K«hj´h²hubhÞ)”}”(hŒlSee Documentation/wmi/acpi-interface.rst for more information regarding the binary format of WMI data items.”h]”hŒlSee Documentation/wmi/acpi-interface.rst for more information regarding the binary format of WMI data items.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K³hj´h²hubeh}”(h]”Œ(exchanging-data-with-the-wmi-driver-core”ah ]”h"]”Œ(exchanging data with the wmi driver core”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K™ubhÉ)”}”(hhh]”(hÎ)”}”(hŒ%Handling multiple WMI devices at once”h]”hŒ%Handling multiple WMI devices at once”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj%h²hh³hÇh´K·ubhÞ)”}”(hXThere are many cases of firmware vendors using multiple WMI devices to control different aspects of a single physical device. This can make developing WMI drivers complicated, as those drivers might need to communicate with each other to present a unified interface to userspace.”h]”hXThere are many cases of firmware vendors using multiple WMI devices to control different aspects of a single physical device. This can make developing WMI drivers complicated, as those drivers might need to communicate with each other to present a unified interface to userspace.”…””}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¹hj%h²hubhÞ)”}”(hŒýOn such case involves a WMI event device which needs to talk to a WMI data block device or WMI method device upon receiving an WMI event. In such a case, two WMI drivers should be developed, one for the WMI event device and one for the other WMI device.”h]”hŒýOn such case involves a WMI event device which needs to talk to a WMI data block device or WMI method device upon receiving an WMI event. In such a case, two WMI drivers should be developed, one for the WMI event device and one for the other WMI device.”…””}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K½hj%h²hubhÞ)”}”(hXeThe WMI event device driver has only one purpose: to receive WMI events, validate any additional event data and invoke a notifier chain. The other WMI driver adds itself to this notifier chain during probing and thus gets notified every time a WMI event is received. This WMI driver might then process the event further for example by using an input device.”h]”hXeThe WMI event device driver has only one purpose: to receive WMI events, validate any additional event data and invoke a notifier chain. The other WMI driver adds itself to this notifier chain during probing and thus gets notified every time a WMI event is received. This WMI driver might then process the event further for example by using an input device.”…””}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÁhj%h²hubhÞ)”}”(hŒDFor other WMI device constellations, similar mechanisms can be used.”h]”hŒDFor other WMI device constellations, similar mechanisms can be used.”…””}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÆhj%h²hubeh}”(h]”Œ%handling-multiple-wmi-devices-at-once”ah ]”h"]”Œ%handling multiple wmi devices at once”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K·ubhÉ)”}”(hhh]”(hÎ)”}”(hŒThings to avoid”h]”hŒThings to avoid”…””}”(hjyh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjvh²hh³hÇh´KÉubhÞ)”}”(hŒRWhen developing WMI drivers, there are a couple of things which should be avoided:”h]”hŒRWhen developing WMI drivers, there are a couple of things which should be avoided:”…””}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KËhjvh²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ_usage of the deprecated GUID-based WMI interface which uses GUIDs instead of WMI device structs”h]”hÞ)”}”(hjžh]”hŒ_usage of the deprecated GUID-based WMI interface which uses GUIDs instead of WMI device structs”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÍhjœubah}”(h]”h ]”h"]”h$]”h&]”uh1jšhj—h²hh³hÇh´Nubj›)”}”(hŒausage of the deprecated ACPI-based WMI interface which uses ACPI objects instead of plain buffers”h]”hÞ)”}”(hjµh]”hŒausage of the deprecated ACPI-based WMI interface which uses ACPI objects instead of plain buffers”…””}”(hj·h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÎhj³ubah}”(h]”h ]”h"]”h$]”h&]”uh1jšhj—h²hh³hÇh´Nubj›)”}”(hŒ:bypassing of the WMI subsystem when talking to WMI devices”h]”hÞ)”}”(hjÌh]”hŒ:bypassing of the WMI subsystem when talking to WMI devices”…””}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÏhjÊubah}”(h]”h ]”h"]”h$]”h&]”uh1jšhj—h²hh³hÇh´Nubj›)”}”(hŒ9WMI drivers which cannot be instantiated multiple times. ”h]”hÞ)”}”(hŒ8WMI drivers which cannot be instantiated multiple times.”h]”hŒ8WMI drivers which cannot be instantiated multiple times.”…””}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÐhjáubah}”(h]”h ]”h"]”h$]”h&]”uh1jšhj—h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j•h³hÇh´KÍhjvh²hubhÞ)”}”(hŒÜMany older WMI drivers violate one or more points from this list. The reason for this is that the WMI subsystem evolved significantly over the last two decades, so there is a lot of legacy cruft inside older WMI drivers.”h]”hŒÜMany older WMI drivers violate one or more points from this list. The reason for this is that the WMI subsystem evolved significantly over the last two decades, so there is a lot of legacy cruft inside older WMI drivers.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÒhjvh²hubhÞ)”}”(hŒùNew WMI drivers are also required to conform to the linux kernel coding style as specified in Documentation/process/coding-style.rst. The checkpatch utility can catch many common coding style violations, you can invoke it with the following command:”h]”hŒùNew WMI drivers are also required to conform to the linux kernel coding style as specified in Documentation/process/coding-style.rst. The checkpatch utility can catch many common coding style violations, you can invoke it with the following command:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KÖhjvh²hubjO)”}”(hŒ6./scripts/checkpatch.pl --strict ”h]”hŒ6./scripts/checkpatch.pl --strict ”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jNh³hÇh´KÜhjvh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ References”h]”hŒ References”…””}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj+h²hh³hÇh´KßubhŒfootnote”“”)”}”(hŒ https://lwn.net/Articles/391230/”h]”(hŒlabel”“”)”}”(hŒ1”h]”hŒ1”…””}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jBhj>ubhÞ)”}”(hj@h]”j!)”}”(hj@h]”hŒ https://lwn.net/Articles/391230/”…””}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”j@uh1j hjRubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Káhj>ubeh}”(h]”hùah ]”h"]”Œ1”ah$]”h&]”hóahúhûuh1j<h³hÇh´Káhj+h²hhüKubeh}”(h]”Œ references”ah ]”h"]”Œ references”ah$]”h&]”uh1hÈhjvh²hh³hÇh´Kßubeh}”(h]”Œthings-to-avoid”ah ]”h"]”Œthings to avoid”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KÉubeh}”(h]”Œwmi-driver-development-guide”ah ]”h"]”Œwmi driver development guide”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j«Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œ1”]”héasŒrefids”}”Œnameids”}”(j…j‚j!jj?j<jŽj‹jj j¶j³j jj@j=j±j®j"jjsjpj}jzjujrjmhùuŒ nametypes”}”(j…‰j!‰j?ˆjŽˆjˆj¶‰j ‰j@‰j±‰j"‰js‰j}‰ju‰jmˆuh}”(j‚hÊhóhéjjj<j6j‹j…j jj³j$jj¹j=jj®jCjj´jpj%jzjvjrj+hùj>uŒ footnote_refs”}”jë]”héasŒ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”j>aŒ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”j¹Ks…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.