123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * adv_swbutton.c - Software Button Interface Driver.
- *
- * (C) Copyright 2020 Advantech Corporation, Inc
- *
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/input.h>
- #include <linux/acpi.h>
- #include <linux/platform_device.h>
- #define ACPI_BUTTON_HID_SWBTN "AHC0310"
- #define ACPI_BUTTON_NOTIFY_SWBTN_RELEASE 0x86
- #define ACPI_BUTTON_NOTIFY_SWBTN_PRESSED 0x85
- struct adv_swbutton {
- struct input_dev *input;
- char phys[32];
- };
- /*-------------------------------------------------------------------------
- * Driver Interface
- *--------------------------------------------------------------------------
- */
- static void adv_swbutton_notify(acpi_handle handle, u32 event, void *context)
- {
- struct platform_device *device = context;
- struct adv_swbutton *button = dev_get_drvdata(&device->dev);
- switch (event) {
- case ACPI_BUTTON_NOTIFY_SWBTN_RELEASE:
- input_report_key(button->input, KEY_PROG1, 0);
- input_sync(button->input);
- break;
- case ACPI_BUTTON_NOTIFY_SWBTN_PRESSED:
- input_report_key(button->input, KEY_PROG1, 1);
- input_sync(button->input);
- break;
- default:
- dev_dbg(&device->dev, "Unsupported event [0x%x]\n", event);
- }
- }
- static int adv_swbutton_probe(struct platform_device *device)
- {
- struct adv_swbutton *button;
- struct input_dev *input;
- acpi_handle handle = ACPI_HANDLE(&device->dev);
- acpi_status status;
- int error;
- button = devm_kzalloc(&device->dev, sizeof(*button), GFP_KERNEL);
- if (!button)
- return -ENOMEM;
- dev_set_drvdata(&device->dev, button);
- input = devm_input_allocate_device(&device->dev);
- if (!input)
- return -ENOMEM;
- button->input = input;
- snprintf(button->phys, sizeof(button->phys), "%s/button/input0", ACPI_BUTTON_HID_SWBTN);
- input->name = "Advantech Software Button";
- input->phys = button->phys;
- input->id.bustype = BUS_HOST;
- input->dev.parent = &device->dev;
- set_bit(EV_REP, input->evbit);
- input_set_capability(input, EV_KEY, KEY_PROG1);
- error = input_register_device(input);
- if (error)
- return error;
- device_init_wakeup(&device->dev, true);
- status = acpi_install_notify_handler(handle,
- ACPI_DEVICE_NOTIFY,
- adv_swbutton_notify,
- device);
- if (ACPI_FAILURE(status)) {
- dev_err(&device->dev, "Error installing notify handler\n");
- return -EIO;
- }
- return 0;
- }
- static int adv_swbutton_remove(struct platform_device *device)
- {
- acpi_handle handle = ACPI_HANDLE(&device->dev);
- acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY,
- adv_swbutton_notify);
- return 0;
- }
- static const struct acpi_device_id button_device_ids[] = {
- {ACPI_BUTTON_HID_SWBTN, 0},
- {"", 0},
- };
- MODULE_DEVICE_TABLE(acpi, button_device_ids);
- static struct platform_driver adv_swbutton_driver = {
- .driver = {
- .name = "adv_swbutton",
- .acpi_match_table = button_device_ids,
- },
- .probe = adv_swbutton_probe,
- .remove = adv_swbutton_remove,
- };
- module_platform_driver(adv_swbutton_driver);
- MODULE_AUTHOR("Andrea Ho");
- MODULE_DESCRIPTION("Advantech ACPI SW Button Driver");
- MODULE_LICENSE("GPL v2");
|