linux/drivers/platform/x86/intel-hid.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  Intel HID event & 5 button array driver
   4 *
   5 *  Copyright (C) 2015 Alex Hung <alex.hung@canonical.com>
   6 *  Copyright (C) 2015 Andrew Lutomirski <luto@kernel.org>
   7 */
   8
   9#include <linux/acpi.h>
  10#include <linux/dmi.h>
  11#include <linux/input.h>
  12#include <linux/input/sparse-keymap.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/platform_device.h>
  16#include <linux/suspend.h>
  17
  18MODULE_LICENSE("GPL");
  19MODULE_AUTHOR("Alex Hung");
  20
  21static const struct acpi_device_id intel_hid_ids[] = {
  22        {"INT33D5", 0},
  23        {"", 0},
  24};
  25
  26/* In theory, these are HID usages. */
  27static const struct key_entry intel_hid_keymap[] = {
  28        /* 1: LSuper (Page 0x07, usage 0xE3) -- unclear what to do */
  29        /* 2: Toggle SW_ROTATE_LOCK -- easy to implement if seen in wild */
  30        { KE_KEY, 3, { KEY_NUMLOCK } },
  31        { KE_KEY, 4, { KEY_HOME } },
  32        { KE_KEY, 5, { KEY_END } },
  33        { KE_KEY, 6, { KEY_PAGEUP } },
  34        { KE_KEY, 7, { KEY_PAGEDOWN } },
  35        { KE_KEY, 8, { KEY_RFKILL } },
  36        { KE_KEY, 9, { KEY_POWER } },
  37        { KE_KEY, 11, { KEY_SLEEP } },
  38        /* 13 has two different meanings in the spec -- ignore it. */
  39        { KE_KEY, 14, { KEY_STOPCD } },
  40        { KE_KEY, 15, { KEY_PLAYPAUSE } },
  41        { KE_KEY, 16, { KEY_MUTE } },
  42        { KE_KEY, 17, { KEY_VOLUMEUP } },
  43        { KE_KEY, 18, { KEY_VOLUMEDOWN } },
  44        { KE_KEY, 19, { KEY_BRIGHTNESSUP } },
  45        { KE_KEY, 20, { KEY_BRIGHTNESSDOWN } },
  46        /* 27: wake -- needs special handling */
  47        { KE_END },
  48};
  49
  50/* 5 button array notification value. */
  51static const struct key_entry intel_array_keymap[] = {
  52        { KE_KEY,    0xC2, { KEY_LEFTMETA } },                /* Press */
  53        { KE_IGNORE, 0xC3, { KEY_LEFTMETA } },                /* Release */
  54        { KE_KEY,    0xC4, { KEY_VOLUMEUP } },                /* Press */
  55        { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } },                /* Release */
  56        { KE_KEY,    0xC6, { KEY_VOLUMEDOWN } },              /* Press */
  57        { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } },              /* Release */
  58        { KE_KEY,    0xC8, { KEY_ROTATE_LOCK_TOGGLE } },      /* Press */
  59        { KE_IGNORE, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } },      /* Release */
  60        { KE_KEY,    0xCE, { KEY_POWER } },                   /* Press */
  61        { KE_IGNORE, 0xCF, { KEY_POWER } },                   /* Release */
  62        { KE_END },
  63};
  64
  65static const struct dmi_system_id button_array_table[] = {
  66        {
  67                .ident = "Wacom MobileStudio Pro 13",
  68                .matches = {
  69                        DMI_MATCH(DMI_SYS_VENDOR, "Wacom Co.,Ltd"),
  70                        DMI_MATCH(DMI_PRODUCT_NAME, "Wacom MobileStudio Pro 13"),
  71                },
  72        },
  73        {
  74                .ident = "Wacom MobileStudio Pro 16",
  75                .matches = {
  76                        DMI_MATCH(DMI_SYS_VENDOR, "Wacom Co.,Ltd"),
  77                        DMI_MATCH(DMI_PRODUCT_NAME, "Wacom MobileStudio Pro 16"),
  78                },
  79        },
  80        { }
  81};
  82
  83struct intel_hid_priv {
  84        struct input_dev *input_dev;
  85        struct input_dev *array;
  86        bool wakeup_mode;
  87};
  88
  89#define HID_EVENT_FILTER_UUID   "eeec56b3-4442-408f-a792-4edd4d758054"
  90
  91enum intel_hid_dsm_fn_codes {
  92        INTEL_HID_DSM_FN_INVALID,
  93        INTEL_HID_DSM_BTNL_FN,
  94        INTEL_HID_DSM_HDMM_FN,
  95        INTEL_HID_DSM_HDSM_FN,
  96        INTEL_HID_DSM_HDEM_FN,
  97        INTEL_HID_DSM_BTNS_FN,
  98        INTEL_HID_DSM_BTNE_FN,
  99        INTEL_HID_DSM_HEBC_V1_FN,
 100        INTEL_HID_DSM_VGBS_FN,
 101        INTEL_HID_DSM_HEBC_V2_FN,
 102        INTEL_HID_DSM_FN_MAX
 103};
 104
 105static const char *intel_hid_dsm_fn_to_method[INTEL_HID_DSM_FN_MAX] = {
 106        NULL,
 107        "BTNL",
 108        "HDMM",
 109        "HDSM",
 110        "HDEM",
 111        "BTNS",
 112        "BTNE",
 113        "HEBC",
 114        "VGBS",
 115        "HEBC"
 116};
 117
 118static unsigned long long intel_hid_dsm_fn_mask;
 119static guid_t intel_dsm_guid;
 120
 121static bool intel_hid_execute_method(acpi_handle handle,
 122                                     enum intel_hid_dsm_fn_codes fn_index,
 123                                     unsigned long long arg)
 124{
 125        union acpi_object *obj, argv4, req;
 126        acpi_status status;
 127        char *method_name;
 128
 129        if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
 130            fn_index >= INTEL_HID_DSM_FN_MAX)
 131                return false;
 132
 133        method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
 134
 135        if (!(intel_hid_dsm_fn_mask & fn_index))
 136                goto skip_dsm_exec;
 137
 138        /* All methods expects a package with one integer element */
 139        req.type = ACPI_TYPE_INTEGER;
 140        req.integer.value = arg;
 141
 142        argv4.type = ACPI_TYPE_PACKAGE;
 143        argv4.package.count = 1;
 144        argv4.package.elements = &req;
 145
 146        obj = acpi_evaluate_dsm(handle, &intel_dsm_guid, 1, fn_index, &argv4);
 147        if (obj) {
 148                acpi_handle_debug(handle, "Exec DSM Fn code: %d[%s] success\n",
 149                                  fn_index, method_name);
 150                ACPI_FREE(obj);
 151                return true;
 152        }
 153
 154skip_dsm_exec:
 155        status = acpi_execute_simple_method(handle, method_name, arg);
 156        if (ACPI_SUCCESS(status))
 157                return true;
 158
 159        return false;
 160}
 161
 162static bool intel_hid_evaluate_method(acpi_handle handle,
 163                                      enum intel_hid_dsm_fn_codes fn_index,
 164                                      unsigned long long *result)
 165{
 166        union acpi_object *obj;
 167        acpi_status status;
 168        char *method_name;
 169
 170        if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
 171            fn_index >= INTEL_HID_DSM_FN_MAX)
 172                return false;
 173
 174        method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
 175
 176        if (!(intel_hid_dsm_fn_mask & fn_index))
 177                goto skip_dsm_eval;
 178
 179        obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid,
 180                                      1, fn_index,
 181                                      NULL,  ACPI_TYPE_INTEGER);
 182        if (obj) {
 183                *result = obj->integer.value;
 184                acpi_handle_debug(handle,
 185                                  "Eval DSM Fn code: %d[%s] results: 0x%llx\n",
 186                                  fn_index, method_name, *result);
 187                ACPI_FREE(obj);
 188                return true;
 189        }
 190
 191skip_dsm_eval:
 192        status = acpi_evaluate_integer(handle, method_name, NULL, result);
 193        if (ACPI_SUCCESS(status))
 194                return true;
 195
 196        return false;
 197}
 198
 199static void intel_hid_init_dsm(acpi_handle handle)
 200{
 201        union acpi_object *obj;
 202
 203        guid_parse(HID_EVENT_FILTER_UUID, &intel_dsm_guid);
 204
 205        obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 1, 0, NULL,
 206                                      ACPI_TYPE_BUFFER);
 207        if (obj) {
 208                intel_hid_dsm_fn_mask = *obj->buffer.pointer;
 209                ACPI_FREE(obj);
 210        }
 211
 212        acpi_handle_debug(handle, "intel_hid_dsm_fn_mask = %llx\n",
 213                          intel_hid_dsm_fn_mask);
 214}
 215
 216static int intel_hid_set_enable(struct device *device, bool enable)
 217{
 218        acpi_handle handle = ACPI_HANDLE(device);
 219
 220        /* Enable|disable features - power button is always enabled */
 221        if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN,
 222                                      enable)) {
 223                dev_warn(device, "failed to %sable hotkeys\n",
 224                         enable ? "en" : "dis");
 225                return -EIO;
 226        }
 227
 228        return 0;
 229}
 230
 231static void intel_button_array_enable(struct device *device, bool enable)
 232{
 233        struct intel_hid_priv *priv = dev_get_drvdata(device);
 234        acpi_handle handle = ACPI_HANDLE(device);
 235        unsigned long long button_cap;
 236        acpi_status status;
 237
 238        if (!priv->array)
 239                return;
 240
 241        /* Query supported platform features */
 242        status = acpi_evaluate_integer(handle, "BTNC", NULL, &button_cap);
 243        if (ACPI_FAILURE(status)) {
 244                dev_warn(device, "failed to get button capability\n");
 245                return;
 246        }
 247
 248        /* Enable|disable features - power button is always enabled */
 249        if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN,
 250                                      enable ? button_cap : 1))
 251                dev_warn(device, "failed to set button capability\n");
 252}
 253
 254static int intel_hid_pm_prepare(struct device *device)
 255{
 256        if (device_may_wakeup(device)) {
 257                struct intel_hid_priv *priv = dev_get_drvdata(device);
 258
 259                priv->wakeup_mode = true;
 260        }
 261        return 0;
 262}
 263
 264static void intel_hid_pm_complete(struct device *device)
 265{
 266        struct intel_hid_priv *priv = dev_get_drvdata(device);
 267
 268        priv->wakeup_mode = false;
 269}
 270
 271static int intel_hid_pl_suspend_handler(struct device *device)
 272{
 273        intel_button_array_enable(device, false);
 274
 275        if (!pm_suspend_no_platform())
 276                intel_hid_set_enable(device, false);
 277
 278        return 0;
 279}
 280
 281static int intel_hid_pl_resume_handler(struct device *device)
 282{
 283        intel_hid_pm_complete(device);
 284
 285        if (!pm_suspend_no_platform())
 286                intel_hid_set_enable(device, true);
 287
 288        intel_button_array_enable(device, true);
 289        return 0;
 290}
 291
 292static const struct dev_pm_ops intel_hid_pl_pm_ops = {
 293        .prepare = intel_hid_pm_prepare,
 294        .complete = intel_hid_pm_complete,
 295        .freeze  = intel_hid_pl_suspend_handler,
 296        .thaw  = intel_hid_pl_resume_handler,
 297        .restore  = intel_hid_pl_resume_handler,
 298        .suspend  = intel_hid_pl_suspend_handler,
 299        .resume  = intel_hid_pl_resume_handler,
 300};
 301
 302static int intel_hid_input_setup(struct platform_device *device)
 303{
 304        struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
 305        int ret;
 306
 307        priv->input_dev = devm_input_allocate_device(&device->dev);
 308        if (!priv->input_dev)
 309                return -ENOMEM;
 310
 311        ret = sparse_keymap_setup(priv->input_dev, intel_hid_keymap, NULL);
 312        if (ret)
 313                return ret;
 314
 315        priv->input_dev->name = "Intel HID events";
 316        priv->input_dev->id.bustype = BUS_HOST;
 317
 318        return input_register_device(priv->input_dev);
 319}
 320
 321static int intel_button_array_input_setup(struct platform_device *device)
 322{
 323        struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
 324        int ret;
 325
 326        /* Setup input device for 5 button array */
 327        priv->array = devm_input_allocate_device(&device->dev);
 328        if (!priv->array)
 329                return -ENOMEM;
 330
 331        ret = sparse_keymap_setup(priv->array, intel_array_keymap, NULL);
 332        if (ret)
 333                return ret;
 334
 335        priv->array->name = "Intel HID 5 button array";
 336        priv->array->id.bustype = BUS_HOST;
 337
 338        return input_register_device(priv->array);
 339}
 340
 341static void notify_handler(acpi_handle handle, u32 event, void *context)
 342{
 343        struct platform_device *device = context;
 344        struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
 345        unsigned long long ev_index;
 346
 347        if (priv->wakeup_mode) {
 348                /*
 349                 * Needed for wakeup from suspend-to-idle to work on some
 350                 * platforms that don't expose the 5-button array, but still
 351                 * send notifies with the power button event code to this
 352                 * device object on power button actions while suspended.
 353                 */
 354                if (event == 0xce)
 355                        goto wakeup;
 356
 357                /* Wake up on 5-button array events only. */
 358                if (event == 0xc0 || !priv->array)
 359                        return;
 360
 361                if (!sparse_keymap_entry_from_scancode(priv->array, event)) {
 362                        dev_info(&device->dev, "unknown event 0x%x\n", event);
 363                        return;
 364                }
 365
 366wakeup:
 367                pm_wakeup_hard_event(&device->dev);
 368                return;
 369        }
 370
 371        /*
 372         * Needed for suspend to work on some platforms that don't expose
 373         * the 5-button array, but still send notifies with power button
 374         * event code to this device object on power button actions.
 375         *
 376         * Report the power button press and release.
 377         */
 378        if (!priv->array) {
 379                if (event == 0xce) {
 380                        input_report_key(priv->input_dev, KEY_POWER, 1);
 381                        input_sync(priv->input_dev);
 382                        return;
 383                }
 384
 385                if (event == 0xcf) {
 386                        input_report_key(priv->input_dev, KEY_POWER, 0);
 387                        input_sync(priv->input_dev);
 388                        return;
 389                }
 390        }
 391
 392        /* 0xC0 is for HID events, other values are for 5 button array */
 393        if (event != 0xc0) {
 394                if (!priv->array ||
 395                    !sparse_keymap_report_event(priv->array, event, 1, true))
 396                        dev_dbg(&device->dev, "unknown event 0x%x\n", event);
 397                return;
 398        }
 399
 400        if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN,
 401                                       &ev_index)) {
 402                dev_warn(&device->dev, "failed to get event index\n");
 403                return;
 404        }
 405
 406        if (!sparse_keymap_report_event(priv->input_dev, ev_index, 1, true))
 407                dev_dbg(&device->dev, "unknown event index 0x%llx\n",
 408                         ev_index);
 409}
 410
 411static bool button_array_present(struct platform_device *device)
 412{
 413        acpi_handle handle = ACPI_HANDLE(&device->dev);
 414        unsigned long long event_cap;
 415
 416        if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN,
 417                                      &event_cap)) {
 418                /* Check presence of 5 button array or v2 power button */
 419                if (event_cap & 0x60000)
 420                        return true;
 421        }
 422
 423        if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN,
 424                                      &event_cap)) {
 425                if (event_cap & 0x20000)
 426                        return true;
 427        }
 428
 429        if (dmi_check_system(button_array_table))
 430                return true;
 431
 432        return false;
 433}
 434
 435static int intel_hid_probe(struct platform_device *device)
 436{
 437        acpi_handle handle = ACPI_HANDLE(&device->dev);
 438        unsigned long long mode;
 439        struct intel_hid_priv *priv;
 440        acpi_status status;
 441        int err;
 442
 443        intel_hid_init_dsm(handle);
 444
 445        if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) {
 446                dev_warn(&device->dev, "failed to read mode\n");
 447                return -ENODEV;
 448        }
 449
 450        if (mode != 0) {
 451                /*
 452                 * This driver only implements "simple" mode.  There appear
 453                 * to be no other modes, but we should be paranoid and check
 454                 * for compatibility.
 455                 */
 456                dev_info(&device->dev, "platform is not in simple mode\n");
 457                return -ENODEV;
 458        }
 459
 460        priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
 461        if (!priv)
 462                return -ENOMEM;
 463        dev_set_drvdata(&device->dev, priv);
 464
 465        err = intel_hid_input_setup(device);
 466        if (err) {
 467                pr_err("Failed to setup Intel HID hotkeys\n");
 468                return err;
 469        }
 470
 471        /* Setup 5 button array */
 472        if (button_array_present(device)) {
 473                dev_info(&device->dev, "platform supports 5 button array\n");
 474                err = intel_button_array_input_setup(device);
 475                if (err)
 476                        pr_err("Failed to setup Intel 5 button array hotkeys\n");
 477        }
 478
 479        status = acpi_install_notify_handler(handle,
 480                                             ACPI_DEVICE_NOTIFY,
 481                                             notify_handler,
 482                                             device);
 483        if (ACPI_FAILURE(status))
 484                return -EBUSY;
 485
 486        err = intel_hid_set_enable(&device->dev, true);
 487        if (err)
 488                goto err_remove_notify;
 489
 490        if (priv->array) {
 491                unsigned long long dummy;
 492
 493                intel_button_array_enable(&device->dev, true);
 494
 495                /* Call button load method to enable HID power button */
 496                if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
 497                                               &dummy)) {
 498                        dev_warn(&device->dev,
 499                                 "failed to enable HID power button\n");
 500                }
 501        }
 502
 503        device_init_wakeup(&device->dev, true);
 504        /*
 505         * In order for system wakeup to work, the EC GPE has to be marked as
 506         * a wakeup one, so do that here (this setting will persist, but it has
 507         * no effect until the wakeup mask is set for the EC GPE).
 508         */
 509        acpi_ec_mark_gpe_for_wake();
 510        return 0;
 511
 512err_remove_notify:
 513        acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
 514
 515        return err;
 516}
 517
 518static int intel_hid_remove(struct platform_device *device)
 519{
 520        acpi_handle handle = ACPI_HANDLE(&device->dev);
 521
 522        device_init_wakeup(&device->dev, false);
 523        acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
 524        intel_hid_set_enable(&device->dev, false);
 525        intel_button_array_enable(&device->dev, false);
 526
 527        /*
 528         * Even if we failed to shut off the event stream, we can still
 529         * safely detach from the device.
 530         */
 531        return 0;
 532}
 533
 534static struct platform_driver intel_hid_pl_driver = {
 535        .driver = {
 536                .name = "intel-hid",
 537                .acpi_match_table = intel_hid_ids,
 538                .pm = &intel_hid_pl_pm_ops,
 539        },
 540        .probe = intel_hid_probe,
 541        .remove = intel_hid_remove,
 542};
 543MODULE_DEVICE_TABLE(acpi, intel_hid_ids);
 544
 545/*
 546 * Unfortunately, some laptops provide a _HID="INT33D5" device with
 547 * _CID="PNP0C02".  This causes the pnpacpi scan driver to claim the
 548 * ACPI node, so no platform device will be created.  The pnpacpi
 549 * driver rejects this device in subsequent processing, so no physical
 550 * node is created at all.
 551 *
 552 * As a workaround until the ACPI core figures out how to handle
 553 * this corner case, manually ask the ACPI platform device code to
 554 * claim the ACPI node.
 555 */
 556static acpi_status __init
 557check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
 558{
 559        const struct acpi_device_id *ids = context;
 560        struct acpi_device *dev;
 561
 562        if (acpi_bus_get_device(handle, &dev) != 0)
 563                return AE_OK;
 564
 565        if (acpi_match_device_ids(dev, ids) == 0)
 566                if (acpi_create_platform_device(dev, NULL))
 567                        dev_info(&dev->dev,
 568                                 "intel-hid: created platform device\n");
 569
 570        return AE_OK;
 571}
 572
 573static int __init intel_hid_init(void)
 574{
 575        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
 576                            ACPI_UINT32_MAX, check_acpi_dev, NULL,
 577                            (void *)intel_hid_ids, NULL);
 578
 579        return platform_driver_register(&intel_hid_pl_driver);
 580}
 581module_init(intel_hid_init);
 582
 583static void __exit intel_hid_exit(void)
 584{
 585        platform_driver_unregister(&intel_hid_pl_driver);
 586}
 587module_exit(intel_hid_exit);
 588