0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/types.h>
0014 #include <linux/acpi.h>
0015 #include <linux/input.h>
0016 #include <linux/input/sparse-keymap.h>
0017 #include <linux/dmi.h>
0018
0019 MODULE_AUTHOR("Azael Avalos");
0020 MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver");
0021 MODULE_LICENSE("GPL");
0022
0023 #define WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
0024
0025 MODULE_ALIAS("wmi:"WMI_EVENT_GUID);
0026
0027 static struct input_dev *toshiba_wmi_input_dev;
0028
0029 static const struct key_entry toshiba_wmi_keymap[] __initconst = {
0030
0031
0032 { KE_END, 0 }
0033 };
0034
0035 static void toshiba_wmi_notify(u32 value, void *context)
0036 {
0037 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
0038 union acpi_object *obj;
0039 acpi_status status;
0040
0041 status = wmi_get_event_data(value, &response);
0042 if (ACPI_FAILURE(status)) {
0043 pr_err("Bad event status 0x%x\n", status);
0044 return;
0045 }
0046
0047 obj = (union acpi_object *)response.pointer;
0048 if (!obj)
0049 return;
0050
0051
0052 pr_debug("Unknown event received, obj type %x\n", obj->type);
0053
0054 kfree(response.pointer);
0055 }
0056
0057 static const struct dmi_system_id toshiba_wmi_dmi_table[] __initconst = {
0058 {
0059 .ident = "Toshiba laptop",
0060 .matches = {
0061 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
0062 },
0063 },
0064 {}
0065 };
0066
0067 static int __init toshiba_wmi_input_setup(void)
0068 {
0069 acpi_status status;
0070 int err;
0071
0072 toshiba_wmi_input_dev = input_allocate_device();
0073 if (!toshiba_wmi_input_dev)
0074 return -ENOMEM;
0075
0076 toshiba_wmi_input_dev->name = "Toshiba WMI hotkeys";
0077 toshiba_wmi_input_dev->phys = "wmi/input0";
0078 toshiba_wmi_input_dev->id.bustype = BUS_HOST;
0079
0080 err = sparse_keymap_setup(toshiba_wmi_input_dev,
0081 toshiba_wmi_keymap, NULL);
0082 if (err)
0083 goto err_free_dev;
0084
0085 status = wmi_install_notify_handler(WMI_EVENT_GUID,
0086 toshiba_wmi_notify, NULL);
0087 if (ACPI_FAILURE(status)) {
0088 err = -EIO;
0089 goto err_free_dev;
0090 }
0091
0092 err = input_register_device(toshiba_wmi_input_dev);
0093 if (err)
0094 goto err_remove_notifier;
0095
0096 return 0;
0097
0098 err_remove_notifier:
0099 wmi_remove_notify_handler(WMI_EVENT_GUID);
0100 err_free_dev:
0101 input_free_device(toshiba_wmi_input_dev);
0102 return err;
0103 }
0104
0105 static void toshiba_wmi_input_destroy(void)
0106 {
0107 wmi_remove_notify_handler(WMI_EVENT_GUID);
0108 input_unregister_device(toshiba_wmi_input_dev);
0109 }
0110
0111 static int __init toshiba_wmi_init(void)
0112 {
0113 int ret;
0114
0115 if (!wmi_has_guid(WMI_EVENT_GUID) ||
0116 !dmi_check_system(toshiba_wmi_dmi_table))
0117 return -ENODEV;
0118
0119 ret = toshiba_wmi_input_setup();
0120 if (ret) {
0121 pr_err("Failed to setup input device\n");
0122 return ret;
0123 }
0124
0125 pr_info("Toshiba WMI Hotkey Driver\n");
0126
0127 return 0;
0128 }
0129
0130 static void __exit toshiba_wmi_exit(void)
0131 {
0132 if (wmi_has_guid(WMI_EVENT_GUID))
0133 toshiba_wmi_input_destroy();
0134 }
0135
0136 module_init(toshiba_wmi_init);
0137 module_exit(toshiba_wmi_exit);