Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.14-rc1 147 lines 3.5 kB view raw
1/* 2 * toshiba_wmi.c - Toshiba WMI Hotkey Driver 3 * 4 * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 */ 17 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/init.h> 23#include <linux/types.h> 24#include <linux/acpi.h> 25#include <linux/input.h> 26#include <linux/input/sparse-keymap.h> 27#include <linux/dmi.h> 28 29MODULE_AUTHOR("Azael Avalos"); 30MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver"); 31MODULE_LICENSE("GPL"); 32 33#define WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100" 34 35MODULE_ALIAS("wmi:"WMI_EVENT_GUID); 36 37static struct input_dev *toshiba_wmi_input_dev; 38 39static const struct key_entry toshiba_wmi_keymap[] __initconst = { 40 /* TODO: Add keymap values once found... */ 41 /*{ KE_KEY, 0x00, { KEY_ } },*/ 42 { KE_END, 0 } 43}; 44 45static void toshiba_wmi_notify(u32 value, void *context) 46{ 47 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 48 union acpi_object *obj; 49 acpi_status status; 50 51 status = wmi_get_event_data(value, &response); 52 if (ACPI_FAILURE(status)) { 53 pr_err("Bad event status 0x%x\n", status); 54 return; 55 } 56 57 obj = (union acpi_object *)response.pointer; 58 if (!obj) 59 return; 60 61 /* TODO: Add proper checks once we have data */ 62 pr_debug("Unknown event received, obj type %x\n", obj->type); 63 64 kfree(response.pointer); 65} 66 67static const struct dmi_system_id toshiba_wmi_dmi_table[] __initconst = { 68 { 69 .ident = "Toshiba laptop", 70 .matches = { 71 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 72 }, 73 }, 74 {} 75}; 76 77static int __init toshiba_wmi_input_setup(void) 78{ 79 acpi_status status; 80 int err; 81 82 toshiba_wmi_input_dev = input_allocate_device(); 83 if (!toshiba_wmi_input_dev) 84 return -ENOMEM; 85 86 toshiba_wmi_input_dev->name = "Toshiba WMI hotkeys"; 87 toshiba_wmi_input_dev->phys = "wmi/input0"; 88 toshiba_wmi_input_dev->id.bustype = BUS_HOST; 89 90 err = sparse_keymap_setup(toshiba_wmi_input_dev, 91 toshiba_wmi_keymap, NULL); 92 if (err) 93 goto err_free_dev; 94 95 status = wmi_install_notify_handler(WMI_EVENT_GUID, 96 toshiba_wmi_notify, NULL); 97 if (ACPI_FAILURE(status)) { 98 err = -EIO; 99 goto err_free_dev; 100 } 101 102 err = input_register_device(toshiba_wmi_input_dev); 103 if (err) 104 goto err_remove_notifier; 105 106 return 0; 107 108 err_remove_notifier: 109 wmi_remove_notify_handler(WMI_EVENT_GUID); 110 err_free_dev: 111 input_free_device(toshiba_wmi_input_dev); 112 return err; 113} 114 115static void toshiba_wmi_input_destroy(void) 116{ 117 wmi_remove_notify_handler(WMI_EVENT_GUID); 118 input_unregister_device(toshiba_wmi_input_dev); 119} 120 121static int __init toshiba_wmi_init(void) 122{ 123 int ret; 124 125 if (!wmi_has_guid(WMI_EVENT_GUID) || 126 !dmi_check_system(toshiba_wmi_dmi_table)) 127 return -ENODEV; 128 129 ret = toshiba_wmi_input_setup(); 130 if (ret) { 131 pr_err("Failed to setup input device\n"); 132 return ret; 133 } 134 135 pr_info("Toshiba WMI Hotkey Driver\n"); 136 137 return 0; 138} 139 140static void __exit toshiba_wmi_exit(void) 141{ 142 if (wmi_has_guid(WMI_EVENT_GUID)) 143 toshiba_wmi_input_destroy(); 144} 145 146module_init(toshiba_wmi_init); 147module_exit(toshiba_wmi_exit);