WMI drivers using the buffer-based WMI API are expected to reject undersized event payloads. Extend the WMI driver core to allow such drivers to specify their minimum supported event payload size. Also remove the now redundant .no_notify_data field. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://patch.msgid.link/20260406203237.2970-7-W_Armin@gmx.de Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
93 lines
2.4 KiB
C
93 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Linux hotkey driver for Uniwill notebooks.
|
|
*
|
|
* Special thanks go to Pőcze Barnabás, Christoffer Sandberg and Werner Sembach
|
|
* for supporting the development of this driver either through prior work or
|
|
* by answering questions regarding the underlying WMI interface.
|
|
*
|
|
* Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/acpi.h>
|
|
#include <linux/device.h>
|
|
#include <linux/init.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/types.h>
|
|
#include <linux/wmi.h>
|
|
|
|
#include "uniwill-wmi.h"
|
|
|
|
#define DRIVER_NAME "uniwill-wmi"
|
|
#define UNIWILL_EVENT_GUID "ABBC0F72-8EA1-11D1-00A0-C90629100000"
|
|
|
|
static BLOCKING_NOTIFIER_HEAD(uniwill_wmi_chain_head);
|
|
|
|
static void devm_uniwill_wmi_unregister_notifier(void *data)
|
|
{
|
|
struct notifier_block *nb = data;
|
|
|
|
blocking_notifier_chain_unregister(&uniwill_wmi_chain_head, nb);
|
|
}
|
|
|
|
int devm_uniwill_wmi_register_notifier(struct device *dev, struct notifier_block *nb)
|
|
{
|
|
int ret;
|
|
|
|
ret = blocking_notifier_chain_register(&uniwill_wmi_chain_head, nb);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return devm_add_action_or_reset(dev, devm_uniwill_wmi_unregister_notifier, nb);
|
|
}
|
|
|
|
static void uniwill_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
|
|
{
|
|
u32 value;
|
|
|
|
if (obj->type != ACPI_TYPE_INTEGER)
|
|
return;
|
|
|
|
value = obj->integer.value;
|
|
|
|
dev_dbg(&wdev->dev, "Received WMI event %u\n", value);
|
|
|
|
blocking_notifier_call_chain(&uniwill_wmi_chain_head, value, NULL);
|
|
}
|
|
|
|
/*
|
|
* We cannot fully trust this GUID since Uniwill just copied the WMI GUID
|
|
* from the Windows driver example, and others probably did the same.
|
|
*
|
|
* Because of this we cannot use this WMI GUID for autoloading. Instead the
|
|
* associated driver will be registered manually after matching a DMI table.
|
|
*/
|
|
static const struct wmi_device_id uniwill_wmi_id_table[] = {
|
|
{ UNIWILL_EVENT_GUID, NULL },
|
|
{ }
|
|
};
|
|
|
|
static struct wmi_driver uniwill_wmi_driver = {
|
|
.driver = {
|
|
.name = DRIVER_NAME,
|
|
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
|
},
|
|
.id_table = uniwill_wmi_id_table,
|
|
.min_event_size = sizeof(u32),
|
|
.notify = uniwill_wmi_notify,
|
|
.no_singleton = true,
|
|
};
|
|
|
|
int __init uniwill_wmi_register_driver(void)
|
|
{
|
|
return wmi_driver_register(&uniwill_wmi_driver);
|
|
}
|
|
|
|
void __exit uniwill_wmi_unregister_driver(void)
|
|
{
|
|
wmi_driver_unregister(&uniwill_wmi_driver);
|
|
}
|