Hi Maxim, 於 日,2012-11-25 於 00:29 +0200,Maxim Mikityanskiy 提到: > Create a driver to support WMI found on MSI Wind laptops. This driver > allows us to receive some additional keycodes for keys that are not > handled without this driver. > > Signed-off-by: Maxim Mikityanskiy <maxtram95@xxxxxxxxx> I simply review this patch and looks there have many code the same with msi-wmi.c. Does there have any reason didn't direct patch msi-wmi but need generate a new driver? Thanks a lot! Joey Lee > --- > drivers/platform/x86/Kconfig | 13 +++ > drivers/platform/x86/Makefile | 1 + > drivers/platform/x86/msi-wind-wmi.c | 169 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 183 insertions(+) > create mode 100644 drivers/platform/x86/msi-wind-wmi.c > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig > index c86bae8..46f269e5 100644 > --- a/drivers/platform/x86/Kconfig > +++ b/drivers/platform/x86/Kconfig > @@ -561,6 +561,19 @@ config MSI_WMI > To compile this driver as a module, choose M here: the module will > be called msi-wmi. > > +config MSI_WIND_WMI > + tristate "MSI Wind WMI Driver" > + depends on ACPI_WMI > + depends on INPUT > + select INPUT_SPARSEKMAP > + ---help--- > + Say Y here if you want to support WMI-based hotkeys on MSI Wind > + laptops. MSI Wind WMI differs from WMI found on other MSI laptops, so > + say Y here if you have MSI Wind, otherwise select "MSI WMI extras". > + > + To compile this driver as a module, choose M here: the module will > + be called msi-wind-wmi. > + > config TOPSTAR_LAPTOP > tristate "Topstar Laptop Extras" > depends on ACPI > diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile > index bf7e4f9..44389c0 100644 > --- a/drivers/platform/x86/Makefile > +++ b/drivers/platform/x86/Makefile > @@ -30,6 +30,7 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o > obj-$(CONFIG_ACPI_WMI) += wmi.o > obj-$(CONFIG_MSI_WMI) += msi-wmi.o > obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o > +obj-$(CONFIG_MSI_WIND_WMI) += msi-wind-wmi.o > > # toshiba_acpi must link after wmi to ensure that wmi devices are found > # before toshiba_acpi initializes > diff --git a/drivers/platform/x86/msi-wind-wmi.c b/drivers/platform/x86/msi-wind-wmi.c > new file mode 100644 > index 0000000..4f19434 > --- /dev/null > +++ b/drivers/platform/x86/msi-wind-wmi.c > @@ -0,0 +1,169 @@ > +/* > + * MSI Wind WMI hotkeys > + * > + * Copyright (C) 2012 Maxim Mikityanskiy <maxtram95@xxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > + > +#include <linux/module.h> > +#include <linux/input.h> > +#include <linux/input/sparse-keymap.h> > +#include <linux/acpi.h> > + > +MODULE_AUTHOR("Maxim Mikityanskiy <maxtram95@xxxxxxxxx>"); > +MODULE_DESCRIPTION("MSI Wind laptop WMI hotkeys driver"); > +MODULE_LICENSE("GPL"); > + > +#define WMI_EVENT_GUID "5B3CC38A-40D9-7245-8AE6-1145B751BE3F" > + > +MODULE_ALIAS("wmi:" WMI_EVENT_GUID); > + > +/* Fn+F3 touchpad toggle */ > +#define WIND_KEY_TOUCHPAD 0x08 > +/* Fn+F11 Bluetooth toggle */ > +#define WIND_KEY_BLUETOOTH 0x56 > +/* Fn+F6 webcam toggle */ > +#define WIND_KEY_CAMERA 0x57 > +/* Fn+F11 Wi-Fi toggle */ > +#define WIND_KEY_WLAN 0x5f > +/* Fn+F10 turbo mode toggle */ > +#define WIND_KEY_TURBO 0x60 > +/* Fn+F10 ECO mode toggle */ > +#define WIND_KEY_ECO 0x69 > + > +static struct key_entry wind_keymap[] = { > + /* These keys work without WMI. Ignore them to avoid double keycodes */ > + { KE_IGNORE, WIND_KEY_TOUCHPAD, { KEY_TOUCHPAD_TOGGLE } }, > + { KE_IGNORE, WIND_KEY_BLUETOOTH, { KEY_BLUETOOTH } }, > + { KE_IGNORE, WIND_KEY_CAMERA, { KEY_CAMERA } }, > + { KE_IGNORE, WIND_KEY_WLAN, { KEY_WLAN } }, > + /* These are keys that should be handled via WMI */ > + { KE_KEY, WIND_KEY_TURBO, { KEY_PROG1 } }, > + { KE_KEY, WIND_KEY_ECO, { KEY_PROG2 } }, > + { KE_END, 0 } > +}; > + > +static struct input_dev *wind_input_dev; > + > +static void wind_wmi_notify(u32 value, void *context) > +{ > + struct acpi_buffer response = { > + .length = ACPI_ALLOCATE_BUFFER, > + .pointer = NULL > + }; > + acpi_status status = wmi_get_event_data(value, &response); > + union acpi_object *obj = response.pointer; > + int code; > + > + if (status != AE_OK) { > + pr_warn("Bad event status %#x\n", status); > + return; > + } > + > + if (!obj || obj->type != ACPI_TYPE_INTEGER) { > + pr_warn("Unknown event received\n"); > + goto wind_wmi_notify_free; > + } > + > + code = obj->integer.value; > + pr_debug("Event code: %#x\n", code); > + > + if (code == 0x00 || code == 0x62 || code == 0x63) { > + /* Unknown events - drop them for now */ > + goto wind_wmi_notify_free; > + } > + > + if (!sparse_keymap_report_event(wind_input_dev, code, 1, true)) > + pr_warn("Unknown key %#x pressed\n", code); > + > +wind_wmi_notify_free: > + kfree(response.pointer); > +} > + > +static int __init wind_input_setup(void) > +{ > + int err; > + > + wind_input_dev = input_allocate_device(); > + if (!wind_input_dev) > + return -ENOMEM; > + > + wind_input_dev->name = "MSI WMI hotkeys"; > + wind_input_dev->phys = "wmi/input0"; > + wind_input_dev->id.bustype = BUS_HOST; > + > + err = sparse_keymap_setup(wind_input_dev, wind_keymap, NULL); > + if (err) > + goto wind_input_setup_free_dev; > + > + err = input_register_device(wind_input_dev); > + if (err) > + goto wind_input_setup_free_keymap; > + > + return 0; > + > +wind_input_setup_free_keymap: > + sparse_keymap_free(wind_input_dev); > +wind_input_setup_free_dev: > + input_free_device(wind_input_dev); > + return err; > +} > + > +static int __init wind_wmi_init(void) > +{ > + int err; > + > + if (!wmi_has_guid(WMI_EVENT_GUID)) { > + pr_err("No MSI Wind WMI found\n"); > + return -ENODEV; > + } > + > + err = wind_input_setup(); > + if (err) { > + pr_err("Unable to setup input device\n"); > + return err; > + } > + > + if (ACPI_FAILURE(wmi_install_notify_handler(WMI_EVENT_GUID, > + wind_wmi_notify, NULL))) { > + pr_err("Unable to install WMI notify handler\n"); > + err = -EIO; > + goto wind_wmi_init_unregister_input; > + } > + > + pr_debug("Event handler installed\n"); > + > + return 0; > + > +wind_wmi_init_unregister_input: > + input_unregister_device(wind_input_dev); > + sparse_keymap_free(wind_input_dev); > + input_free_device(wind_input_dev); > + return err; > +} > + > +static void __exit wind_wmi_exit(void) > +{ > + wmi_remove_notify_handler(WMI_EVENT_GUID); > + input_unregister_device(wind_input_dev); > + sparse_keymap_free(wind_input_dev); > + input_free_device(wind_input_dev); > +} > + > +module_init(wind_wmi_init); > +module_exit(wind_wmi_exit); -- To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html