120 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * adv_swbutton.c - Software Button Interface Driver.4 *5 * (C) Copyright 2020 Advantech Corporation, Inc6 *7 */8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/input.h>11#include <linux/acpi.h>12#include <linux/platform_device.h>13 14#define ACPI_BUTTON_HID_SWBTN "AHC0310"15 16#define ACPI_BUTTON_NOTIFY_SWBTN_RELEASE 0x8617#define ACPI_BUTTON_NOTIFY_SWBTN_PRESSED 0x8518 19struct adv_swbutton {20 struct input_dev *input;21 char phys[32];22};23 24/*-------------------------------------------------------------------------25 * Driver Interface26 *--------------------------------------------------------------------------27 */28static void adv_swbutton_notify(acpi_handle handle, u32 event, void *context)29{30 struct platform_device *device = context;31 struct adv_swbutton *button = dev_get_drvdata(&device->dev);32 33 switch (event) {34 case ACPI_BUTTON_NOTIFY_SWBTN_RELEASE:35 input_report_key(button->input, KEY_PROG1, 0);36 input_sync(button->input);37 break;38 case ACPI_BUTTON_NOTIFY_SWBTN_PRESSED:39 input_report_key(button->input, KEY_PROG1, 1);40 input_sync(button->input);41 break;42 default:43 dev_dbg(&device->dev, "Unsupported event [0x%x]\n", event);44 }45}46 47static int adv_swbutton_probe(struct platform_device *device)48{49 struct adv_swbutton *button;50 struct input_dev *input;51 acpi_handle handle = ACPI_HANDLE(&device->dev);52 acpi_status status;53 int error;54 55 button = devm_kzalloc(&device->dev, sizeof(*button), GFP_KERNEL);56 if (!button)57 return -ENOMEM;58 59 dev_set_drvdata(&device->dev, button);60 61 input = devm_input_allocate_device(&device->dev);62 if (!input)63 return -ENOMEM;64 65 button->input = input;66 snprintf(button->phys, sizeof(button->phys), "%s/button/input0", ACPI_BUTTON_HID_SWBTN);67 68 input->name = "Advantech Software Button";69 input->phys = button->phys;70 input->id.bustype = BUS_HOST;71 input->dev.parent = &device->dev;72 set_bit(EV_REP, input->evbit);73 input_set_capability(input, EV_KEY, KEY_PROG1);74 75 error = input_register_device(input);76 if (error)77 return error;78 79 device_init_wakeup(&device->dev, true);80 81 status = acpi_install_notify_handler(handle,82 ACPI_DEVICE_NOTIFY,83 adv_swbutton_notify,84 device);85 if (ACPI_FAILURE(status)) {86 dev_err(&device->dev, "Error installing notify handler\n");87 return -EIO;88 }89 90 return 0;91}92 93static void adv_swbutton_remove(struct platform_device *device)94{95 acpi_handle handle = ACPI_HANDLE(&device->dev);96 97 acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY,98 adv_swbutton_notify);99}100 101static const struct acpi_device_id button_device_ids[] = {102 {ACPI_BUTTON_HID_SWBTN, 0},103 {"", 0},104};105MODULE_DEVICE_TABLE(acpi, button_device_ids);106 107static struct platform_driver adv_swbutton_driver = {108 .driver = {109 .name = "adv_swbutton",110 .acpi_match_table = button_device_ids,111 },112 .probe = adv_swbutton_probe,113 .remove_new = adv_swbutton_remove,114};115module_platform_driver(adv_swbutton_driver);116 117MODULE_AUTHOR("Andrea Ho");118MODULE_DESCRIPTION("Advantech ACPI SW Button Driver");119MODULE_LICENSE("GPL v2");120