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"); 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 can't adjust brightness through ACPI interface 83 * and have duplicate events(ACPI and WMI) for display toggle 84 */ 85 static struct quirk_entry quirk_asus_x55u = { 86 .wapf = 4, 87 .wmi_backlight_power = true, 88 .wmi_backlight_set_devstate = true, 89 .no_display_toggle = true, 90 }; 91 92 static struct quirk_entry quirk_asus_wapf4 = { 93 .wapf = 4, 94 .wmi_backlight_set_devstate = true, 95 }; 96 97 static struct quirk_entry quirk_asus_x200ca = { 98 .wapf = 2, 99 .wmi_backlight_set_devstate = true, 100 }; 101 102 static struct quirk_entry quirk_asus_ux303ub = { 103 .wmi_backlight_native = true, 104 .wmi_backlight_set_devstate = true, 105 }; 106 107 static struct quirk_entry quirk_asus_x550lb = { 108 .wmi_backlight_set_devstate = true, 109 .xusb2pr = 0x01D9, 110 }; 111 112 static struct quirk_entry quirk_asus_forceals = { 113 .wmi_backlight_set_devstate = true, 114 .wmi_force_als_set = true, 115 }; 116 117 static struct quirk_entry quirk_asus_use_kbd_dock_devid = { 118 .use_kbd_dock_devid = true, 119 }; 120 121 static struct quirk_entry quirk_asus_use_lid_flip_devid = { 122 .wmi_backlight_set_devstate = true, 123 .use_lid_flip_devid = true, 124 }; 125 126 static int dmi_matched(const struct dmi_system_id *dmi) 127 { 128 pr_info("Identified laptop model '%s'\n", dmi->ident); 129 quirks = dmi->driver_data; 130 return 1; 131 } 132 133 static const struct dmi_system_id asus_quirks[] = { 134 { 135 .callback = dmi_matched, 136 .ident = "ASUSTeK COMPUTER INC. Q500A", 137 .matches = { 138 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 139 DMI_MATCH(DMI_PRODUCT_NAME, "Q500A"), 140 }, 141 .driver_data = &quirk_asus_q500a, 142 }, 143 { 144 .callback = dmi_matched, 145 .ident = "ASUSTeK COMPUTER INC. U32U", 146 .matches = { 147 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 148 DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), 149 }, 150 /* 151 * Note this machine has a Brazos APU, and most Brazos Asus 152 * machines need quirk_asus_x55u / wmi_backlight_power but 153 * here acpi-video seems to work fine for backlight control. 154 */ 155 .driver_data = &quirk_asus_wapf4, 156 }, 157 { 158 .callback = dmi_matched, 159 .ident = "ASUSTeK COMPUTER INC. X302UA", 160 .matches = { 161 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 162 DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"), 163 }, 164 .driver_data = &quirk_asus_wapf4, 165 }, 166 { 167 .callback = dmi_matched, 168 .ident = "ASUSTeK COMPUTER INC. X401U", 169 .matches = { 170 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 171 DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), 172 }, 173 .driver_data = &quirk_asus_x55u, 174 }, 175 { 176 .callback = dmi_matched, 177 .ident = "ASUSTeK COMPUTER INC. X401A", 178 .matches = { 179 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 180 DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), 181 }, 182 .driver_data = &quirk_asus_wapf4, 183 }, 184 { 185 .callback = dmi_matched, 186 .ident = "ASUSTeK COMPUTER INC. X401A1", 187 .matches = { 188 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 189 DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), 190 }, 191 .driver_data = &quirk_asus_wapf4, 192 }, 193 { 194 .callback = dmi_matched, 195 .ident = "ASUSTeK COMPUTER INC. X45U", 196 .matches = { 197 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 198 DMI_MATCH(DMI_PRODUCT_NAME, "X45U"), 199 }, 200 .driver_data = &quirk_asus_wapf4, 201 }, 202 { 203 .callback = dmi_matched, 204 .ident = "ASUSTeK COMPUTER INC. X456UA", 205 .matches = { 206 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 207 DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"), 208 }, 209 .driver_data = &quirk_asus_wapf4, 210 }, 211 { 212 .callback = dmi_matched, 213 .ident = "ASUSTeK COMPUTER INC. X456UF", 214 .matches = { 215 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 216 DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"), 217 }, 218 .driver_data = &quirk_asus_wapf4, 219 }, 220 { 221 .callback = dmi_matched, 222 .ident = "ASUSTeK COMPUTER INC. X501U", 223 .matches = { 224 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 225 DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), 226 }, 227 .driver_data = &quirk_asus_x55u, 228 }, 229 { 230 .callback = dmi_matched, 231 .ident = "ASUSTeK COMPUTER INC. X501A", 232 .matches = { 233 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 234 DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), 235 }, 236 .driver_data = &quirk_asus_wapf4, 237 }, 238 { 239 .callback = dmi_matched, 240 .ident = "ASUSTeK COMPUTER INC. X501A1", 241 .matches = { 242 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 243 DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), 244 }, 245 .driver_data = &quirk_asus_wapf4, 246 }, 247 { 248 .callback = dmi_matched, 249 .ident = "ASUSTeK COMPUTER INC. X550CA", 250 .matches = { 251 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 252 DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), 253 }, 254 .driver_data = &quirk_asus_wapf4, 255 }, 256 { 257 .callback = dmi_matched, 258 .ident = "ASUSTeK COMPUTER INC. X550CC", 259 .matches = { 260 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 261 DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), 262 }, 263 .driver_data = &quirk_asus_wapf4, 264 }, 265 { 266 .callback = dmi_matched, 267 .ident = "ASUSTeK COMPUTER INC. X550CL", 268 .matches = { 269 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 270 DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), 271 }, 272 .driver_data = &quirk_asus_wapf4, 273 }, 274 { 275 .callback = dmi_matched, 276 .ident = "ASUSTeK COMPUTER INC. X550VB", 277 .matches = { 278 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 279 DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"), 280 }, 281 .driver_data = &quirk_asus_wapf4, 282 }, 283 { 284 .callback = dmi_matched, 285 .ident = "ASUSTeK COMPUTER INC. X551CA", 286 .matches = { 287 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 288 DMI_MATCH(DMI_PRODUCT_NAME, "X551CA"), 289 }, 290 .driver_data = &quirk_asus_wapf4, 291 }, 292 { 293 .callback = dmi_matched, 294 .ident = "ASUSTeK COMPUTER INC. X55A", 295 .matches = { 296 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 297 DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), 298 }, 299 .driver_data = &quirk_asus_wapf4, 300 }, 301 { 302 .callback = dmi_matched, 303 .ident = "ASUSTeK COMPUTER INC. X55C", 304 .matches = { 305 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 306 DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), 307 }, 308 .driver_data = &quirk_asus_wapf4, 309 }, 310 { 311 .callback = dmi_matched, 312 .ident = "ASUSTeK COMPUTER INC. X55U", 313 .matches = { 314 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 315 DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), 316 }, 317 .driver_data = &quirk_asus_x55u, 318 }, 319 { 320 .callback = dmi_matched, 321 .ident = "ASUSTeK COMPUTER INC. X55VD", 322 .matches = { 323 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 324 DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), 325 }, 326 .driver_data = &quirk_asus_wapf4, 327 }, 328 { 329 .callback = dmi_matched, 330 .ident = "ASUSTeK COMPUTER INC. X75A", 331 .matches = { 332 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 333 DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), 334 }, 335 .driver_data = &quirk_asus_wapf4, 336 }, 337 { 338 .callback = dmi_matched, 339 .ident = "ASUSTeK COMPUTER INC. X75VBP", 340 .matches = { 341 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 342 DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), 343 }, 344 .driver_data = &quirk_asus_wapf4, 345 }, 346 { 347 .callback = dmi_matched, 348 .ident = "ASUSTeK COMPUTER INC. X75VD", 349 .matches = { 350 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 351 DMI_MATCH(DMI_PRODUCT_NAME, "X75VD"), 352 }, 353 .driver_data = &quirk_asus_wapf4, 354 }, 355 { 356 .callback = dmi_matched, 357 .ident = "ASUSTeK COMPUTER INC. 1015E", 358 .matches = { 359 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 360 DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), 361 }, 362 .driver_data = &quirk_asus_wapf4, 363 }, 364 { 365 .callback = dmi_matched, 366 .ident = "ASUSTeK COMPUTER INC. 1015U", 367 .matches = { 368 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 369 DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), 370 }, 371 .driver_data = &quirk_asus_wapf4, 372 }, 373 { 374 .callback = dmi_matched, 375 .ident = "ASUSTeK COMPUTER INC. X200CA", 376 .matches = { 377 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 378 DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), 379 }, 380 .driver_data = &quirk_asus_x200ca, 381 }, 382 { 383 .callback = dmi_matched, 384 .ident = "ASUSTeK COMPUTER INC. UX303UB", 385 .matches = { 386 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 387 DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"), 388 }, 389 .driver_data = &quirk_asus_ux303ub, 390 }, 391 { 392 .callback = dmi_matched, 393 .ident = "ASUSTeK COMPUTER INC. UX330UAK", 394 .matches = { 395 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 396 DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"), 397 }, 398 .driver_data = &quirk_asus_forceals, 399 }, 400 { 401 .callback = dmi_matched, 402 .ident = "ASUSTeK COMPUTER INC. X550LB", 403 .matches = { 404 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 405 DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"), 406 }, 407 .driver_data = &quirk_asus_x550lb, 408 }, 409 { 410 .callback = dmi_matched, 411 .ident = "ASUSTeK COMPUTER INC. UX430UQ", 412 .matches = { 413 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 414 DMI_MATCH(DMI_PRODUCT_NAME, "UX430UQ"), 415 }, 416 .driver_data = &quirk_asus_forceals, 417 }, 418 { 419 .callback = dmi_matched, 420 .ident = "ASUSTeK COMPUTER INC. UX430UNR", 421 .matches = { 422 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 423 DMI_MATCH(DMI_PRODUCT_NAME, "UX430UNR"), 424 }, 425 .driver_data = &quirk_asus_forceals, 426 }, 427 { 428 .callback = dmi_matched, 429 .ident = "Asus Transformer T100TA / T100HA / T100CHI", 430 .matches = { 431 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 432 /* Match *T100* */ 433 DMI_MATCH(DMI_PRODUCT_NAME, "T100"), 434 }, 435 .driver_data = &quirk_asus_use_kbd_dock_devid, 436 }, 437 { 438 .callback = dmi_matched, 439 .ident = "Asus Transformer T101HA", 440 .matches = { 441 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 442 DMI_MATCH(DMI_PRODUCT_NAME, "T101HA"), 443 }, 444 .driver_data = &quirk_asus_use_kbd_dock_devid, 445 }, 446 { 447 .callback = dmi_matched, 448 .ident = "Asus Transformer T200TA", 449 .matches = { 450 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 451 DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"), 452 }, 453 .driver_data = &quirk_asus_use_kbd_dock_devid, 454 }, 455 { 456 .callback = dmi_matched, 457 .ident = "ASUS ZenBook Flip UX360", 458 .matches = { 459 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 460 /* Match UX360* */ 461 DMI_MATCH(DMI_PRODUCT_NAME, "UX360"), 462 }, 463 .driver_data = &quirk_asus_use_lid_flip_devid, 464 }, 465 { 466 .callback = dmi_matched, 467 .ident = "ASUS TP200s / E205SA", 468 .matches = { 469 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 470 DMI_MATCH(DMI_PRODUCT_NAME, "E205SA"), 471 }, 472 .driver_data = &quirk_asus_use_lid_flip_devid, 473 }, 474 {}, 475 }; 476 477 static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) 478 { 479 int ret; 480 481 quirks = &quirk_asus_unknown; 482 dmi_check_system(asus_quirks); 483 484 driver->quirks = quirks; 485 driver->panel_power = FB_BLANK_UNBLANK; 486 487 /* overwrite the wapf setting if the wapf paramater is specified */ 488 if (wapf != -1) 489 quirks->wapf = wapf; 490 else 491 wapf = quirks->wapf; 492 493 switch (tablet_mode_sw) { 494 case 0: 495 quirks->use_kbd_dock_devid = false; 496 quirks->use_lid_flip_devid = false; 497 break; 498 case 1: 499 quirks->use_kbd_dock_devid = true; 500 quirks->use_lid_flip_devid = false; 501 break; 502 case 2: 503 quirks->use_kbd_dock_devid = false; 504 quirks->use_lid_flip_devid = true; 505 break; 506 } 507 508 if (quirks->i8042_filter) { 509 ret = i8042_install_filter(quirks->i8042_filter); 510 if (ret) { 511 pr_warn("Unable to install key filter\n"); 512 return; 513 } 514 pr_info("Using i8042 filter function for receiving events\n"); 515 } 516 } 517 518 static const struct key_entry asus_nb_wmi_keymap[] = { 519 { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, 520 { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, 521 { KE_KEY, 0x30, { KEY_VOLUMEUP } }, 522 { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, 523 { KE_KEY, 0x32, { KEY_MUTE } }, 524 { KE_KEY, 0x35, { KEY_SCREENLOCK } }, 525 { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, 526 { KE_KEY, 0x41, { KEY_NEXTSONG } }, 527 { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ 528 { KE_KEY, 0x45, { KEY_PLAYPAUSE } }, 529 { KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */ 530 { KE_KEY, 0x50, { KEY_EMAIL } }, 531 { KE_KEY, 0x51, { KEY_WWW } }, 532 { KE_KEY, 0x55, { KEY_CALC } }, 533 { KE_IGNORE, 0x57, }, /* Battery mode */ 534 { KE_IGNORE, 0x58, }, /* AC mode */ 535 { KE_KEY, 0x5C, { KEY_F15 } }, /* Power Gear key */ 536 { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */ 537 { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */ 538 { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */ 539 { KE_KEY, 0x60, { KEY_TOUCHPAD_ON } }, 540 { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */ 541 { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */ 542 { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */ 543 { KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */ 544 { KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */ 545 { KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */ 546 { KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */ 547 { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } }, 548 { KE_IGNORE, 0x6E, }, /* Low Battery notification */ 549 { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */ 550 { KE_IGNORE, 0x79, }, /* Charger type dectection notification */ 551 { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */ 552 { KE_KEY, 0x7c, { KEY_MICMUTE } }, 553 { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ 554 { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ 555 { KE_KEY, 0x82, { KEY_CAMERA } }, 556 { KE_KEY, 0x88, { KEY_RFKILL } }, /* Radio Toggle Key */ 557 { KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */ 558 { KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */ 559 { KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */ 560 { KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */ 561 { KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */ 562 { KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */ 563 { KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */ 564 { KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */ 565 { KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */ 566 { KE_KEY, 0x95, { KEY_MEDIA } }, 567 { KE_KEY, 0x99, { KEY_PHONE } }, /* Conflicts with fan mode switch */ 568 { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ 569 { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ 570 { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ 571 { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ 572 { KE_KEY, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */ 573 { KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */ 574 { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */ 575 { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */ 576 { KE_KEY, 0xB5, { KEY_CALC } }, 577 { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, 578 { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, 579 { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ 580 { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ 581 { KE_END, 0}, 582 }; 583 584 static struct asus_wmi_driver asus_nb_wmi_driver = { 585 .name = ASUS_NB_WMI_FILE, 586 .owner = THIS_MODULE, 587 .event_guid = ASUS_NB_WMI_EVENT_GUID, 588 .keymap = asus_nb_wmi_keymap, 589 .input_name = "Asus WMI hotkeys", 590 .input_phys = ASUS_NB_WMI_FILE "/input0", 591 .detect_quirks = asus_nb_wmi_quirks, 592 }; 593 594 595 static int __init asus_nb_wmi_init(void) 596 { 597 return asus_wmi_register_driver(&asus_nb_wmi_driver); 598 } 599 600 static void __exit asus_nb_wmi_exit(void) 601 { 602 asus_wmi_unregister_driver(&asus_nb_wmi_driver); 603 } 604 605 module_init(asus_nb_wmi_init); 606 module_exit(asus_nb_wmi_exit); 607