FILE
uniwill-wmi.c
File preview with syntax highlighting.
linux-6.19.14/drivers/platform/x86/uniwill/uniwill-wmi.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Linux hotkey driver for Uniwill notebooks. 4 * 5 * Special thanks go to Pőcze Barnabás, Christoffer Sandberg and Werner Sembach 6 * for supporting the development of this driver either through prior work or 7 * by answering questions regarding the underlying WMI interface. 8 * 9 * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de> 10 */ 11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14#include <linux/acpi.h> 15#include <linux/device.h> 16#include <linux/init.h> 17#include <linux/mod_devicetable.h> 18#include <linux/notifier.h> 19#include <linux/printk.h> 20#include <linux/types.h> 21#include <linux/wmi.h> 22 23#include "uniwill-wmi.h" 24 25#define DRIVER_NAME "uniwill-wmi" 26#define UNIWILL_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000" 27 28static BLOCKING_NOTIFIER_HEAD(uniwill_wmi_chain_head); 29 30static void devm_uniwill_wmi_unregister_notifier(void *data) 31{ 32 struct notifier_block *nb = data; 33 34 blocking_notifier_chain_unregister(&uniwill_wmi_chain_head, nb); 35} 36 37int devm_uniwill_wmi_register_notifier(struct device *dev, struct notifier_block *nb) 38{ 39 int ret; 40 41 ret = blocking_notifier_chain_register(&uniwill_wmi_chain_head, nb); 42 if (ret < 0) 43 return ret; 44 45 return devm_add_action_or_reset(dev, devm_uniwill_wmi_unregister_notifier, nb); 46} 47 48static void uniwill_wmi_notify(struct wmi_device *wdev, union acpi_object *obj) 49{ 50 u32 value; 51 52 if (obj->type != ACPI_TYPE_INTEGER) 53 return; 54 55 value = obj->integer.value; 56 57 dev_dbg(&wdev->dev, "Received WMI event %u\n", value); 58 59 blocking_notifier_call_chain(&uniwill_wmi_chain_head, value, NULL); 60} 61 62/* 63 * We cannot fully trust this GUID since Uniwill just copied the WMI GUID 64 * from the Windows driver example, and others probably did the same. 65 * 66 * Because of this we cannot use this WMI GUID for autoloading. Instead the 67 * associated driver will be registered manually after matching a DMI table. 68 */ 69static const struct wmi_device_id uniwill_wmi_id_table[] = { 70 { UNIWILL_EVENT_GUID, NULL }, 71 { } 72}; 73 74static struct wmi_driver uniwill_wmi_driver = { 75 .driver = { 76 .name = DRIVER_NAME, 77 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 78 }, 79 .id_table = uniwill_wmi_id_table, 80 .notify = uniwill_wmi_notify, 81 .no_singleton = true, 82}; 83 84int __init uniwill_wmi_register_driver(void) 85{ 86 return wmi_driver_register(&uniwill_wmi_driver); 87} 88 89void __exit uniwill_wmi_unregister_driver(void) 90{ 91 wmi_driver_unregister(&uniwill_wmi_driver); 92}
~/
Read-only file preview.