681 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Asus Notebooks WMI hotkey driver4 *5 * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>6 */7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9 10#include <linux/backlight.h>11#include <linux/kernel.h>12#include <linux/module.h>13#include <linux/init.h>14#include <linux/input.h>15#include <linux/input/sparse-keymap.h>16#include <linux/dmi.h>17#include <linux/i8042.h>18 19#include <acpi/video.h>20 21#include "asus-wmi.h"22 23#define ASUS_NB_WMI_FILE "asus-nb-wmi"24 25MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");26MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");27MODULE_LICENSE("GPL");28 29#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"30 31MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);32 33/*34 * WAPF defines the behavior of the Fn+Fx wlan key35 * The significance of values is yet to be found, but36 * most of the time:37 * Bit | Bluetooth | WLAN38 * 0 | Hardware | Hardware39 * 1 | Hardware | Software40 * 4 | Software | Software41 */42static int wapf = -1;43module_param(wapf, uint, 0444);44MODULE_PARM_DESC(wapf, "WAPF value");45 46static int tablet_mode_sw = -1;47module_param(tablet_mode_sw, uint, 0444);48MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip 3:lid-flip-rog");49 50static struct quirk_entry *quirks;51static bool atkbd_reports_vol_keys;52 53static bool asus_i8042_filter(unsigned char data, unsigned char str, struct serio *port)54{55 static bool extended_e0;56 static bool extended_e1;57 58 if (str & I8042_STR_AUXDATA)59 return false;60 61 if (quirks->filter_i8042_e1_extended_codes) {62 if (data == 0xe1) {63 extended_e1 = true;64 return true;65 }66 67 if (extended_e1) {68 extended_e1 = false;69 return true;70 }71 }72 73 if (data == 0xe0) {74 extended_e0 = true;75 } else if (extended_e0) {76 extended_e0 = false;77 78 switch (data & 0x7f) {79 case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */80 case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */81 case 0x30: /* e0 30 / e0 b0, Volume Up press / release */82 atkbd_reports_vol_keys = true;83 break;84 }85 }86 87 return false;88}89 90static struct quirk_entry quirk_asus_unknown = {91 .wapf = 0,92 .wmi_backlight_set_devstate = true,93};94 95static struct quirk_entry quirk_asus_q500a = {96 .filter_i8042_e1_extended_codes = true,97 .wmi_backlight_set_devstate = true,98};99 100/*101 * For those machines that need software to control bt/wifi status102 * and have duplicate events(ACPI and WMI) for display toggle103 */104static struct quirk_entry quirk_asus_x55u = {105 .wapf = 4,106 .wmi_backlight_set_devstate = true,107 .no_display_toggle = true,108};109 110static struct quirk_entry quirk_asus_wapf4 = {111 .wapf = 4,112 .wmi_backlight_set_devstate = true,113};114 115static struct quirk_entry quirk_asus_x200ca = {116 .wapf = 2,117 .wmi_backlight_set_devstate = true,118};119 120static struct quirk_entry quirk_asus_x550lb = {121 .wmi_backlight_set_devstate = true,122 .xusb2pr = 0x01D9,123};124 125static struct quirk_entry quirk_asus_forceals = {126 .wmi_backlight_set_devstate = true,127 .wmi_force_als_set = true,128};129 130static struct quirk_entry quirk_asus_use_kbd_dock_devid = {131 .tablet_switch_mode = asus_wmi_kbd_dock_devid,132};133 134static struct quirk_entry quirk_asus_use_lid_flip_devid = {135 .wmi_backlight_set_devstate = true,136 .tablet_switch_mode = asus_wmi_lid_flip_devid,137};138 139static struct quirk_entry quirk_asus_tablet_mode = {140 .wmi_backlight_set_devstate = true,141 .tablet_switch_mode = asus_wmi_lid_flip_rog_devid,142};143 144static struct quirk_entry quirk_asus_ignore_fan = {145 .wmi_ignore_fan = true,146};147 148static struct quirk_entry quirk_asus_zenbook_duo_kbd = {149 .ignore_key_wlan = true,150};151 152static int dmi_matched(const struct dmi_system_id *dmi)153{154 pr_info("Identified laptop model '%s'\n", dmi->ident);155 quirks = dmi->driver_data;156 return 1;157}158 159static const struct dmi_system_id asus_quirks[] = {160 {161 .callback = dmi_matched,162 .ident = "ASUSTeK COMPUTER INC. Q500A",163 .matches = {164 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),165 DMI_MATCH(DMI_PRODUCT_NAME, "Q500A"),166 },167 .driver_data = &quirk_asus_q500a,168 },169 {170 .callback = dmi_matched,171 .ident = "ASUSTeK COMPUTER INC. U32U",172 .matches = {173 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),174 DMI_MATCH(DMI_PRODUCT_NAME, "U32U"),175 },176 .driver_data = &quirk_asus_wapf4,177 },178 {179 .callback = dmi_matched,180 .ident = "ASUSTeK COMPUTER INC. X302UA",181 .matches = {182 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),183 DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"),184 },185 .driver_data = &quirk_asus_wapf4,186 },187 {188 .callback = dmi_matched,189 .ident = "ASUSTeK COMPUTER INC. X401U",190 .matches = {191 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),192 DMI_MATCH(DMI_PRODUCT_NAME, "X401U"),193 },194 .driver_data = &quirk_asus_x55u,195 },196 {197 .callback = dmi_matched,198 .ident = "ASUSTeK COMPUTER INC. X401A",199 .matches = {200 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),201 DMI_MATCH(DMI_PRODUCT_NAME, "X401A"),202 },203 .driver_data = &quirk_asus_wapf4,204 },205 {206 .callback = dmi_matched,207 .ident = "ASUSTeK COMPUTER INC. X401A1",208 .matches = {209 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),210 DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"),211 },212 .driver_data = &quirk_asus_wapf4,213 },214 {215 .callback = dmi_matched,216 .ident = "ASUSTeK COMPUTER INC. X45U",217 .matches = {218 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),219 DMI_MATCH(DMI_PRODUCT_NAME, "X45U"),220 },221 .driver_data = &quirk_asus_wapf4,222 },223 {224 .callback = dmi_matched,225 .ident = "ASUSTeK COMPUTER INC. X456UA",226 .matches = {227 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),228 DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"),229 },230 .driver_data = &quirk_asus_wapf4,231 },232 {233 .callback = dmi_matched,234 .ident = "ASUSTeK COMPUTER INC. X456UF",235 .matches = {236 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),237 DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"),238 },239 .driver_data = &quirk_asus_wapf4,240 },241 {242 .callback = dmi_matched,243 .ident = "ASUSTeK COMPUTER INC. X501U",244 .matches = {245 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),246 DMI_MATCH(DMI_PRODUCT_NAME, "X501U"),247 },248 .driver_data = &quirk_asus_x55u,249 },250 {251 .callback = dmi_matched,252 .ident = "ASUSTeK COMPUTER INC. X501A",253 .matches = {254 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),255 DMI_MATCH(DMI_PRODUCT_NAME, "X501A"),256 },257 .driver_data = &quirk_asus_wapf4,258 },259 {260 .callback = dmi_matched,261 .ident = "ASUSTeK COMPUTER INC. X501A1",262 .matches = {263 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),264 DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"),265 },266 .driver_data = &quirk_asus_wapf4,267 },268 {269 .callback = dmi_matched,270 .ident = "ASUSTeK COMPUTER INC. X550CA",271 .matches = {272 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),273 DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"),274 },275 .driver_data = &quirk_asus_wapf4,276 },277 {278 .callback = dmi_matched,279 .ident = "ASUSTeK COMPUTER INC. X550CC",280 .matches = {281 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),282 DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"),283 },284 .driver_data = &quirk_asus_wapf4,285 },286 {287 .callback = dmi_matched,288 .ident = "ASUSTeK COMPUTER INC. X550CL",289 .matches = {290 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),291 DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"),292 },293 .driver_data = &quirk_asus_wapf4,294 },295 {296 .callback = dmi_matched,297 .ident = "ASUSTeK COMPUTER INC. X550VB",298 .matches = {299 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),300 DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"),301 },302 .driver_data = &quirk_asus_wapf4,303 },304 {305 .callback = dmi_matched,306 .ident = "ASUSTeK COMPUTER INC. X551CA",307 .matches = {308 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),309 DMI_MATCH(DMI_PRODUCT_NAME, "X551CA"),310 },311 .driver_data = &quirk_asus_wapf4,312 },313 {314 .callback = dmi_matched,315 .ident = "ASUSTeK COMPUTER INC. X55A",316 .matches = {317 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),318 DMI_MATCH(DMI_PRODUCT_NAME, "X55A"),319 },320 .driver_data = &quirk_asus_wapf4,321 },322 {323 .callback = dmi_matched,324 .ident = "ASUSTeK COMPUTER INC. X55C",325 .matches = {326 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),327 DMI_MATCH(DMI_PRODUCT_NAME, "X55C"),328 },329 .driver_data = &quirk_asus_wapf4,330 },331 {332 .callback = dmi_matched,333 .ident = "ASUSTeK COMPUTER INC. X55U",334 .matches = {335 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),336 DMI_MATCH(DMI_PRODUCT_NAME, "X55U"),337 },338 .driver_data = &quirk_asus_x55u,339 },340 {341 .callback = dmi_matched,342 .ident = "ASUSTeK COMPUTER INC. X55VD",343 .matches = {344 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),345 DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"),346 },347 .driver_data = &quirk_asus_wapf4,348 },349 {350 .callback = dmi_matched,351 .ident = "ASUSTeK COMPUTER INC. X75A",352 .matches = {353 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),354 DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),355 },356 .driver_data = &quirk_asus_wapf4,357 },358 {359 .callback = dmi_matched,360 .ident = "ASUSTeK COMPUTER INC. X75VBP",361 .matches = {362 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),363 DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"),364 },365 .driver_data = &quirk_asus_wapf4,366 },367 {368 .callback = dmi_matched,369 .ident = "ASUSTeK COMPUTER INC. X75VD",370 .matches = {371 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),372 DMI_MATCH(DMI_PRODUCT_NAME, "X75VD"),373 },374 .driver_data = &quirk_asus_wapf4,375 },376 {377 .callback = dmi_matched,378 .ident = "ASUSTeK COMPUTER INC. 1015E",379 .matches = {380 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),381 DMI_MATCH(DMI_PRODUCT_NAME, "1015E"),382 },383 .driver_data = &quirk_asus_wapf4,384 },385 {386 .callback = dmi_matched,387 .ident = "ASUSTeK COMPUTER INC. 1015U",388 .matches = {389 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),390 DMI_MATCH(DMI_PRODUCT_NAME, "1015U"),391 },392 .driver_data = &quirk_asus_wapf4,393 },394 {395 .callback = dmi_matched,396 .ident = "ASUSTeK COMPUTER INC. X200CA",397 .matches = {398 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),399 DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"),400 },401 .driver_data = &quirk_asus_x200ca,402 },403 {404 .callback = dmi_matched,405 .ident = "ASUSTeK COMPUTER INC. UX330UAK",406 .matches = {407 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),408 DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"),409 },410 .driver_data = &quirk_asus_forceals,411 },412 {413 .callback = dmi_matched,414 .ident = "ASUSTeK COMPUTER INC. X550LB",415 .matches = {416 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),417 DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"),418 },419 .driver_data = &quirk_asus_x550lb,420 },421 {422 .callback = dmi_matched,423 .ident = "ASUSTeK COMPUTER INC. UX430UQ",424 .matches = {425 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),426 DMI_MATCH(DMI_PRODUCT_NAME, "UX430UQ"),427 },428 .driver_data = &quirk_asus_forceals,429 },430 {431 .callback = dmi_matched,432 .ident = "ASUSTeK COMPUTER INC. UX430UNR",433 .matches = {434 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),435 DMI_MATCH(DMI_PRODUCT_NAME, "UX430UNR"),436 },437 .driver_data = &quirk_asus_forceals,438 },439 {440 .callback = dmi_matched,441 .ident = "Asus Transformer T100TA / T100HA / T100CHI",442 .matches = {443 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),444 /* Match *T100* */445 DMI_MATCH(DMI_PRODUCT_NAME, "T100"),446 },447 .driver_data = &quirk_asus_use_kbd_dock_devid,448 },449 {450 .callback = dmi_matched,451 .ident = "Asus Transformer T101HA",452 .matches = {453 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),454 DMI_MATCH(DMI_PRODUCT_NAME, "T101HA"),455 },456 .driver_data = &quirk_asus_use_kbd_dock_devid,457 },458 {459 .callback = dmi_matched,460 .ident = "Asus Transformer T200TA",461 .matches = {462 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),463 DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"),464 },465 .driver_data = &quirk_asus_use_kbd_dock_devid,466 },467 {468 .callback = dmi_matched,469 .ident = "ASUS ZenBook Flip UX360",470 .matches = {471 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),472 /* Match UX360* */473 DMI_MATCH(DMI_PRODUCT_NAME, "UX360"),474 },475 .driver_data = &quirk_asus_use_lid_flip_devid,476 },477 {478 .callback = dmi_matched,479 .ident = "ASUS TP200s / E205SA",480 .matches = {481 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),482 DMI_MATCH(DMI_PRODUCT_NAME, "E205SA"),483 },484 .driver_data = &quirk_asus_use_lid_flip_devid,485 },486 {487 .callback = dmi_matched,488 .ident = "ASUS ROG FLOW X13",489 .matches = {490 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),491 /* Match GV301** */492 DMI_MATCH(DMI_PRODUCT_NAME, "GV301"),493 },494 .driver_data = &quirk_asus_tablet_mode,495 },496 {497 .callback = dmi_matched,498 .ident = "ASUS ROG FLOW X16",499 .matches = {500 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),501 DMI_MATCH(DMI_PRODUCT_NAME, "GV601R"),502 },503 .driver_data = &quirk_asus_tablet_mode,504 },505 {506 .callback = dmi_matched,507 .ident = "ASUS ROG FLOW X16",508 .matches = {509 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),510 DMI_MATCH(DMI_PRODUCT_NAME, "GV601V"),511 },512 .driver_data = &quirk_asus_tablet_mode,513 },514 {515 .callback = dmi_matched,516 .ident = "ASUS VivoBook E410MA",517 .matches = {518 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),519 DMI_MATCH(DMI_PRODUCT_NAME, "E410MA"),520 },521 .driver_data = &quirk_asus_ignore_fan,522 },523 {524 .callback = dmi_matched,525 .ident = "ASUS Zenbook Duo UX8406MA",526 .matches = {527 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),528 DMI_MATCH(DMI_PRODUCT_NAME, "UX8406MA"),529 },530 .driver_data = &quirk_asus_zenbook_duo_kbd,531 },532 {},533};534 535static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)536{537 quirks = &quirk_asus_unknown;538 dmi_check_system(asus_quirks);539 540 driver->quirks = quirks;541 driver->panel_power = BACKLIGHT_POWER_ON;542 543 /* overwrite the wapf setting if the wapf paramater is specified */544 if (wapf != -1)545 quirks->wapf = wapf;546 else547 wapf = quirks->wapf;548 549 if (tablet_mode_sw != -1)550 quirks->tablet_switch_mode = tablet_mode_sw;551}552 553static const struct key_entry asus_nb_wmi_keymap[] = {554 { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } },555 { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } },556 { KE_KEY, 0x2a, { KEY_SELECTIVE_SCREENSHOT } },557 { KE_IGNORE, 0x2b, }, /* PrintScreen (also send via PS/2) on newer models */558 { KE_IGNORE, 0x2c, }, /* CapsLock (also send via PS/2) on newer models */559 { KE_KEY, 0x30, { KEY_VOLUMEUP } },560 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },561 { KE_KEY, 0x32, { KEY_MUTE } },562 { KE_KEY, 0x33, { KEY_SCREENLOCK } },563 { KE_KEY, 0x35, { KEY_SCREENLOCK } },564 { KE_KEY, 0x38, { KEY_PROG3 } }, /* Armoury Crate */565 { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },566 { KE_KEY, 0x41, { KEY_NEXTSONG } },567 { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */568 { KE_KEY, 0x45, { KEY_PLAYPAUSE } },569 { KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */570 { KE_KEY, 0x50, { KEY_EMAIL } },571 { KE_KEY, 0x51, { KEY_WWW } },572 { KE_KEY, 0x55, { KEY_CALC } },573 { KE_IGNORE, 0x57, }, /* Battery mode */574 { KE_IGNORE, 0x58, }, /* AC mode */575 { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */576 { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */577 { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */578 { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */579 { KE_KEY, 0x60, { KEY_TOUCHPAD_ON } },580 { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */581 { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */582 { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */583 { KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */584 { KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */585 { KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */586 { KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */587 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },588 { KE_IGNORE, 0x6E, }, /* Low Battery notification */589 { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */590 { KE_IGNORE, 0x79, }, /* Charger type dectection notification */591 { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */592 { KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */593 { KE_KEY, 0x7c, { KEY_MICMUTE } },594 { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */595 { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */596 { KE_KEY, 0x82, { KEY_CAMERA } },597 { KE_KEY, 0x85, { KEY_CAMERA } },598 { KE_KEY, 0x86, { KEY_PROG1 } }, /* MyASUS Key */599 { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */600 { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */601 { KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */602 { KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */603 { KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */604 { KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */605 { KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */606 { KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */607 { KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */608 { KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */609 { KE_KEY, 0x95, { KEY_MEDIA } },610 { KE_KEY, 0x99, { KEY_PHONE } }, /* Conflicts with fan mode switch */611 { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */612 { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */613 { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */614 { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */615 { KE_KEY, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */616 { KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */617 { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */618 { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */619 { KE_KEY, 0xAE, { KEY_FN_F5 } }, /* Fn+F5 fan mode on 2020+ */620 { KE_KEY, 0xB3, { KEY_PROG4 } }, /* AURA */621 { KE_KEY, 0xB5, { KEY_CALC } },622 { KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */623 { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },624 { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },625 { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */626 { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */627 { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */628 { KE_END, 0},629};630 631static void asus_nb_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,632 unsigned int *value, bool *autorelease)633{634 switch (*code) {635 case ASUS_WMI_BRN_DOWN:636 case ASUS_WMI_BRN_UP:637 if (acpi_video_handles_brightness_key_presses())638 *code = ASUS_WMI_KEY_IGNORE;639 640 break;641 case 0x30: /* Volume Up */642 case 0x31: /* Volume Down */643 case 0x32: /* Volume Mute */644 if (atkbd_reports_vol_keys)645 *code = ASUS_WMI_KEY_IGNORE;646 break;647 case 0x5D: /* Wireless console Toggle */648 case 0x5E: /* Wireless console Enable */649 case 0x5F: /* Wireless console Disable */650 if (quirks->ignore_key_wlan)651 *code = ASUS_WMI_KEY_IGNORE;652 break;653 }654}655 656static struct asus_wmi_driver asus_nb_wmi_driver = {657 .name = ASUS_NB_WMI_FILE,658 .owner = THIS_MODULE,659 .event_guid = ASUS_NB_WMI_EVENT_GUID,660 .keymap = asus_nb_wmi_keymap,661 .input_name = "Asus WMI hotkeys",662 .input_phys = ASUS_NB_WMI_FILE "/input0",663 .detect_quirks = asus_nb_wmi_quirks,664 .key_filter = asus_nb_wmi_key_filter,665 .i8042_filter = asus_i8042_filter,666};667 668 669static int __init asus_nb_wmi_init(void)670{671 return asus_wmi_register_driver(&asus_nb_wmi_driver);672}673 674static void __exit asus_nb_wmi_exit(void)675{676 asus_wmi_unregister_driver(&asus_nb_wmi_driver);677}678 679module_init(asus_nb_wmi_init);680module_exit(asus_nb_wmi_exit);681