// SPDX-License-Identifier: GPL-2.0-or-later #include #include #include #include MODULE_AUTHOR("Josh Triplett"); MODULE_DESCRIPTION("ACPI Tiny Power Button Driver"); MODULE_LICENSE("GPL"); static int power_signal __read_mostly = CONFIG_ACPI_TINY_POWER_BUTTON_SIGNAL; module_param(power_signal, int, 0644); MODULE_PARM_DESC(power_signal, "Power button sends this signal to init"); static const struct acpi_device_id tiny_power_button_device_ids[] = { { ACPI_BUTTON_HID_POWER, 0 }, { ACPI_BUTTON_HID_POWERF, 0 }, { "", 0 }, }; MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids); static void acpi_tiny_power_button_notify(acpi_handle handle, u32 event, void *data) { kill_cad_pid(power_signal, 1); } static void acpi_tiny_power_button_notify_run(void *not_used) { acpi_tiny_power_button_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, NULL); } static u32 acpi_tiny_power_button_event(void *not_used) { acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_tiny_power_button_notify_run, NULL); return ACPI_INTERRUPT_HANDLED; } static int acpi_tiny_power_button_add(struct acpi_device *device) { acpi_status status; if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_tiny_power_button_event, NULL); } else { status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_tiny_power_button_notify, NULL); } if (ACPI_FAILURE(status)) return -ENODEV; return 0; } static void acpi_tiny_power_button_remove(struct acpi_device *device) { if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) { acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, acpi_tiny_power_button_event); } else { acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_tiny_power_button_notify); } acpi_os_wait_events_complete(); } static struct acpi_driver acpi_tiny_power_button_driver = { .name = "tiny-power-button", .class = "tiny-power-button", .ids = tiny_power_button_device_ids, .ops = { .add = acpi_tiny_power_button_add, .remove = acpi_tiny_power_button_remove, }, }; module_acpi_driver(acpi_tiny_power_button_driver);