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