linux/drivers/platform/x86/dell/dell-wmi-base.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Dell WMI hotkeys
   4 *
   5 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
   6 * Copyright (C) 2014-2015 Pali Rohár <pali@kernel.org>
   7 *
   8 * Portions based on wistron_btns.c:
   9 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
  10 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
  11 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
  12 */
  13
  14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19#include <linux/slab.h>
  20#include <linux/types.h>
  21#include <linux/input.h>
  22#include <linux/input/sparse-keymap.h>
  23#include <linux/acpi.h>
  24#include <linux/string.h>
  25#include <linux/dmi.h>
  26#include <linux/wmi.h>
  27#include <acpi/video.h>
  28#include "dell-smbios.h"
  29#include "dell-wmi-descriptor.h"
  30#include "dell-wmi-privacy.h"
  31
  32MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
  33MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
  34MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
  35MODULE_LICENSE("GPL");
  36
  37#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
  38
  39static bool wmi_requires_smbios_request;
  40
  41struct dell_wmi_priv {
  42        struct input_dev *input_dev;
  43        u32 interface_version;
  44};
  45
  46static int __init dmi_matched(const struct dmi_system_id *dmi)
  47{
  48        wmi_requires_smbios_request = 1;
  49        return 1;
  50}
  51
  52static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
  53        {
  54                .callback = dmi_matched,
  55                .ident = "Dell Inspiron M5110",
  56                .matches = {
  57                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  58                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
  59                },
  60        },
  61        {
  62                .callback = dmi_matched,
  63                .ident = "Dell Vostro V131",
  64                .matches = {
  65                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  66                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
  67                },
  68        },
  69        { }
  70};
  71
  72/*
  73 * Keymap for WMI events of type 0x0000
  74 *
  75 * Certain keys are flagged as KE_IGNORE. All of these are either
  76 * notifications (rather than requests for change) or are also sent
  77 * via the keyboard controller so should not be sent again.
  78 */
  79static const struct key_entry dell_wmi_keymap_type_0000[] = {
  80        { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
  81
  82        /* Key code is followed by brightness level */
  83        { KE_KEY,    0xe005, { KEY_BRIGHTNESSDOWN } },
  84        { KE_KEY,    0xe006, { KEY_BRIGHTNESSUP } },
  85
  86        /* Battery health status button */
  87        { KE_KEY,    0xe007, { KEY_BATTERY } },
  88
  89        /* Radio devices state change, key code is followed by other values */
  90        { KE_IGNORE, 0xe008, { KEY_RFKILL } },
  91
  92        { KE_KEY,    0xe009, { KEY_EJECTCD } },
  93
  94        /* Key code is followed by: next, active and attached devices */
  95        { KE_KEY,    0xe00b, { KEY_SWITCHVIDEOMODE } },
  96
  97        /* Key code is followed by keyboard illumination level */
  98        { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
  99
 100        /* BIOS error detected */
 101        { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
 102
 103        /* Battery was removed or inserted */
 104        { KE_IGNORE, 0xe00e, { KEY_RESERVED } },
 105
 106        /* Wifi Catcher */
 107        { KE_KEY,    0xe011, { KEY_WLAN } },
 108
 109        /* Ambient light sensor toggle */
 110        { KE_IGNORE, 0xe013, { KEY_RESERVED } },
 111
 112        { KE_IGNORE, 0xe020, { KEY_MUTE } },
 113
 114        /* Unknown, defined in ACPI DSDT */
 115        /* { KE_IGNORE, 0xe023, { KEY_RESERVED } }, */
 116
 117        /* Untested, Dell Instant Launch key on Inspiron 7520 */
 118        /* { KE_IGNORE, 0xe024, { KEY_RESERVED } }, */
 119
 120        /* Dell Instant Launch key */
 121        { KE_KEY,    0xe025, { KEY_PROG4 } },
 122
 123        /* Audio panel key */
 124        { KE_IGNORE, 0xe026, { KEY_RESERVED } },
 125
 126        /* LCD Display On/Off Control key */
 127        { KE_KEY,    0xe027, { KEY_DISPLAYTOGGLE } },
 128
 129        /* Untested, Multimedia key on Dell Vostro 3560 */
 130        /* { KE_IGNORE, 0xe028, { KEY_RESERVED } }, */
 131
 132        /* Dell Instant Launch key */
 133        { KE_KEY,    0xe029, { KEY_PROG4 } },
 134
 135        /* Untested, Windows Mobility Center button on Inspiron 7520 */
 136        /* { KE_IGNORE, 0xe02a, { KEY_RESERVED } }, */
 137
 138        /* Unknown, defined in ACPI DSDT */
 139        /* { KE_IGNORE, 0xe02b, { KEY_RESERVED } }, */
 140
 141        /* Untested, Dell Audio With Preset Switch button on Inspiron 7520 */
 142        /* { KE_IGNORE, 0xe02c, { KEY_RESERVED } }, */
 143
 144        { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
 145        { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
 146        { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
 147        { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
 148        { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
 149
 150        /* NIC Link is Up */
 151        { KE_IGNORE, 0xe043, { KEY_RESERVED } },
 152
 153        /* NIC Link is Down */
 154        { KE_IGNORE, 0xe044, { KEY_RESERVED } },
 155
 156        /*
 157         * This entry is very suspicious!
 158         * Originally Matthew Garrett created this dell-wmi driver specially for
 159         * "button with a picture of a battery" which has event code 0xe045.
 160         * Later Mario Limonciello from Dell told us that event code 0xe045 is
 161         * reported by Num Lock and should be ignored because key is send also
 162         * by keyboard controller.
 163         * So for now we will ignore this event to prevent potential double
 164         * Num Lock key press.
 165         */
 166        { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
 167
 168        /* Scroll lock and also going to tablet mode on portable devices */
 169        { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
 170
 171        /* Untested, going from tablet mode on portable devices */
 172        /* { KE_IGNORE, 0xe047, { KEY_RESERVED } }, */
 173
 174        /* Dell Support Center key */
 175        { KE_IGNORE, 0xe06e, { KEY_RESERVED } },
 176
 177        { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
 178        { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
 179        { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
 180};
 181
 182struct dell_bios_keymap_entry {
 183        u16 scancode;
 184        u16 keycode;
 185};
 186
 187struct dell_bios_hotkey_table {
 188        struct dmi_header header;
 189        struct dell_bios_keymap_entry keymap[];
 190
 191};
 192
 193struct dell_dmi_results {
 194        int err;
 195        int keymap_size;
 196        struct key_entry *keymap;
 197};
 198
 199/* Uninitialized entries here are KEY_RESERVED == 0. */
 200static const u16 bios_to_linux_keycode[256] = {
 201        [0]     = KEY_MEDIA,
 202        [1]     = KEY_NEXTSONG,
 203        [2]     = KEY_PLAYPAUSE,
 204        [3]     = KEY_PREVIOUSSONG,
 205        [4]     = KEY_STOPCD,
 206        [5]     = KEY_UNKNOWN,
 207        [6]     = KEY_UNKNOWN,
 208        [7]     = KEY_UNKNOWN,
 209        [8]     = KEY_WWW,
 210        [9]     = KEY_UNKNOWN,
 211        [10]    = KEY_VOLUMEDOWN,
 212        [11]    = KEY_MUTE,
 213        [12]    = KEY_VOLUMEUP,
 214        [13]    = KEY_UNKNOWN,
 215        [14]    = KEY_BATTERY,
 216        [15]    = KEY_EJECTCD,
 217        [16]    = KEY_UNKNOWN,
 218        [17]    = KEY_SLEEP,
 219        [18]    = KEY_PROG1,
 220        [19]    = KEY_BRIGHTNESSDOWN,
 221        [20]    = KEY_BRIGHTNESSUP,
 222        [21]    = KEY_BRIGHTNESS_AUTO,
 223        [22]    = KEY_KBDILLUMTOGGLE,
 224        [23]    = KEY_UNKNOWN,
 225        [24]    = KEY_SWITCHVIDEOMODE,
 226        [25]    = KEY_UNKNOWN,
 227        [26]    = KEY_UNKNOWN,
 228        [27]    = KEY_SWITCHVIDEOMODE,
 229        [28]    = KEY_UNKNOWN,
 230        [29]    = KEY_UNKNOWN,
 231        [30]    = KEY_PROG2,
 232        [31]    = KEY_UNKNOWN,
 233        [32]    = KEY_UNKNOWN,
 234        [33]    = KEY_UNKNOWN,
 235        [34]    = KEY_UNKNOWN,
 236        [35]    = KEY_UNKNOWN,
 237        [36]    = KEY_UNKNOWN,
 238        [37]    = KEY_UNKNOWN,
 239        [38]    = KEY_MICMUTE,
 240        [255]   = KEY_PROG3,
 241};
 242
 243/*
 244 * Keymap for WMI events of type 0x0010
 245 *
 246 * These are applied if the 0xB2 DMI hotkey table is present and doesn't
 247 * override them.
 248 */
 249static const struct key_entry dell_wmi_keymap_type_0010[] = {
 250        /* Fn-lock switched to function keys */
 251        { KE_IGNORE, 0x0, { KEY_RESERVED } },
 252
 253        /* Fn-lock switched to multimedia keys */
 254        { KE_IGNORE, 0x1, { KEY_RESERVED } },
 255
 256        /* Keyboard backlight change notification */
 257        { KE_IGNORE, 0x3f, { KEY_RESERVED } },
 258
 259        /* Backlight brightness level */
 260        { KE_KEY,    0x57, { KEY_BRIGHTNESSDOWN } },
 261        { KE_KEY,    0x58, { KEY_BRIGHTNESSUP } },
 262
 263        /* Mic mute */
 264        { KE_KEY, 0x150, { KEY_MICMUTE } },
 265
 266        /* Fn-lock */
 267        { KE_IGNORE, 0x151, { KEY_RESERVED } },
 268
 269        /* Change keyboard illumination */
 270        { KE_IGNORE, 0x152, { KEY_KBDILLUMTOGGLE } },
 271
 272        /*
 273         * Radio disable (notify only -- there is no model for which the
 274         * WMI event is supposed to trigger an action).
 275         */
 276        { KE_IGNORE, 0x153, { KEY_RFKILL } },
 277
 278        /* RGB keyboard backlight control */
 279        { KE_IGNORE, 0x154, { KEY_RESERVED } },
 280
 281        /*
 282         * Stealth mode toggle. This will "disable all lights and sounds".
 283         * The action is performed by the BIOS and EC; the WMI event is just
 284         * a notification. On the XPS 13 9350, this is Fn+F7, and there's
 285         * a BIOS setting to enable and disable the hotkey.
 286         */
 287        { KE_IGNORE, 0x155, { KEY_RESERVED } },
 288
 289        /* Rugged magnetic dock attach/detach events */
 290        { KE_IGNORE, 0x156, { KEY_RESERVED } },
 291        { KE_IGNORE, 0x157, { KEY_RESERVED } },
 292
 293        /* Rugged programmable (P1/P2/P3 keys) */
 294        { KE_KEY,    0x850, { KEY_PROG1 } },
 295        { KE_KEY,    0x851, { KEY_PROG2 } },
 296        { KE_KEY,    0x852, { KEY_PROG3 } },
 297
 298        /*
 299         * Radio disable (notify only -- there is no model for which the
 300         * WMI event is supposed to trigger an action).
 301         */
 302        { KE_IGNORE, 0xe008, { KEY_RFKILL } },
 303
 304        /* Fn-lock */
 305        { KE_IGNORE, 0xe035, { KEY_RESERVED } },
 306};
 307
 308/*
 309 * Keymap for WMI events of type 0x0011
 310 */
 311static const struct key_entry dell_wmi_keymap_type_0011[] = {
 312        /* Battery unplugged */
 313        { KE_IGNORE, 0xfff0, { KEY_RESERVED } },
 314
 315        /* Battery inserted */
 316        { KE_IGNORE, 0xfff1, { KEY_RESERVED } },
 317
 318        /*
 319         * Detachable keyboard detached / undocked
 320         * Note SW_TABLET_MODE is already reported through the intel_vbtn
 321         * driver for this, so we ignore it.
 322         */
 323        { KE_IGNORE, 0xfff2, { KEY_RESERVED } },
 324
 325        /* Detachable keyboard attached / docked */
 326        { KE_IGNORE, 0xfff3, { KEY_RESERVED } },
 327
 328        /* Keyboard backlight level changed */
 329        { KE_IGNORE, KBD_LED_OFF_TOKEN,      { KEY_RESERVED } },
 330        { KE_IGNORE, KBD_LED_ON_TOKEN,       { KEY_RESERVED } },
 331        { KE_IGNORE, KBD_LED_AUTO_TOKEN,     { KEY_RESERVED } },
 332        { KE_IGNORE, KBD_LED_AUTO_25_TOKEN,  { KEY_RESERVED } },
 333        { KE_IGNORE, KBD_LED_AUTO_50_TOKEN,  { KEY_RESERVED } },
 334        { KE_IGNORE, KBD_LED_AUTO_75_TOKEN,  { KEY_RESERVED } },
 335        { KE_IGNORE, KBD_LED_AUTO_100_TOKEN, { KEY_RESERVED } },
 336};
 337
 338/*
 339 * Keymap for WMI events of type 0x0012
 340 * They are events with extended data
 341 */
 342static const struct key_entry dell_wmi_keymap_type_0012[] = {
 343        /* Fn-lock button pressed */
 344        { KE_IGNORE, 0xe035, { KEY_RESERVED } },
 345};
 346
 347static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
 348{
 349        struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 350        const struct key_entry *key;
 351
 352        key = sparse_keymap_entry_from_scancode(priv->input_dev,
 353                                                (type << 16) | code);
 354        if (!key) {
 355                pr_info("Unknown key with type 0x%04x and code 0x%04x pressed\n",
 356                        type, code);
 357                return;
 358        }
 359
 360        pr_debug("Key with type 0x%04x and code 0x%04x pressed\n", type, code);
 361
 362        /* Don't report brightness notifications that will also come via ACPI */
 363        if ((key->keycode == KEY_BRIGHTNESSUP ||
 364             key->keycode == KEY_BRIGHTNESSDOWN) &&
 365            acpi_video_handles_brightness_key_presses())
 366                return;
 367
 368        if (type == 0x0000 && code == 0xe025 && !wmi_requires_smbios_request)
 369                return;
 370
 371        if (key->keycode == KEY_KBDILLUMTOGGLE)
 372                dell_laptop_call_notifier(
 373                        DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED, NULL);
 374
 375        sparse_keymap_report_entry(priv->input_dev, key, 1, true);
 376}
 377
 378static void dell_wmi_notify(struct wmi_device *wdev,
 379                            union acpi_object *obj)
 380{
 381        struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 382        u16 *buffer_entry, *buffer_end;
 383        acpi_size buffer_size;
 384        int len, i;
 385
 386        if (obj->type != ACPI_TYPE_BUFFER) {
 387                pr_warn("bad response type %x\n", obj->type);
 388                return;
 389        }
 390
 391        pr_debug("Received WMI event (%*ph)\n",
 392                obj->buffer.length, obj->buffer.pointer);
 393
 394        buffer_entry = (u16 *)obj->buffer.pointer;
 395        buffer_size = obj->buffer.length/2;
 396        buffer_end = buffer_entry + buffer_size;
 397
 398        /*
 399         * BIOS/ACPI on devices with WMI interface version 0 does not clear
 400         * buffer before filling it. So next time when BIOS/ACPI send WMI event
 401         * which is smaller as previous then it contains garbage in buffer from
 402         * previous event.
 403         *
 404         * BIOS/ACPI on devices with WMI interface version 1 clears buffer and
 405         * sometimes send more events in buffer at one call.
 406         *
 407         * So to prevent reading garbage from buffer we will process only first
 408         * one event on devices with WMI interface version 0.
 409         */
 410        if (priv->interface_version == 0 && buffer_entry < buffer_end)
 411                if (buffer_end > buffer_entry + buffer_entry[0] + 1)
 412                        buffer_end = buffer_entry + buffer_entry[0] + 1;
 413
 414        while (buffer_entry < buffer_end) {
 415
 416                len = buffer_entry[0];
 417                if (len == 0)
 418                        break;
 419
 420                len++;
 421
 422                if (buffer_entry + len > buffer_end) {
 423                        pr_warn("Invalid length of WMI event\n");
 424                        break;
 425                }
 426
 427                pr_debug("Process buffer (%*ph)\n", len*2, buffer_entry);
 428
 429                switch (buffer_entry[1]) {
 430                case 0x0000: /* One key pressed or event occurred */
 431                        if (len > 2)
 432                                dell_wmi_process_key(wdev, buffer_entry[1],
 433                                                     buffer_entry[2]);
 434                        /* Extended data is currently ignored */
 435                        break;
 436                case 0x0010: /* Sequence of keys pressed */
 437                case 0x0011: /* Sequence of events occurred */
 438                        for (i = 2; i < len; ++i)
 439                                dell_wmi_process_key(wdev, buffer_entry[1],
 440                                                     buffer_entry[i]);
 441                        break;
 442                case 0x0012:
 443                        if ((len > 4) && dell_privacy_process_event(buffer_entry[1], buffer_entry[3],
 444                                                                    buffer_entry[4]))
 445                                /* dell_privacy_process_event has handled the event */;
 446                        else if (len > 2)
 447                                dell_wmi_process_key(wdev, buffer_entry[1], buffer_entry[2]);
 448                        break;
 449                default: /* Unknown event */
 450                        pr_info("Unknown WMI event type 0x%x\n",
 451                                (int)buffer_entry[1]);
 452                        break;
 453                }
 454
 455                buffer_entry += len;
 456
 457        }
 458
 459}
 460
 461static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len)
 462{
 463        int i;
 464
 465        for (i = 0; i < len; i++)
 466                if (keymap[i].code == scancode)
 467                        return true;
 468
 469        return false;
 470}
 471
 472static void handle_dmi_entry(const struct dmi_header *dm, void *opaque)
 473{
 474        struct dell_dmi_results *results = opaque;
 475        struct dell_bios_hotkey_table *table;
 476        int hotkey_num, i, pos = 0;
 477        struct key_entry *keymap;
 478
 479        if (results->err || results->keymap)
 480                return;         /* We already found the hotkey table. */
 481
 482        /* The Dell hotkey table is type 0xB2.  Scan until we find it. */
 483        if (dm->type != 0xb2)
 484                return;
 485
 486        table = container_of(dm, struct dell_bios_hotkey_table, header);
 487
 488        hotkey_num = (table->header.length -
 489                      sizeof(struct dell_bios_hotkey_table)) /
 490                                sizeof(struct dell_bios_keymap_entry);
 491        if (hotkey_num < 1) {
 492                /*
 493                 * Historically, dell-wmi would ignore a DMI entry of
 494                 * fewer than 7 bytes.  Sizes between 4 and 8 bytes are
 495                 * nonsensical (both the header and all entries are 4
 496                 * bytes), so we approximate the old behavior by
 497                 * ignoring tables with fewer than one entry.
 498                 */
 499                return;
 500        }
 501
 502        keymap = kcalloc(hotkey_num, sizeof(struct key_entry), GFP_KERNEL);
 503        if (!keymap) {
 504                results->err = -ENOMEM;
 505                return;
 506        }
 507
 508        for (i = 0; i < hotkey_num; i++) {
 509                const struct dell_bios_keymap_entry *bios_entry =
 510                                        &table->keymap[i];
 511
 512                /* Uninitialized entries are 0 aka KEY_RESERVED. */
 513                u16 keycode = (bios_entry->keycode <
 514                               ARRAY_SIZE(bios_to_linux_keycode)) ?
 515                        bios_to_linux_keycode[bios_entry->keycode] :
 516                        (bios_entry->keycode == 0xffff ? KEY_UNKNOWN : KEY_RESERVED);
 517
 518                /*
 519                 * Log if we find an entry in the DMI table that we don't
 520                 * understand.  If this happens, we should figure out what
 521                 * the entry means and add it to bios_to_linux_keycode.
 522                 */
 523                if (keycode == KEY_RESERVED) {
 524                        pr_info("firmware scancode 0x%x maps to unrecognized keycode 0x%x\n",
 525                                bios_entry->scancode, bios_entry->keycode);
 526                        continue;
 527                }
 528
 529                if (keycode == KEY_KBDILLUMTOGGLE)
 530                        keymap[pos].type = KE_IGNORE;
 531                else
 532                        keymap[pos].type = KE_KEY;
 533                keymap[pos].code = bios_entry->scancode;
 534                keymap[pos].keycode = keycode;
 535
 536                pos++;
 537        }
 538
 539        results->keymap = keymap;
 540        results->keymap_size = pos;
 541}
 542
 543static int dell_wmi_input_setup(struct wmi_device *wdev)
 544{
 545        struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 546        struct dell_dmi_results dmi_results = {};
 547        struct key_entry *keymap;
 548        int err, i, pos = 0;
 549
 550        priv->input_dev = input_allocate_device();
 551        if (!priv->input_dev)
 552                return -ENOMEM;
 553
 554        priv->input_dev->name = "Dell WMI hotkeys";
 555        priv->input_dev->id.bustype = BUS_HOST;
 556        priv->input_dev->dev.parent = &wdev->dev;
 557
 558        if (dmi_walk(handle_dmi_entry, &dmi_results)) {
 559                /*
 560                 * Historically, dell-wmi ignored dmi_walk errors.  A failure
 561                 * is certainly surprising, but it probably just indicates
 562                 * a very old laptop.
 563                 */
 564                pr_warn("no DMI; using the old-style hotkey interface\n");
 565        }
 566
 567        if (dmi_results.err) {
 568                err = dmi_results.err;
 569                goto err_free_dev;
 570        }
 571
 572        keymap = kcalloc(dmi_results.keymap_size +
 573                         ARRAY_SIZE(dell_wmi_keymap_type_0000) +
 574                         ARRAY_SIZE(dell_wmi_keymap_type_0010) +
 575                         ARRAY_SIZE(dell_wmi_keymap_type_0011) +
 576                         ARRAY_SIZE(dell_wmi_keymap_type_0012) +
 577                         1,
 578                         sizeof(struct key_entry), GFP_KERNEL);
 579        if (!keymap) {
 580                kfree(dmi_results.keymap);
 581                err = -ENOMEM;
 582                goto err_free_dev;
 583        }
 584
 585        /* Append table with events of type 0x0010 which comes from DMI */
 586        for (i = 0; i < dmi_results.keymap_size; i++) {
 587                keymap[pos] = dmi_results.keymap[i];
 588                keymap[pos].code |= (0x0010 << 16);
 589                pos++;
 590        }
 591
 592        kfree(dmi_results.keymap);
 593
 594        /* Append table with extra events of type 0x0010 which are not in DMI */
 595        for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0010); i++) {
 596                const struct key_entry *entry = &dell_wmi_keymap_type_0010[i];
 597
 598                /*
 599                 * Check if we've already found this scancode.  This takes
 600                 * quadratic time, but it doesn't matter unless the list
 601                 * of extra keys gets very long.
 602                 */
 603                if (dmi_results.keymap_size &&
 604                    have_scancode(entry->code | (0x0010 << 16),
 605                                  keymap, dmi_results.keymap_size)
 606                   )
 607                        continue;
 608
 609                keymap[pos] = *entry;
 610                keymap[pos].code |= (0x0010 << 16);
 611                pos++;
 612        }
 613
 614        /* Append table with events of type 0x0011 */
 615        for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0011); i++) {
 616                keymap[pos] = dell_wmi_keymap_type_0011[i];
 617                keymap[pos].code |= (0x0011 << 16);
 618                pos++;
 619        }
 620
 621        /* Append table with events of type 0x0012 */
 622        for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
 623                keymap[pos] = dell_wmi_keymap_type_0012[i];
 624                keymap[pos].code |= (0x0012 << 16);
 625                pos++;
 626        }
 627
 628        /*
 629         * Now append also table with "legacy" events of type 0x0000. Some of
 630         * them are reported also on laptops which have scancodes in DMI.
 631         */
 632        for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0000); i++) {
 633                keymap[pos] = dell_wmi_keymap_type_0000[i];
 634                pos++;
 635        }
 636
 637        keymap[pos].type = KE_END;
 638
 639        err = sparse_keymap_setup(priv->input_dev, keymap, NULL);
 640        /*
 641         * Sparse keymap library makes a copy of keymap so we don't need the
 642         * original one that was allocated.
 643         */
 644        kfree(keymap);
 645        if (err)
 646                goto err_free_dev;
 647
 648        err = input_register_device(priv->input_dev);
 649        if (err)
 650                goto err_free_dev;
 651
 652        return 0;
 653
 654 err_free_dev:
 655        input_free_device(priv->input_dev);
 656        return err;
 657}
 658
 659static void dell_wmi_input_destroy(struct wmi_device *wdev)
 660{
 661        struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 662
 663        input_unregister_device(priv->input_dev);
 664}
 665
 666/*
 667 * According to Dell SMBIOS documentation:
 668 *
 669 * 17  3  Application Program Registration
 670 *
 671 *     cbArg1 Application ID 1 = 0x00010000
 672 *     cbArg2 Application ID 2
 673 *            QUICKSET/DCP = 0x51534554 "QSET"
 674 *            ALS Driver   = 0x416c7353 "AlsS"
 675 *            Latitude ON  = 0x4c6f6e52 "LonR"
 676 *     cbArg3 Application version or revision number
 677 *     cbArg4 0 = Unregister application
 678 *            1 = Register application
 679 *     cbRes1 Standard return codes (0, -1, -2)
 680 */
 681
 682static int dell_wmi_events_set_enabled(bool enable)
 683{
 684        struct calling_interface_buffer *buffer;
 685        int ret;
 686
 687        buffer = kzalloc(sizeof(struct calling_interface_buffer), GFP_KERNEL);
 688        if (!buffer)
 689                return -ENOMEM;
 690        buffer->cmd_class = CLASS_INFO;
 691        buffer->cmd_select = SELECT_APP_REGISTRATION;
 692        buffer->input[0] = 0x10000;
 693        buffer->input[1] = 0x51534554;
 694        buffer->input[3] = enable;
 695        ret = dell_smbios_call(buffer);
 696        if (ret == 0)
 697                ret = buffer->output[0];
 698        kfree(buffer);
 699
 700        return dell_smbios_error(ret);
 701}
 702
 703static int dell_wmi_probe(struct wmi_device *wdev, const void *context)
 704{
 705        struct dell_wmi_priv *priv;
 706        int ret;
 707
 708        ret = dell_wmi_get_descriptor_valid();
 709        if (ret)
 710                return ret;
 711
 712        priv = devm_kzalloc(
 713                &wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL);
 714        if (!priv)
 715                return -ENOMEM;
 716        dev_set_drvdata(&wdev->dev, priv);
 717
 718        if (!dell_wmi_get_interface_version(&priv->interface_version))
 719                return -EPROBE_DEFER;
 720
 721        return dell_wmi_input_setup(wdev);
 722}
 723
 724static void dell_wmi_remove(struct wmi_device *wdev)
 725{
 726        dell_wmi_input_destroy(wdev);
 727}
 728static const struct wmi_device_id dell_wmi_id_table[] = {
 729        { .guid_string = DELL_EVENT_GUID },
 730        { },
 731};
 732
 733static struct wmi_driver dell_wmi_driver = {
 734        .driver = {
 735                .name = "dell-wmi",
 736        },
 737        .id_table = dell_wmi_id_table,
 738        .probe = dell_wmi_probe,
 739        .remove = dell_wmi_remove,
 740        .notify = dell_wmi_notify,
 741};
 742
 743static int __init dell_wmi_init(void)
 744{
 745        int err;
 746
 747        dmi_check_system(dell_wmi_smbios_list);
 748
 749        if (wmi_requires_smbios_request) {
 750                err = dell_wmi_events_set_enabled(true);
 751                if (err) {
 752                        pr_err("Failed to enable WMI events\n");
 753                        return err;
 754                }
 755        }
 756
 757        err = dell_privacy_register_driver();
 758        if (err)
 759                return err;
 760
 761        return wmi_driver_register(&dell_wmi_driver);
 762}
 763late_initcall(dell_wmi_init);
 764
 765static void __exit dell_wmi_exit(void)
 766{
 767        if (wmi_requires_smbios_request)
 768                dell_wmi_events_set_enabled(false);
 769
 770        wmi_driver_unregister(&dell_wmi_driver);
 771        dell_privacy_unregister_driver();
 772}
 773module_exit(dell_wmi_exit);
 774
 775MODULE_DEVICE_TABLE(wmi, dell_wmi_id_table);
 776