€•©sŒ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Œ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”…””}”(hhöhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hhóhž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”…””}”(hjhž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”juh1j Œ 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 KhhóhžhubhŒ literal_block”“”)”}”(hŒlswmi -V”h]”hŒlswmi -V”…””}”hj<sbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1j:hŸh³h Khhóhž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.”…””}”(hjJhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Khhóhž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 ”…””}”(hjXhžhhŸNh Nubj )”}”(hŒ*`bmfdec `_”h]”hŒbmfdec”…””}”(hj`hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œname”Œbmfdec”jŒhttps://github.com/pali/bmfdec”uh1j hjXubj!)”}”(hŒ! ”h]”h}”(h]”Œbmfdec”ah ]”h"]”Œbmfdec”ah$]”h&]”Œrefuri”jpuh1j j/KhjXubhŒv utilities can be used to decode the Binary MOF (Managed Object Format) information used to describe WMI devices. The ”…””}”(hjXhžhhŸNh NubhŒliteral”“”)”}”(hŒ ``wmi-bmof``”h]”hŒwmi-bmof”…””}”(hj„hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j‚hjXubhŒZ driver exposes this information to userspace, see Documentation/wmi/devices/wmi-bmof.rst.”…””}”(hjXhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Khhóhž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!hhóhžhubj;)”}”(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²uh1j:hŸh³h K%hhóhž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'hhóhž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”jŒ%https://github.com/vinaypamnani/wmie2”uh1j hjØubj!)”}”(hŒ( ”h]”h}”(h]”Œ wmiexplorer”ah ]”h"]”Œ wmiexplorer”ah$]”h&]”Œrefuri”jðuh1j j/KhjØ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,hhóhž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”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjhž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:”…””}”(hj!hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K3hjhžhubj;)”}”(hXstatic const struct wmi_device_id foo_id_table[] = { { "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 = foo_notify, /* optional, for event handling */ .no_notify_data = true, /* optional, enables events containing no additional data */ .no_singleton = true, /* required for new WMI drivers */ }; module_wmi_driver(foo_driver);”h]”hXstatic const struct wmi_device_id foo_id_table[] = { { "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 = foo_notify, /* optional, for event handling */ .no_notify_data = true, /* optional, enables events containing no additional data */ .no_singleton = true, /* required for new WMI drivers */ }; module_wmi_driver(foo_driver);”…””}”hj/sbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1j:hŸh³h K8hjhž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.”…””}”(hj=hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KNhjhž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.”…””}”(hjKhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KRhjhž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.”…””}”(hjYhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KWhjhžhubhÊ)”}”(hX'Please note that new WMI drivers are required to be able to be instantiated multiple times, and are forbidden from using any deprecated GUID-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]”hX'Please note that new WMI drivers are required to be able to be instantiated multiple times, and are forbidden from using any deprecated GUID-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.”…””}”(hjghžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K[hjhž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.”…””}”(hjuhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K`hjhž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.”…””}”(hj‰hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Kchj…ubah}”(h]”h ]”h"]”h$]”h&]”uh1jƒhjhž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 KhubhÊ)”}”(hX­WMI drivers can call WMI device methods using wmidev_evaluate_method(), the structure of the ACPI buffer passed to this function is device-specific and usually needs some tinkering to get right. Looking at the ACPI tables containing the WMI device usually helps here. The method id and instance number passed to this function are also device-specific, looking at the decoded Binary MOF is usually enough to find the right values.”h]”hX­WMI drivers can call WMI device methods using wmidev_evaluate_method(), the structure of the ACPI buffer passed to this function is device-specific and usually needs some tinkering to get right. Looking at the ACPI tables containing the WMI device usually helps here. The method id and instance number passed to this function are also device-specific, looking at the decoded Binary MOF is usually enough to find the right values.”…””}”(hj¶hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Kjhj¥hžhubhÊ)”}”(hŒZThe maximum instance number can be retrieved during runtime using wmidev_instance_count().”h]”hŒZThe maximum instance number can be retrieved during runtime using wmidev_instance_count().”…””}”(hjÄhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Kqhj¥hžhubhÊ)”}”(hŒ_Take a look at drivers/platform/x86/inspur_platform_profile.c for an example WMI method driver.”h]”hŒ_Take a look at drivers/platform/x86/inspur_platform_profile.c for an example WMI method driver.”…””}”(hjÒhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Kshj¥hžhubeh}”(h]”Œwmi-method-drivers”ah ]”h"]”Œwmi method drivers”ah$]”h&]”uh1h´hh¶hžhhŸh³h Khubhµ)”}”(hhh]”(hº)”}”(hŒWMI data block drivers”h]”hŒWMI data block drivers”…””}”(hjëhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjèhžhhŸh³h KvubhÊ)”}”(hŒÚWMI drivers can query WMI device data blocks using wmidev_block_query(), the structure of the returned ACPI object is again device-specific. Some WMI devices also allow for setting data blocks using wmidev_block_set().”h]”hŒÚWMI drivers can query WMI device data blocks using wmidev_block_query(), the structure of the returned ACPI object is again device-specific. Some WMI devices also allow for setting data blocks using wmidev_block_set().”…””}”(hjùhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h KxhjèhžhubhÊ)”}”(hŒPThe maximum instance number can also be retrieved using wmidev_instance_count().”h]”hŒPThe maximum instance number can also be retrieved using wmidev_instance_count().”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K|hjèhž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.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K~hjèhžhubeh}”(h]”Œwmi-data-block-drivers”ah ]”h"]”Œwmi data block drivers”ah$]”h&]”uh1h´hh¶hžhhŸh³h Kvubhµ)”}”(hhh]”(hº)”}”(hŒWMI event drivers”h]”hŒWMI event drivers”…””}”(hj.hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hj+hžhhŸh³h K‚ubhÊ)”}”(hXWWMI drivers can receive WMI events via the notify() callback inside the struct wmi_driver. The WMI subsystem will then take care of setting up the WMI event accordingly. Please note that the structure of the ACPI object passed to this callback is device-specific, and freeing the ACPI object is being done by the WMI subsystem, not the driver.”h]”hXWWMI drivers can receive WMI events via the notify() callback inside the struct wmi_driver. The WMI subsystem will then take care of setting up the WMI event accordingly. Please note that the structure of the ACPI object passed to this callback is device-specific, and freeing the ACPI object is being done by the WMI subsystem, not the driver.”…””}”(hj<hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K„hj+hžhubhÊ)”}”(hŒõThe WMI driver core will take care that the notify() 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() 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.”…””}”(hjJhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K‰hj+hž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.”…””}”(hjXhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Khj+hžhubhÊ)”}”(hŒžIn order to be able to receive WMI events containing no additional event data, the ``no_notify_data`` flag inside struct wmi_driver should be set to ``true``.”h]”(hŒSIn order to be able to receive WMI events containing no additional event data, the ”…””}”(hjfhžhhŸNh Nubjƒ)”}”(hŒ``no_notify_data``”h]”hŒno_notify_data”…””}”(hjnhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j‚hjfubhŒ0 flag inside struct wmi_driver should be set to ”…””}”(hjfhžhhŸNh Nubjƒ)”}”(hŒ``true``”h]”hŒtrue”…””}”(hj€hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j‚hjfubhŒ.”…””}”(hjfhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Khj+hž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“hj+hžhubeh}”(h]”Œwmi-event-drivers”ah ]”h"]”Œwmi event drivers”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.”…””}”(hj¿hž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.”…””}”(hjÍhž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.”…””}”(hjÛhž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”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjÿhž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:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h Kªhjÿhž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Œ: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.”…””}”(hjWhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K®hjSubah}”(h]”h ]”h"]”h$]”h&]”uh1j#hj hžhhŸh³h Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jhŸh³h K¬hjÿhž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.”…””}”(hjshžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÉhŸh³h K°hjÿhž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´hjÿhžhubj;)”}”(hŒ6./scripts/checkpatch.pl --strict ”h]”hŒ6./scripts/checkpatch.pl --strict ”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”h±h²uh1j:hŸh³h Kºhjÿhžhubhµ)”}”(hhh]”(hº)”}”(hŒ References”h]”hŒ References”…””}”(hj hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¹hjhžhhŸh³h K½ubhŒfootnote”“”)”}”(hŒ https://lwn.net/Articles/391230/”h]”(hŒlabel”“”)”}”(hŒ1”h]”hŒ1”…””}”(hj¶hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j´hj°ubhÊ)”}”(hj²h]”j )”}”(hj²h]”hŒ https://lwn.net/Articles/391230/”…””}”(hjÇhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”j²uh1j hjÄubah}”(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¿hjhžhhèKubeh}”(h]”Œ references”ah ]”h"]”Œ references”ah$]”h&]”uh1h´hjÿhž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 j j+j(jzjwjúj÷j¢jŸjåjâj(j%j«j¨jüjùjïjìjçjäjßhåuŒ nametypes”}”(j÷‰j ‰j+ˆjzˆjúˆj¢‰jå‰j(‰j«‰jü‰jï‰jç‰j߈uh}”(jôh¶hßhÕj hój(j"jwjqj÷jñjŸjjâj¥j%jèj¨j+jùj®jìjÿjäjhå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.