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