linux/drivers/platform/x86/asus-nb-wmi.c
<<
>>
Prefs
   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
  23MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
  24MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
  25MODULE_LICENSE("GPL");
  26
  27#define ASUS_NB_WMI_EVENT_GUID  "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
  28
  29MODULE_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 */
  40static int wapf = -1;
  41module_param(wapf, uint, 0444);
  42MODULE_PARM_DESC(wapf, "WAPF value");
  43
  44static int tablet_mode_sw = -1;
  45module_param(tablet_mode_sw, uint, 0444);
  46MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip");
  47
  48static struct quirk_entry *quirks;
  49
  50static 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
  70static struct quirk_entry quirk_asus_unknown = {
  71        .wapf = 0,
  72        .wmi_backlight_set_devstate = true,
  73};
  74
  75static 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 */
  85static 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
  92static struct quirk_entry quirk_asus_wapf4 = {
  93        .wapf = 4,
  94        .wmi_backlight_set_devstate = true,
  95};
  96
  97static struct quirk_entry quirk_asus_x200ca = {
  98        .wapf = 2,
  99        .wmi_backlight_set_devstate = true,
 100};
 101
 102static struct quirk_entry quirk_asus_ux303ub = {
 103        .wmi_backlight_native = true,
 104        .wmi_backlight_set_devstate = true,
 105};
 106
 107static struct quirk_entry quirk_asus_x550lb = {
 108        .wmi_backlight_set_devstate = true,
 109        .xusb2pr = 0x01D9,
 110};
 111
 112static struct quirk_entry quirk_asus_forceals = {
 113        .wmi_backlight_set_devstate = true,
 114        .wmi_force_als_set = true,
 115};
 116
 117static struct quirk_entry quirk_asus_use_kbd_dock_devid = {
 118        .use_kbd_dock_devid = true,
 119};
 120
 121static struct quirk_entry quirk_asus_use_lid_flip_devid = {
 122        .wmi_backlight_set_devstate = true,
 123        .use_lid_flip_devid = true,
 124};
 125
 126static 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
 133static 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
 477static 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
 518static 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
 584static 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
 595static int __init asus_nb_wmi_init(void)
 596{
 597        return asus_wmi_register_driver(&asus_nb_wmi_driver);
 598}
 599
 600static void __exit asus_nb_wmi_exit(void)
 601{
 602        asus_wmi_unregister_driver(&asus_nb_wmi_driver);
 603}
 604
 605module_init(asus_nb_wmi_init);
 606module_exit(asus_nb_wmi_exit);
 607