linux/drivers/platform/x86/toshiba-wmi.c
Armin Wolf e04e2b760d platform/x86: wmi: Pass event data directly to legacy notify handlers
The current legacy WMI handlers are susceptible to picking up wrong
WMI event data on systems where different WMI devices share some
notification IDs.

Prevent this by letting the WMI driver core taking care of retrieving
the event data. This also simplifies the legacy WMI handlers and their
implementation inside the WMI driver core.

Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20240901031055.3030-3-W_Armin@gmx.de
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2024-09-05 17:21:59 +02:00

125 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* toshiba_wmi.c - Toshiba WMI Hotkey Driver
*
* Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/dmi.h>
MODULE_AUTHOR("Azael Avalos");
MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver");
MODULE_LICENSE("GPL");
#define WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
MODULE_ALIAS("wmi:"WMI_EVENT_GUID);
static struct input_dev *toshiba_wmi_input_dev;
static const struct key_entry toshiba_wmi_keymap[] __initconst = {
/* TODO: Add keymap values once found... */
/*{ KE_KEY, 0x00, { KEY_ } },*/
{ KE_END, 0 }
};
static void toshiba_wmi_notify(union acpi_object *obj, void *context)
{
if (!obj)
return;
/* TODO: Add proper checks once we have data */
pr_debug("Unknown event received, obj type %x\n", obj->type);
}
static const struct dmi_system_id toshiba_wmi_dmi_table[] __initconst = {
{
.ident = "Toshiba laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
},
},
{}
};
static int __init toshiba_wmi_input_setup(void)
{
acpi_status status;
int err;
toshiba_wmi_input_dev = input_allocate_device();
if (!toshiba_wmi_input_dev)
return -ENOMEM;
toshiba_wmi_input_dev->name = "Toshiba WMI hotkeys";
toshiba_wmi_input_dev->phys = "wmi/input0";
toshiba_wmi_input_dev->id.bustype = BUS_HOST;
err = sparse_keymap_setup(toshiba_wmi_input_dev,
toshiba_wmi_keymap, NULL);
if (err)
goto err_free_dev;
status = wmi_install_notify_handler(WMI_EVENT_GUID,
toshiba_wmi_notify, NULL);
if (ACPI_FAILURE(status)) {
err = -EIO;
goto err_free_dev;
}
err = input_register_device(toshiba_wmi_input_dev);
if (err)
goto err_remove_notifier;
return 0;
err_remove_notifier:
wmi_remove_notify_handler(WMI_EVENT_GUID);
err_free_dev:
input_free_device(toshiba_wmi_input_dev);
return err;
}
static void toshiba_wmi_input_destroy(void)
{
wmi_remove_notify_handler(WMI_EVENT_GUID);
input_unregister_device(toshiba_wmi_input_dev);
}
static int __init toshiba_wmi_init(void)
{
int ret;
if (!wmi_has_guid(WMI_EVENT_GUID) ||
!dmi_check_system(toshiba_wmi_dmi_table))
return -ENODEV;
ret = toshiba_wmi_input_setup();
if (ret) {
pr_err("Failed to setup input device\n");
return ret;
}
pr_info("Toshiba WMI Hotkey Driver\n");
return 0;
}
static void __exit toshiba_wmi_exit(void)
{
if (wmi_has_guid(WMI_EVENT_GUID))
toshiba_wmi_input_destroy();
}
module_init(toshiba_wmi_init);
module_exit(toshiba_wmi_exit);