mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
2.9 KiB
137 lines
2.9 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* toshiba_wmi.c - Toshiba WMI Hotkey Driver |
|
* |
|
* Copyright (C) 2015 Azael Avalos <[email protected]> |
|
*/ |
|
|
|
#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(u32 value, void *context) |
|
{ |
|
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
|
union acpi_object *obj; |
|
acpi_status status; |
|
|
|
status = wmi_get_event_data(value, &response); |
|
if (ACPI_FAILURE(status)) { |
|
pr_err("Bad event status 0x%x\n", status); |
|
return; |
|
} |
|
|
|
obj = (union acpi_object *)response.pointer; |
|
if (!obj) |
|
return; |
|
|
|
/* TODO: Add proper checks once we have data */ |
|
pr_debug("Unknown event received, obj type %x\n", obj->type); |
|
|
|
kfree(response.pointer); |
|
} |
|
|
|
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);
|
|
|