linux/drivers/platform/x86/adv_swbutton.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  adv_swbutton.c - Software Button Interface Driver.
   4 *
   5 *  (C) Copyright 2020 Advantech Corporation, Inc
   6 *
   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    0x86
  17#define ACPI_BUTTON_NOTIFY_SWBTN_PRESSED    0x85
  18
  19struct adv_swbutton {
  20        struct input_dev *input;
  21        char phys[32];
  22};
  23
  24/*-------------------------------------------------------------------------
  25 *                               Driver Interface
  26 *--------------------------------------------------------------------------
  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 int 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        return 0;
 101}
 102
 103static const struct acpi_device_id button_device_ids[] = {
 104        {ACPI_BUTTON_HID_SWBTN, 0},
 105        {"", 0},
 106};
 107MODULE_DEVICE_TABLE(acpi, button_device_ids);
 108
 109static struct platform_driver adv_swbutton_driver = {
 110        .driver = {
 111                .name = "adv_swbutton",
 112                .acpi_match_table = button_device_ids,
 113        },
 114        .probe = adv_swbutton_probe,
 115        .remove = adv_swbutton_remove,
 116};
 117module_platform_driver(adv_swbutton_driver);
 118
 119MODULE_AUTHOR("Andrea Ho");
 120MODULE_DESCRIPTION("Advantech ACPI SW Button Driver");
 121MODULE_LICENSE("GPL v2");
 122