linux/drivers/platform/x86/wireless-hotkey.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Airplane mode button for AMD, HP & Xiaomi laptops
   4 *
   5 *  Copyright (C) 2014-2017 Alex Hung <alex.hung@canonical.com>
   6 *  Copyright (C) 2021 Advanced Micro Devices
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/module.h>
  11#include <linux/init.h>
  12#include <linux/input.h>
  13#include <linux/platform_device.h>
  14#include <linux/acpi.h>
  15#include <acpi/acpi_bus.h>
  16
  17MODULE_LICENSE("GPL");
  18MODULE_AUTHOR("Alex Hung");
  19MODULE_ALIAS("acpi*:HPQ6001:*");
  20MODULE_ALIAS("acpi*:WSTADEF:*");
  21MODULE_ALIAS("acpi*:AMDI0051:*");
  22
  23static struct input_dev *wl_input_dev;
  24
  25static const struct acpi_device_id wl_ids[] = {
  26        {"HPQ6001", 0},
  27        {"WSTADEF", 0},
  28        {"AMDI0051", 0},
  29        {"", 0},
  30};
  31
  32static int wireless_input_setup(void)
  33{
  34        int err;
  35
  36        wl_input_dev = input_allocate_device();
  37        if (!wl_input_dev)
  38                return -ENOMEM;
  39
  40        wl_input_dev->name = "Wireless hotkeys";
  41        wl_input_dev->phys = "hpq6001/input0";
  42        wl_input_dev->id.bustype = BUS_HOST;
  43        wl_input_dev->evbit[0] = BIT(EV_KEY);
  44        set_bit(KEY_RFKILL, wl_input_dev->keybit);
  45
  46        err = input_register_device(wl_input_dev);
  47        if (err)
  48                goto err_free_dev;
  49
  50        return 0;
  51
  52err_free_dev:
  53        input_free_device(wl_input_dev);
  54        return err;
  55}
  56
  57static void wireless_input_destroy(void)
  58{
  59        input_unregister_device(wl_input_dev);
  60}
  61
  62static void wl_notify(struct acpi_device *acpi_dev, u32 event)
  63{
  64        if (event != 0x80) {
  65                pr_info("Received unknown event (0x%x)\n", event);
  66                return;
  67        }
  68
  69        input_report_key(wl_input_dev, KEY_RFKILL, 1);
  70        input_sync(wl_input_dev);
  71        input_report_key(wl_input_dev, KEY_RFKILL, 0);
  72        input_sync(wl_input_dev);
  73}
  74
  75static int wl_add(struct acpi_device *device)
  76{
  77        int err;
  78
  79        err = wireless_input_setup();
  80        if (err)
  81                pr_err("Failed to setup wireless hotkeys\n");
  82
  83        return err;
  84}
  85
  86static int wl_remove(struct acpi_device *device)
  87{
  88        wireless_input_destroy();
  89        return 0;
  90}
  91
  92static struct acpi_driver wl_driver = {
  93        .name   = "wireless-hotkey",
  94        .owner  = THIS_MODULE,
  95        .ids    = wl_ids,
  96        .ops    = {
  97                .add    = wl_add,
  98                .remove = wl_remove,
  99                .notify = wl_notify,
 100        },
 101};
 102
 103module_acpi_driver(wl_driver);
 104