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