// SPDX-License-Identifier: GPL-2.0-or-later /* * Airplane mode button for AMD, HP & Xiaomi laptops * * Copyright (C) 2014-2017 Alex Hung * Copyright (C) 2021 Advanced Micro Devices */ #include #include #include #include #include #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Hung"); MODULE_ALIAS("acpi*:HPQ6001:*"); MODULE_ALIAS("acpi*:WSTADEF:*"); MODULE_ALIAS("acpi*:AMDI0051:*"); static struct input_dev *wl_input_dev; static const struct acpi_device_id wl_ids[] = { {"HPQ6001", 0}, {"WSTADEF", 0}, {"AMDI0051", 0}, {"", 0}, }; static int wireless_input_setup(void) { int err; wl_input_dev = input_allocate_device(); if (!wl_input_dev) return -ENOMEM; wl_input_dev->name = "Wireless hotkeys"; wl_input_dev->phys = "hpq6001/input0"; wl_input_dev->id.bustype = BUS_HOST; wl_input_dev->evbit[0] = BIT(EV_KEY); set_bit(KEY_RFKILL, wl_input_dev->keybit); err = input_register_device(wl_input_dev); if (err) goto err_free_dev; return 0; err_free_dev: input_free_device(wl_input_dev); return err; } static void wireless_input_destroy(void) { input_unregister_device(wl_input_dev); } static void wl_notify(struct acpi_device *acpi_dev, u32 event) { if (event != 0x80) { pr_info("Received unknown event (0x%x)\n", event); return; } input_report_key(wl_input_dev, KEY_RFKILL, 1); input_sync(wl_input_dev); input_report_key(wl_input_dev, KEY_RFKILL, 0); input_sync(wl_input_dev); } static int wl_add(struct acpi_device *device) { int err; err = wireless_input_setup(); if (err) pr_err("Failed to setup wireless hotkeys\n"); return err; } static int wl_remove(struct acpi_device *device) { wireless_input_destroy(); return 0; } static struct acpi_driver wl_driver = { .name = "wireless-hotkey", .owner = THIS_MODULE, .ids = wl_ids, .ops = { .add = wl_add, .remove = wl_remove, .notify = wl_notify, }, }; module_acpi_driver(wl_driver);