| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Dell WMI hotkeys |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2008 Red Hat <mjg@redhat.com> |
|---|
| 5 | | - * Copyright (C) 2014-2015 Pali Rohár <pali.rohar@gmail.com> |
|---|
| 6 | + * Copyright (C) 2014-2015 Pali Rohár <pali@kernel.org> |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Portions based on wistron_btns.c: |
|---|
| 8 | 9 | * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> |
|---|
| 9 | 10 | * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> |
|---|
| 10 | 11 | * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 15 | | - * (at your option) any later version. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 18 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 19 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 20 | | - * GNU General Public License for more details. |
|---|
| 21 | | - * |
|---|
| 22 | | - * You should have received a copy of the GNU General Public License |
|---|
| 23 | | - * along with this program; if not, write to the Free Software |
|---|
| 24 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 25 | 12 | */ |
|---|
| 26 | 13 | |
|---|
| 27 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 42 | 29 | #include "dell-wmi-descriptor.h" |
|---|
| 43 | 30 | |
|---|
| 44 | 31 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); |
|---|
| 45 | | -MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); |
|---|
| 32 | +MODULE_AUTHOR("Pali Rohár <pali@kernel.org>"); |
|---|
| 46 | 33 | MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); |
|---|
| 47 | 34 | MODULE_LICENSE("GPL"); |
|---|
| 48 | 35 | |
|---|
| 49 | 36 | #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" |
|---|
| 50 | 37 | |
|---|
| 51 | 38 | static bool wmi_requires_smbios_request; |
|---|
| 52 | | - |
|---|
| 53 | | -MODULE_ALIAS("wmi:"DELL_EVENT_GUID); |
|---|
| 54 | 39 | |
|---|
| 55 | 40 | struct dell_wmi_priv { |
|---|
| 56 | 41 | struct input_dev *input_dev; |
|---|
| .. | .. |
|---|
| 267 | 252 | /* Fn-lock switched to multimedia keys */ |
|---|
| 268 | 253 | { KE_IGNORE, 0x1, { KEY_RESERVED } }, |
|---|
| 269 | 254 | |
|---|
| 255 | + /* Keyboard backlight change notification */ |
|---|
| 256 | + { KE_IGNORE, 0x3f, { KEY_RESERVED } }, |
|---|
| 257 | + |
|---|
| 258 | + /* Backlight brightness level */ |
|---|
| 259 | + { KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } }, |
|---|
| 260 | + { KE_KEY, 0x58, { KEY_BRIGHTNESSUP } }, |
|---|
| 261 | + |
|---|
| 262 | + /*Speaker Mute*/ |
|---|
| 263 | + { KE_KEY, 0x109, { KEY_MUTE} }, |
|---|
| 264 | + |
|---|
| 270 | 265 | /* Mic mute */ |
|---|
| 271 | 266 | { KE_KEY, 0x150, { KEY_MICMUTE } }, |
|---|
| 272 | 267 | |
|---|
| .. | .. |
|---|
| 322 | 317 | /* Battery inserted */ |
|---|
| 323 | 318 | { KE_IGNORE, 0xfff1, { KEY_RESERVED } }, |
|---|
| 324 | 319 | |
|---|
| 320 | + /* |
|---|
| 321 | + * Detachable keyboard detached / undocked |
|---|
| 322 | + * Note SW_TABLET_MODE is already reported through the intel_vbtn |
|---|
| 323 | + * driver for this, so we ignore it. |
|---|
| 324 | + */ |
|---|
| 325 | + { KE_IGNORE, 0xfff2, { KEY_RESERVED } }, |
|---|
| 326 | + |
|---|
| 327 | + /* Detachable keyboard attached / docked */ |
|---|
| 328 | + { KE_IGNORE, 0xfff3, { KEY_RESERVED } }, |
|---|
| 329 | + |
|---|
| 325 | 330 | /* Keyboard backlight level changed */ |
|---|
| 326 | | - { KE_IGNORE, 0x01e1, { KEY_RESERVED } }, |
|---|
| 327 | | - { KE_IGNORE, 0x02ea, { KEY_RESERVED } }, |
|---|
| 328 | | - { KE_IGNORE, 0x02eb, { KEY_RESERVED } }, |
|---|
| 329 | | - { KE_IGNORE, 0x02ec, { KEY_RESERVED } }, |
|---|
| 330 | | - { KE_IGNORE, 0x02f6, { KEY_RESERVED } }, |
|---|
| 331 | + { KE_IGNORE, KBD_LED_OFF_TOKEN, { KEY_RESERVED } }, |
|---|
| 332 | + { KE_IGNORE, KBD_LED_ON_TOKEN, { KEY_RESERVED } }, |
|---|
| 333 | + { KE_IGNORE, KBD_LED_AUTO_TOKEN, { KEY_RESERVED } }, |
|---|
| 334 | + { KE_IGNORE, KBD_LED_AUTO_25_TOKEN, { KEY_RESERVED } }, |
|---|
| 335 | + { KE_IGNORE, KBD_LED_AUTO_50_TOKEN, { KEY_RESERVED } }, |
|---|
| 336 | + { KE_IGNORE, KBD_LED_AUTO_75_TOKEN, { KEY_RESERVED } }, |
|---|
| 337 | + { KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } }, |
|---|
| 338 | +}; |
|---|
| 339 | + |
|---|
| 340 | +/* |
|---|
| 341 | + * Keymap for WMI events of type 0x0012 |
|---|
| 342 | + * They are events with extended data |
|---|
| 343 | + */ |
|---|
| 344 | +static const struct key_entry dell_wmi_keymap_type_0012[] = { |
|---|
| 345 | + /* Fn-lock button pressed */ |
|---|
| 346 | + { KE_IGNORE, 0xe035, { KEY_RESERVED } }, |
|---|
| 331 | 347 | }; |
|---|
| 332 | 348 | |
|---|
| 333 | 349 | static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code) |
|---|
| .. | .. |
|---|
| 414 | 430 | |
|---|
| 415 | 431 | switch (buffer_entry[1]) { |
|---|
| 416 | 432 | case 0x0000: /* One key pressed or event occurred */ |
|---|
| 433 | + case 0x0012: /* Event with extended data occurred */ |
|---|
| 417 | 434 | if (len > 2) |
|---|
| 418 | | - dell_wmi_process_key(wdev, 0x0000, |
|---|
| 435 | + dell_wmi_process_key(wdev, buffer_entry[1], |
|---|
| 419 | 436 | buffer_entry[2]); |
|---|
| 420 | | - /* Other entries could contain additional information */ |
|---|
| 437 | + /* Extended data is currently ignored */ |
|---|
| 421 | 438 | break; |
|---|
| 422 | 439 | case 0x0010: /* Sequence of keys pressed */ |
|---|
| 423 | 440 | case 0x0011: /* Sequence of events occurred */ |
|---|
| .. | .. |
|---|
| 492 | 509 | u16 keycode = (bios_entry->keycode < |
|---|
| 493 | 510 | ARRAY_SIZE(bios_to_linux_keycode)) ? |
|---|
| 494 | 511 | bios_to_linux_keycode[bios_entry->keycode] : |
|---|
| 495 | | - KEY_RESERVED; |
|---|
| 512 | + (bios_entry->keycode == 0xffff ? KEY_UNKNOWN : KEY_RESERVED); |
|---|
| 496 | 513 | |
|---|
| 497 | 514 | /* |
|---|
| 498 | 515 | * Log if we find an entry in the DMI table that we don't |
|---|
| .. | .. |
|---|
| 552 | 569 | ARRAY_SIZE(dell_wmi_keymap_type_0000) + |
|---|
| 553 | 570 | ARRAY_SIZE(dell_wmi_keymap_type_0010) + |
|---|
| 554 | 571 | ARRAY_SIZE(dell_wmi_keymap_type_0011) + |
|---|
| 572 | + ARRAY_SIZE(dell_wmi_keymap_type_0012) + |
|---|
| 555 | 573 | 1, |
|---|
| 556 | 574 | sizeof(struct key_entry), GFP_KERNEL); |
|---|
| 557 | 575 | if (!keymap) { |
|---|
| .. | .. |
|---|
| 593 | 611 | for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0011); i++) { |
|---|
| 594 | 612 | keymap[pos] = dell_wmi_keymap_type_0011[i]; |
|---|
| 595 | 613 | keymap[pos].code |= (0x0011 << 16); |
|---|
| 614 | + pos++; |
|---|
| 615 | + } |
|---|
| 616 | + |
|---|
| 617 | + /* Append table with events of type 0x0012 */ |
|---|
| 618 | + for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) { |
|---|
| 619 | + keymap[pos] = dell_wmi_keymap_type_0012[i]; |
|---|
| 620 | + keymap[pos].code |= (0x0012 << 16); |
|---|
| 596 | 621 | pos++; |
|---|
| 597 | 622 | } |
|---|
| 598 | 623 | |
|---|
| .. | .. |
|---|
| 671 | 696 | return dell_smbios_error(ret); |
|---|
| 672 | 697 | } |
|---|
| 673 | 698 | |
|---|
| 674 | | -static int dell_wmi_probe(struct wmi_device *wdev) |
|---|
| 699 | +static int dell_wmi_probe(struct wmi_device *wdev, const void *context) |
|---|
| 675 | 700 | { |
|---|
| 676 | 701 | struct dell_wmi_priv *priv; |
|---|
| 677 | 702 | int ret; |
|---|
| .. | .. |
|---|
| 738 | 763 | wmi_driver_unregister(&dell_wmi_driver); |
|---|
| 739 | 764 | } |
|---|
| 740 | 765 | module_exit(dell_wmi_exit); |
|---|
| 766 | + |
|---|
| 767 | +MODULE_DEVICE_TABLE(wmi, dell_wmi_id_table); |
|---|