* [V1,1/1] Input/misc: add support for Advantech software defined button
@ 2020-02-27 3:15 ycho1399
2020-02-27 5:37 ` [V1, 1/1] " kbuild test robot
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: ycho1399 @ 2020-02-27 3:15 UTC (permalink / raw)
To: linux-input
Cc: voyandrea, andrea.ho, oakley.ding, Andrea.Ho, Dmitry Torokhov,
Mauro Carvalho Chehab, David S. Miller, Rob Herring,
Greg Kroah-Hartman, Jonathan Cameron, Luca Weiss, Maximilian Luz,
Lee Jones, Bartosz Golaszewski, Thomas Gleixner, Pavel Machek,
linux-kernel
From: "Andrea.Ho" <Andrea.Ho@advantech.com.tw>
Advantech sw_button is a ACPI event trigger button.
With this driver, we can report KEY_EVENTs on the
Advantech Tabletop Network Appliances products and it has been
tested in FWA1112VC.
Add the software define button support to report KEY_EVENTs by
different acts of pressing button (like double-click, long pressed
and tick) that cloud be get on user interface and trigger the
customized actions.
Signed-off-by: Andrea.Ho <Andrea.Ho@advantech.com.tw>
---
...define.patch.EXPERIMENTAL-checkpatch-fixes | 554 ++++++++++++++++++
MAINTAINERS | 5 +
drivers/input/misc/Kconfig | 11 +
drivers/input/misc/Makefile | 2 +-
drivers/input/misc/adv_swbutton.c | 473 +++++++++++++++
5 files changed, 1044 insertions(+), 1 deletion(-)
create mode 100644 0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
create mode 100644 drivers/input/misc/adv_swbutton.c
diff --git a/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes b/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
new file mode 100644
index 000000000000..45e49aee5b47
--- /dev/null
+++ b/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
@@ -0,0 +1,553 @@
+From b5375ec981bf5b434731ac59fa1471dce79cce26 Mon Sep 17 00:00:00 2001
+From: "Andrea.Ho" <Andrea.Ho@advantech.com.tw>
+Date: Tue, 25 Feb 2020 03:52:38 +0000
+Subject: [V1,1/1] Input/misc: add support for Advantech software defined
+ button
+
+Advantech sw_button is a ACPI event trigger button.
+
+With this driver, we can report KEY_EVENTs on the
+Advantech Tabletop Network Appliances products and it has been
+tested in FWA1112VC.
+
+Add the software define button support to report KEY_EVENTs by
+different acts of pressing button (like double-click, long pressed
+and tick) that cloud be get on user interface and trigger the
+customized actions.
+
+Signed-off-by: Andrea.Ho <Andrea.Ho@advantech.com.tw>
+---
+ MAINTAINERS | 5 +
+ drivers/input/misc/Kconfig | 11 +
+ drivers/input/misc/Makefile | 2 +-
+ drivers/input/misc/adv_swbutton.c | 473 ++++++++++++++++++++++++++++++
+ 4 files changed, 490 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/input/misc/adv_swbutton.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 8982c6e013b3..d68db02fa280 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -543,6 +543,11 @@ S: Maintained
+ F: Documentation/scsi/advansys.txt
+ F: drivers/scsi/advansys.c
+
++ADVANTECH SWBTN DRIVER
++M: Andrea Ho <Andrea.Ho@advantech.com.tw>
++S: Maintained
++F: drivers/input/misc/adv_swbutton.c
++
+ ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
+ M: Michael Hennerich <michael.hennerich@analog.com>
+ W: http://wiki.analog.com/ADXL345
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index 7e2e658d551c..3c9350bdd7ae 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -879,4 +879,15 @@ config INPUT_STPMIC1_ONKEY
+ To compile this driver as a module, choose M here: the
+ module will be called stpmic1_onkey.
+
++config INPUT_ADV_SWBUTTON
++ tristate "Advantech ACPI Software button Driver"
++ depends on X86 && ACPI
++ help
++ Say Y here to enable support for Advantech software defined
++ button feature. More information can be fount at
++ <http://www.advantech.com.tw/products/>
++
++ To compile this driver as a module, choose M here. The module will
++ be called adv_swbutton.
++
+ endif
+diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
+index 8fd187f314bd..a5ceb98f18f6 100644
+--- a/drivers/input/misc/Makefile
++++ b/drivers/input/misc/Makefile
+@@ -85,4 +85,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
+ obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
+ obj-$(CONFIG_INPUT_YEALINK) += yealink.o
+ obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
+-
++obj-$(CONFIG_INPUT_ADV_SWBUTTON) += adv_swbutton.o
+diff --git a/drivers/input/misc/adv_swbutton.c b/drivers/input/misc/adv_swbutton.c
+new file mode 100644
+index 000000000000..7e4db67780dc
+--- /dev/null
++++ b/drivers/input/misc/adv_swbutton.c
+@@ -0,0 +1,473 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * adv_swbutton.c - Software Button Interface Driver.
++ *
++ * (C) Copyright 2020 Advantech Corporation, Inc
++ *
++ * Based on soc_button_array.c:
++ *
++ * {C} Copyright 2014 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/input.h>
++#include <linux/slab.h>
++#include <linux/acpi.h>
++#include <linux/ktime.h>
++#include <linux/moduleparam.h>
++#include <acpi/button.h>
++#include <acpi/acpi_bus.h>
++#include <acpi/acpi_drivers.h>
++
++#define PREFIX "[AHC] ACPI: "
++#define DRIVER_VERSION "v1.0.0"
++
++#define ACPI_BUTTON_CLASS "button"
++#define ACPI_BUTTON_FILE_INFO "info"
++#define ACPI_BUTTON_FILE_STATE "state"
++#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
++
++#define ACPI_BUTTON_SUBCLASS_SOFTWARE "software"
++#define ACPI_BUTTON_HID_SWBTN "AHC0310"
++#define ACPI_BUTTON_DEVICE_NAME_SOFTWARE "Software Button"
++#define ACPI_BUTTON_TYPE_SOFTWARE 0x07
++
++#define ACPI_BUTTON_NOTIFY_SWBTN_RELEASE 0x86
++#define ACPI_BUTTON_NOTIFY_SWBTN_PRESSED 0x85
++
++#define SWBTN_DOUBLE_TRIGGER_DELAY 130
++#define SWBTN_TRIGGER_DELAY 350
++#define SWBTN_MAX_PKEYS 8
++#define SWBTN_DEF_PKEYS 2
++
++#define _COMPONENT ACPI_BUTTON_COMPONENT
++
++ACPI_MODULE_NAME("swbutton");
++
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_AUTHOR("Andrea Ho");
++MODULE_DESCRIPTION("Advantech ACPI SW Button Driver");
++MODULE_LICENSE("GPL");
++
++/* Defined keycodes */
++static short swbtn_keycodes[] = {
++ BTN_TRIGGER_HAPPY2, /* double click */
++ BTN_TRIGGER_HAPPY, /* tick */
++ BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* long press */
++ BTN_TRIGGER_HAPPY5, BTN_TRIGGER_HAPPY6, BTN_TRIGGER_HAPPY7,
++ BTN_TRIGGER_HAPPY8, BTN_TRIGGER_HAPPY9, BTN_TRIGGER_HAPPY10
++};
++
++struct swbtn_config {
++ bool dclick_enabled;
++ int lkey_number;
++ unsigned int pressed_interval[SWBTN_MAX_PKEYS];
++ unsigned int tolerance;
++ bool open_interval;
++};
++
++static struct swbtn_config swbtn_cfg = {
++ .dclick_enabled = true,
++ .lkey_number = SWBTN_DEF_PKEYS,
++ .pressed_interval = {3000, 8000},
++ .tolerance = 800,
++ .open_interval = true
++};
++
++module_param_array_named(press_interval, swbtn_cfg.pressed_interval, uint,
++ &swbtn_cfg.lkey_number, 0444);
++MODULE_PARM_DESC(press_interval,
++ "A list of long press interval in ms. If no need, fill 0.");
++
++module_param_named(tolerance, swbtn_cfg.tolerance, uint, 0444);
++MODULE_PARM_DESC(tolerance,
++ "The torlerance of press interval in ms. Default is 800ms.");
++
++module_param_named(open_interval, swbtn_cfg.open_interval, bool, 0444);
++MODULE_PARM_DESC(open_interval,
++ "To let the last interval is the open interval.");
++
++module_param_named(enable_dclick, swbtn_cfg.dclick_enabled, bool, 0444);
++MODULE_PARM_DESC(enable_dclick,
++ "To enable/disable double click event. Default is enabled.");
++
++static const struct acpi_device_id button_device_ids[] = {
++ {ACPI_BUTTON_HID_SWBTN, 0},
++ {"", 0},
++};
++MODULE_DEVICE_TABLE(acpi, button_device_ids);
++
++static int acpi_button_add(struct acpi_device *device);
++static int acpi_button_remove(struct acpi_device *device);
++static void acpi_button_notify(struct acpi_device *device, u32 event);
++
++static struct acpi_driver acpi_button_driver = {
++ .name = ACPI_BUTTON_DEVICE_NAME_SOFTWARE,
++ .class = ACPI_BUTTON_CLASS,
++ .owner = THIS_MODULE,
++ .ids = button_device_ids,
++ .ops = {
++ .add = acpi_button_add,
++ .remove = acpi_button_remove,
++ .notify = acpi_button_notify,
++ },
++};
++
++struct acpi_button {
++ unsigned int type;
++ struct input_dev *input;
++ char phys[32]; /* for input device */
++ unsigned long pushed;
++ int last_state;
++ ktime_t last_time;
++ bool doubleclick;
++
++ /* defined timer_list struct */
++ struct timer_list swbtn_trigger_timer;
++};
++
++/*
++ * trigger software button event while timeout
++ *
++ */
++static void swbtn_trigger(struct timer_list *tdata)
++{
++ struct acpi_button *btn = from_timer(btn, tdata, swbtn_trigger_timer);
++
++ struct input_dev *input;
++ int keycode;
++
++ input = btn->input;
++
++ keycode = btn->last_state;
++ input_report_key(input, keycode, 1);
++ input_sync(input);
++
++ input_report_key(input, keycode, 0);
++ input_sync(input);
++}
++
++/*
++ * Switch two elements in array.
++ *
++ * @param xp, yp The array elements need to swap.
++ */
++void array_swap(unsigned int *xp, unsigned int *yp)
++{
++ int temp = *xp;
++ *xp = *yp;
++ *yp = temp;
++}
++
++/*
++ * Sorting an array in ascending order
++ *
++ * @param arr The array for sorting.
++ * @param n The array size
++ */
++void sort_asc(unsigned int arr[], int n)
++{
++ int i, j, min_idx;
++
++ for (i = 0; i < n - 1; i++) {
++ min_idx = i;
++ for (j = i + 1; j < n; j++)
++ if (arr[j] < arr[min_idx])
++ min_idx = j;
++
++ array_swap(&arr[min_idx], &arr[i]);
++ }
++}
++
++/*
++ * initial software button timer to check tick or double click
++ *
++ * @param btn Struct of acpi_button that should be required.
++ */
++static void swbtn_init_timer(struct acpi_button *btn)
++{
++ pr_info(PREFIX "swbtn timer start\n");
++
++ timer_setup(&btn->swbtn_trigger_timer, swbtn_trigger, 0);
++
++ btn->swbtn_trigger_timer.expires =
++ jiffies + SWBTN_DOUBLE_TRIGGER_DELAY;
++ add_timer(&btn->swbtn_trigger_timer);
++}
++
++/*-------------------------------------------------------------------------
++ * Driver Interface
++ *--------------------------------------------------------------------------
++ */
++static void acpi_button_notify(struct acpi_device *device, u32 event)
++{
++ struct acpi_button *button = acpi_driver_data(device);
++ struct input_dev *input;
++
++ int i, keycode, BTN_KEYCODE, lkey_number = swbtn_cfg.lkey_number;
++ ktime_t calltime, delta, lasttime, l_time;
++ unsigned long long duration;
++
++ pr_debug(PREFIX "%s, event:0x%x\n", __func__, event);
++
++ switch (event) {
++ case ACPI_BUTTON_NOTIFY_SWBTN_RELEASE:
++ del_timer(&button->swbtn_trigger_timer);
++
++ if (button->last_state != KEY_DOWN)
++ return;
++
++ input = button->input;
++
++ calltime = ktime_get();
++ lasttime = button->last_time;
++ button->last_time = calltime;
++
++ if (ktime_to_ns(lasttime) == 0)
++ lasttime = calltime;
++
++ delta = ktime_sub(calltime, lasttime); //ns
++ duration = (unsigned long long)
++ (ktime_to_ns(delta) >> 10) >> 10; //ms
++ pr_debug(PREFIX "duration time %llu ms\n", duration);
++
++ BTN_KEYCODE = BTN_TRIGGER_HAPPY;
++ if (button->doubleclick && duration < SWBTN_TRIGGER_DELAY) {
++ pr_debug(PREFIX "double click %llu s\n",
++ duration >> 10);
++
++ BTN_KEYCODE = BTN_TRIGGER_HAPPY2;
++ } else if (duration >= 0 && duration < SWBTN_TRIGGER_DELAY) {
++ pr_debug(PREFIX "click %llu s\n", duration >> 10);
++
++ button->last_state = BTN_TRIGGER_HAPPY;
++ swbtn_init_timer(button);
++ } else {
++ for (i = 0; i < lkey_number; i++) {
++ unsigned int p_intval =
++ swbtn_cfg.pressed_interval[i];
++ unsigned int diff = swbtn_cfg.tolerance;
++ int j = i + 1;
++
++ if (p_intval < diff ||
++ p_intval < SWBTN_TRIGGER_DELAY)
++ break;
++ if ((j) < lkey_number) {
++ unsigned int n_intval =
++ swbtn_cfg.pressed_interval[j];
++
++ if ((p_intval + diff) >
++ (n_intval - diff))
++ diff = (n_intval
++ - p_intval) / 2;
++ }
++
++ pr_debug(PREFIX "pressed_interval: %lu ms\n",
++ p_intval);
++
++ if ((swbtn_cfg.open_interval &&
++ j == lkey_number &&
++ duration > (p_intval - diff)) ||
++ (duration > (p_intval - diff) &&
++ duration < (p_intval + diff))) {
++ pr_debug(PREFIX "long pressed %llu s\n",
++ duration >> 10);
++
++ BTN_KEYCODE = swbtn_keycodes[i + 2];
++ break;
++ }
++ }
++ }
++
++ if (!button->doubleclick &&
++ (duration >= 0 &&
++ duration < SWBTN_TRIGGER_DELAY))
++ return;
++
++ keycode = test_bit(BTN_KEYCODE, input->keybit) ?
++ BTN_KEYCODE : KEY_UNKNOWN;
++ pr_debug(PREFIX "released keycode: 0x%x", keycode);
++
++ button->last_state = keycode;
++ button->doubleclick = false;
++
++ input_report_key(input, keycode, 1);
++ input_sync(input);
++
++ input_report_key(input, keycode, 0);
++ input_sync(input);
++
++ break;
++ case ACPI_BUTTON_NOTIFY_SWBTN_PRESSED:
++ l_time = ktime_to_ns(button->last_time);
++
++ input = button->input;
++
++ calltime = ktime_get();
++ lasttime = l_time == 0 ? calltime : button->last_time;
++
++ delta = ktime_sub(calltime, lasttime); //ns
++ duration = (unsigned long long)
++ (ktime_to_ns(delta) >> 10) >> 10; //ms
++
++ button->doubleclick = (button->last_state ==
++ BTN_TRIGGER_HAPPY &&
++ duration > 0 &&
++ duration < SWBTN_DOUBLE_TRIGGER_DELAY);
++
++ button->last_time = calltime;
++ button->last_state = KEY_DOWN;
++
++ pr_debug(PREFIX "pressed software button, duration %llu ms",
++ duration);
++ pr_debug(PREFIX " is double click: %s\n",
++ (button->doubleclick) ? "true" : "false");
++
++ break;
++ default:
++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
++ "Unsupported event [0x%x]\n", event));
++ break;
++ }
++}
++
++static int __init acpi_button_init(void)
++{
++ int result;
++
++ pr_info(PREFIX "acpi button init!");
++
++ result = acpi_bus_register_driver(&acpi_button_driver);
++ if (result < 0) {
++ pr_err(PREFIX "register acpi button driver failed");
++ return -ENODEV;
++ }
++ return 0;
++}
++
++static void __exit acpi_button_exit(void)
++{
++ pr_info(PREFIX "%s\n", __func__);
++ acpi_bus_unregister_driver(&acpi_button_driver);
++}
++
++static int acpi_button_add(struct acpi_device *device)
++{
++ struct acpi_button *button;
++ struct input_dev *input;
++ const char *hid = acpi_device_hid(device);
++ char *name, *class;
++ int error, i;
++
++ pr_info(PREFIX "%s\n", __func__);
++ button = kzalloc(sizeof(*button), GFP_KERNEL);
++ if (!button) {
++ pr_err(PREFIX "alloc acpi_button failed\n");
++ return -ENOMEM;
++ }
++
++ device->driver_data = button;
++
++ button->input = input_allocate_device();
++ input = button->input;
++ if (!input) {
++ error = -ENOMEM;
++ pr_err(PREFIX "allocat input device failed!\n");
++ goto err_free_button;
++ }
++
++ name = acpi_device_name(device);
++ class = acpi_device_class(device);
++
++ pr_info(PREFIX "device name[%s]\n", name);
++
++ if (!strcmp(hid, ACPI_BUTTON_HID_SWBTN)) {
++ button->type = ACPI_BUTTON_TYPE_SOFTWARE;
++ button->last_time = ktime_set(0, 0);
++ button->last_state = KEY_UNKNOWN;
++ strcpy(name, ACPI_BUTTON_DEVICE_NAME_SOFTWARE);
++ sprintf(class, "%s/%s", ACPI_BUTTON_CLASS,
++ ACPI_BUTTON_SUBCLASS_SOFTWARE);
++ } else {
++ pr_err(PREFIX "Unsupported hid [%s]\n", hid);
++ error = -ENODEV;
++ goto err_free_input;
++ }
++
++ snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
++
++ input->name = name;
++ input->phys = button->phys;
++ input->id.bustype = BUS_HOST;
++ input->id.product = button->type;
++ input->dev.parent = &device->dev;
++
++ pr_info(PREFIX "ACPI_BUTTON_TYPE_SOFTWARE: [0x%x]",
++ ACPI_BUTTON_TYPE_SOFTWARE);
++
++ switch (button->type) {
++ case ACPI_BUTTON_TYPE_SOFTWARE:
++ set_bit(EV_KEY, input->evbit);
++ set_bit(EV_REP, input->evbit);
++
++ if (swbtn_cfg.lkey_number == 1 &&
++ swbtn_cfg.pressed_interval[0] == 0)
++ swbtn_cfg.lkey_number = 0;
++
++ for (i = (!swbtn_cfg.dclick_enabled);
++ i < (swbtn_cfg.lkey_number + 2); i++) {
++ pr_info(PREFIX "%d. Enabled keycode[0x%x]\n",
++ i, swbtn_keycodes[i]);
++ input_set_capability(input, EV_KEY, swbtn_keycodes[i]);
++ }
++ break;
++ }
++
++ sort_asc(swbtn_cfg.pressed_interval, swbtn_cfg.lkey_number);
++
++ input_set_drvdata(input, device);
++ error = input_register_device(input);
++ if (error)
++ goto err_free_input;
++
++ device_init_wakeup(&device->dev, true);
++
++ pr_info(PREFIX "%s [%s]\n", name, acpi_device_bid(device));
++ return 0;
++
++err_free_input:
++ input_free_device(input);
++err_free_button:
++ kfree(button);
++ return error;
++}
++
++static int acpi_button_remove(struct acpi_device *device)
++{
++ struct acpi_button *button = acpi_driver_data(device);
++
++ pr_info(PREFIX "acpi_button_remove");
++
++ input_unregister_device(button->input);
++ kfree(button);
++ return 0;
++}
++
++module_init(acpi_button_init);
++module_exit(acpi_button_exit);
+--
+2.17.1
diff --git a/MAINTAINERS b/MAINTAINERS
index 8982c6e013b3..821c5cacf553 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -543,6 +543,11 @@ S: Maintained
F: Documentation/scsi/advansys.txt
F: drivers/scsi/advansys.c
+ADVANTECH SWBTN DRIVER
+M: Andrea Ho <Andrea.Ho@advantech.com.tw>
+S: Maintained
+F: drivers/input/misc/adv_swbutton.c
+
ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
M: Michael Hennerich <michael.hennerich@analog.com>
W: http://wiki.analog.com/ADXL345
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7e2e658d551c..3c9350bdd7ae 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -879,4 +879,15 @@ config INPUT_STPMIC1_ONKEY
To compile this driver as a module, choose M here: the
module will be called stpmic1_onkey.
+config INPUT_ADV_SWBUTTON
+ tristate "Advantech ACPI Software button Driver"
+ depends on X86 && ACPI
+ help
+ Say Y here to enable support for Advantech software defined
+ button feature. More information can be fount at
+ <http://www.advantech.com.tw/products/>
+
+ To compile this driver as a module, choose M here. The module will
+ be called adv_swbutton.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 8fd187f314bd..a5ceb98f18f6 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -85,4 +85,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
-
+obj-$(CONFIG_INPUT_ADV_SWBUTTON) += adv_swbutton.o
diff --git a/drivers/input/misc/adv_swbutton.c b/drivers/input/misc/adv_swbutton.c
new file mode 100644
index 000000000000..7e4db67780dc
--- /dev/null
+++ b/drivers/input/misc/adv_swbutton.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * adv_swbutton.c - Software Button Interface Driver.
+ *
+ * (C) Copyright 2020 Advantech Corporation, Inc
+ *
+ * Based on soc_button_array.c:
+ *
+ * {C} Copyright 2014 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/ktime.h>
+#include <linux/moduleparam.h>
+#include <acpi/button.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define PREFIX "[AHC] ACPI: "
+#define DRIVER_VERSION "v1.0.0"
+
+#define ACPI_BUTTON_CLASS "button"
+#define ACPI_BUTTON_FILE_INFO "info"
+#define ACPI_BUTTON_FILE_STATE "state"
+#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
+
+#define ACPI_BUTTON_SUBCLASS_SOFTWARE "software"
+#define ACPI_BUTTON_HID_SWBTN "AHC0310"
+#define ACPI_BUTTON_DEVICE_NAME_SOFTWARE "Software Button"
+#define ACPI_BUTTON_TYPE_SOFTWARE 0x07
+
+#define ACPI_BUTTON_NOTIFY_SWBTN_RELEASE 0x86
+#define ACPI_BUTTON_NOTIFY_SWBTN_PRESSED 0x85
+
+#define SWBTN_DOUBLE_TRIGGER_DELAY 130
+#define SWBTN_TRIGGER_DELAY 350
+#define SWBTN_MAX_PKEYS 8
+#define SWBTN_DEF_PKEYS 2
+
+#define _COMPONENT ACPI_BUTTON_COMPONENT
+
+ACPI_MODULE_NAME("swbutton");
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Andrea Ho");
+MODULE_DESCRIPTION("Advantech ACPI SW Button Driver");
+MODULE_LICENSE("GPL");
+
+/* Defined keycodes */
+static short swbtn_keycodes[] = {
+ BTN_TRIGGER_HAPPY2, /* double click */
+ BTN_TRIGGER_HAPPY, /* tick */
+ BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4, /* long press */
+ BTN_TRIGGER_HAPPY5, BTN_TRIGGER_HAPPY6, BTN_TRIGGER_HAPPY7,
+ BTN_TRIGGER_HAPPY8, BTN_TRIGGER_HAPPY9, BTN_TRIGGER_HAPPY10
+};
+
+struct swbtn_config {
+ bool dclick_enabled;
+ int lkey_number;
+ unsigned int pressed_interval[SWBTN_MAX_PKEYS];
+ unsigned int tolerance;
+ bool open_interval;
+};
+
+static struct swbtn_config swbtn_cfg = {
+ .dclick_enabled = true,
+ .lkey_number = SWBTN_DEF_PKEYS,
+ .pressed_interval = {3000, 8000},
+ .tolerance = 800,
+ .open_interval = true
+};
+
+module_param_array_named(press_interval, swbtn_cfg.pressed_interval, uint,
+ &swbtn_cfg.lkey_number, 0444);
+MODULE_PARM_DESC(press_interval,
+ "A list of long press interval in ms. If no need, fill 0.");
+
+module_param_named(tolerance, swbtn_cfg.tolerance, uint, 0444);
+MODULE_PARM_DESC(tolerance,
+ "The torlerance of press interval in ms. Default is 800ms.");
+
+module_param_named(open_interval, swbtn_cfg.open_interval, bool, 0444);
+MODULE_PARM_DESC(open_interval,
+ "To let the last interval is the open interval.");
+
+module_param_named(enable_dclick, swbtn_cfg.dclick_enabled, bool, 0444);
+MODULE_PARM_DESC(enable_dclick,
+ "To enable/disable double click event. Default is enabled.");
+
+static const struct acpi_device_id button_device_ids[] = {
+ {ACPI_BUTTON_HID_SWBTN, 0},
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, button_device_ids);
+
+static int acpi_button_add(struct acpi_device *device);
+static int acpi_button_remove(struct acpi_device *device);
+static void acpi_button_notify(struct acpi_device *device, u32 event);
+
+static struct acpi_driver acpi_button_driver = {
+ .name = ACPI_BUTTON_DEVICE_NAME_SOFTWARE,
+ .class = ACPI_BUTTON_CLASS,
+ .owner = THIS_MODULE,
+ .ids = button_device_ids,
+ .ops = {
+ .add = acpi_button_add,
+ .remove = acpi_button_remove,
+ .notify = acpi_button_notify,
+ },
+};
+
+struct acpi_button {
+ unsigned int type;
+ struct input_dev *input;
+ char phys[32]; /* for input device */
+ unsigned long pushed;
+ int last_state;
+ ktime_t last_time;
+ bool doubleclick;
+
+ /* defined timer_list struct */
+ struct timer_list swbtn_trigger_timer;
+};
+
+/*
+ * trigger software button event while timeout
+ *
+ */
+static void swbtn_trigger(struct timer_list *tdata)
+{
+ struct acpi_button *btn = from_timer(btn, tdata, swbtn_trigger_timer);
+
+ struct input_dev *input;
+ int keycode;
+
+ input = btn->input;
+
+ keycode = btn->last_state;
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+
+ input_report_key(input, keycode, 0);
+ input_sync(input);
+}
+
+/*
+ * Switch two elements in array.
+ *
+ * @param xp, yp The array elements need to swap.
+ */
+void array_swap(unsigned int *xp, unsigned int *yp)
+{
+ int temp = *xp;
+ *xp = *yp;
+ *yp = temp;
+}
+
+/*
+ * Sorting an array in ascending order
+ *
+ * @param arr The array for sorting.
+ * @param n The array size
+ */
+void sort_asc(unsigned int arr[], int n)
+{
+ int i, j, min_idx;
+
+ for (i = 0; i < n - 1; i++) {
+ min_idx = i;
+ for (j = i + 1; j < n; j++)
+ if (arr[j] < arr[min_idx])
+ min_idx = j;
+
+ array_swap(&arr[min_idx], &arr[i]);
+ }
+}
+
+/*
+ * initial software button timer to check tick or double click
+ *
+ * @param btn Struct of acpi_button that should be required.
+ */
+static void swbtn_init_timer(struct acpi_button *btn)
+{
+ pr_info(PREFIX "swbtn timer start\n");
+
+ timer_setup(&btn->swbtn_trigger_timer, swbtn_trigger, 0);
+
+ btn->swbtn_trigger_timer.expires =
+ jiffies + SWBTN_DOUBLE_TRIGGER_DELAY;
+ add_timer(&btn->swbtn_trigger_timer);
+}
+
+/*-------------------------------------------------------------------------
+ * Driver Interface
+ *--------------------------------------------------------------------------
+ */
+static void acpi_button_notify(struct acpi_device *device, u32 event)
+{
+ struct acpi_button *button = acpi_driver_data(device);
+ struct input_dev *input;
+
+ int i, keycode, BTN_KEYCODE, lkey_number = swbtn_cfg.lkey_number;
+ ktime_t calltime, delta, lasttime, l_time;
+ unsigned long long duration;
+
+ pr_debug(PREFIX "%s, event:0x%x\n", __func__, event);
+
+ switch (event) {
+ case ACPI_BUTTON_NOTIFY_SWBTN_RELEASE:
+ del_timer(&button->swbtn_trigger_timer);
+
+ if (button->last_state != KEY_DOWN)
+ return;
+
+ input = button->input;
+
+ calltime = ktime_get();
+ lasttime = button->last_time;
+ button->last_time = calltime;
+
+ if (ktime_to_ns(lasttime) == 0)
+ lasttime = calltime;
+
+ delta = ktime_sub(calltime, lasttime); //ns
+ duration = (unsigned long long)
+ (ktime_to_ns(delta) >> 10) >> 10; //ms
+ pr_debug(PREFIX "duration time %llu ms\n", duration);
+
+ BTN_KEYCODE = BTN_TRIGGER_HAPPY;
+ if (button->doubleclick && duration < SWBTN_TRIGGER_DELAY) {
+ pr_debug(PREFIX "double click %llu s\n",
+ duration >> 10);
+
+ BTN_KEYCODE = BTN_TRIGGER_HAPPY2;
+ } else if (duration >= 0 && duration < SWBTN_TRIGGER_DELAY) {
+ pr_debug(PREFIX "click %llu s\n", duration >> 10);
+
+ button->last_state = BTN_TRIGGER_HAPPY;
+ swbtn_init_timer(button);
+ } else {
+ for (i = 0; i < lkey_number; i++) {
+ unsigned int p_intval =
+ swbtn_cfg.pressed_interval[i];
+ unsigned int diff = swbtn_cfg.tolerance;
+ int j = i + 1;
+
+ if (p_intval < diff ||
+ p_intval < SWBTN_TRIGGER_DELAY)
+ break;
+ if ((j) < lkey_number) {
+ unsigned int n_intval =
+ swbtn_cfg.pressed_interval[j];
+
+ if ((p_intval + diff) >
+ (n_intval - diff))
+ diff = (n_intval
+ - p_intval) / 2;
+ }
+
+ pr_debug(PREFIX "pressed_interval: %lu ms\n",
+ p_intval);
+
+ if ((swbtn_cfg.open_interval &&
+ j == lkey_number &&
+ duration > (p_intval - diff)) ||
+ (duration > (p_intval - diff) &&
+ duration < (p_intval + diff))) {
+ pr_debug(PREFIX "long pressed %llu s\n",
+ duration >> 10);
+
+ BTN_KEYCODE = swbtn_keycodes[i + 2];
+ break;
+ }
+ }
+ }
+
+ if (!button->doubleclick &&
+ (duration >= 0 &&
+ duration < SWBTN_TRIGGER_DELAY))
+ return;
+
+ keycode = test_bit(BTN_KEYCODE, input->keybit) ?
+ BTN_KEYCODE : KEY_UNKNOWN;
+ pr_debug(PREFIX "released keycode: 0x%x", keycode);
+
+ button->last_state = keycode;
+ button->doubleclick = false;
+
+ input_report_key(input, keycode, 1);
+ input_sync(input);
+
+ input_report_key(input, keycode, 0);
+ input_sync(input);
+
+ break;
+ case ACPI_BUTTON_NOTIFY_SWBTN_PRESSED:
+ l_time = ktime_to_ns(button->last_time);
+
+ input = button->input;
+
+ calltime = ktime_get();
+ lasttime = l_time == 0 ? calltime : button->last_time;
+
+ delta = ktime_sub(calltime, lasttime); //ns
+ duration = (unsigned long long)
+ (ktime_to_ns(delta) >> 10) >> 10; //ms
+
+ button->doubleclick = (button->last_state ==
+ BTN_TRIGGER_HAPPY &&
+ duration > 0 &&
+ duration < SWBTN_DOUBLE_TRIGGER_DELAY);
+
+ button->last_time = calltime;
+ button->last_state = KEY_DOWN;
+
+ pr_debug(PREFIX "pressed software button, duration %llu ms",
+ duration);
+ pr_debug(PREFIX " is double click: %s\n",
+ (button->doubleclick) ? "true" : "false");
+
+ break;
+ default:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Unsupported event [0x%x]\n", event));
+ break;
+ }
+}
+
+static int __init acpi_button_init(void)
+{
+ int result;
+
+ pr_info(PREFIX "acpi button init!");
+
+ result = acpi_bus_register_driver(&acpi_button_driver);
+ if (result < 0) {
+ pr_err(PREFIX "register acpi button driver failed");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit acpi_button_exit(void)
+{
+ pr_info(PREFIX "%s\n", __func__);
+ acpi_bus_unregister_driver(&acpi_button_driver);
+}
+
+static int acpi_button_add(struct acpi_device *device)
+{
+ struct acpi_button *button;
+ struct input_dev *input;
+ const char *hid = acpi_device_hid(device);
+ char *name, *class;
+ int error, i;
+
+ pr_info(PREFIX "%s\n", __func__);
+ button = kzalloc(sizeof(*button), GFP_KERNEL);
+ if (!button) {
+ pr_err(PREFIX "alloc acpi_button failed\n");
+ return -ENOMEM;
+ }
+
+ device->driver_data = button;
+
+ button->input = input_allocate_device();
+ input = button->input;
+ if (!input) {
+ error = -ENOMEM;
+ pr_err(PREFIX "allocat input device failed!\n");
+ goto err_free_button;
+ }
+
+ name = acpi_device_name(device);
+ class = acpi_device_class(device);
+
+ pr_info(PREFIX "device name[%s]\n", name);
+
+ if (!strcmp(hid, ACPI_BUTTON_HID_SWBTN)) {
+ button->type = ACPI_BUTTON_TYPE_SOFTWARE;
+ button->last_time = ktime_set(0, 0);
+ button->last_state = KEY_UNKNOWN;
+ strcpy(name, ACPI_BUTTON_DEVICE_NAME_SOFTWARE);
+ sprintf(class, "%s/%s", ACPI_BUTTON_CLASS,
+ ACPI_BUTTON_SUBCLASS_SOFTWARE);
+ } else {
+ pr_err(PREFIX "Unsupported hid [%s]\n", hid);
+ error = -ENODEV;
+ goto err_free_input;
+ }
+
+ snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
+
+ input->name = name;
+ input->phys = button->phys;
+ input->id.bustype = BUS_HOST;
+ input->id.product = button->type;
+ input->dev.parent = &device->dev;
+
+ pr_info(PREFIX "ACPI_BUTTON_TYPE_SOFTWARE: [0x%x]",
+ ACPI_BUTTON_TYPE_SOFTWARE);
+
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_SOFTWARE:
+ set_bit(EV_KEY, input->evbit);
+ set_bit(EV_REP, input->evbit);
+
+ if (swbtn_cfg.lkey_number == 1 &&
+ swbtn_cfg.pressed_interval[0] == 0)
+ swbtn_cfg.lkey_number = 0;
+
+ for (i = (!swbtn_cfg.dclick_enabled);
+ i < (swbtn_cfg.lkey_number + 2); i++) {
+ pr_info(PREFIX "%d. Enabled keycode[0x%x]\n",
+ i, swbtn_keycodes[i]);
+ input_set_capability(input, EV_KEY, swbtn_keycodes[i]);
+ }
+ break;
+ }
+
+ sort_asc(swbtn_cfg.pressed_interval, swbtn_cfg.lkey_number);
+
+ input_set_drvdata(input, device);
+ error = input_register_device(input);
+ if (error)
+ goto err_free_input;
+
+ device_init_wakeup(&device->dev, true);
+
+ pr_info(PREFIX "%s [%s]\n", name, acpi_device_bid(device));
+ return 0;
+
+err_free_input:
+ input_free_device(input);
+err_free_button:
+ kfree(button);
+ return error;
+}
+
+static int acpi_button_remove(struct acpi_device *device)
+{
+ struct acpi_button *button = acpi_driver_data(device);
+
+ pr_info(PREFIX "acpi_button_remove");
+
+ input_unregister_device(button->input);
+ kfree(button);
+ return 0;
+}
+
+module_init(acpi_button_init);
+module_exit(acpi_button_exit);
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [V1, 1/1] Input/misc: add support for Advantech software defined button
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
@ 2020-02-27 5:37 ` kbuild test robot
2020-02-27 7:06 ` kbuild test robot
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2020-02-27 5:37 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 7139 bytes --]
Hi,
I love your patch! Perhaps something to improve:
[auto build test WARNING on input/next]
[also build test WARNING on linus/master v5.6-rc3 next-20200226]
[cannot apply to sparc-next/master]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/ycho1399-gmail-com/Input-misc-add-support-for-Advantech-software-defined-button/20200227-112039
base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
config: i386-allyesconfig (attached as .config)
compiler: gcc-7 (Debian 7.5.0-5) 7.5.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:15:0,
from drivers/input/misc/adv_swbutton.c:22:
drivers/input/misc/adv_swbutton.c: In function 'acpi_button_notify':
include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'unsigned int' [-Wformat=]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^
include/linux/printk.h:137:10: note: in definition of macro 'no_printk'
printk(fmt, ##__VA_ARGS__); \
^~~
include/linux/kern_levels.h:15:20: note: in expansion of macro 'KERN_SOH'
#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
^~~~~~~~
include/linux/printk.h:341:12: note: in expansion of macro 'KERN_DEBUG'
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
^~~~~~~~~~
>> drivers/input/misc/adv_swbutton.c:281:5: note: in expansion of macro 'pr_debug'
pr_debug(PREFIX "pressed_interval: %lu ms\n",
^~~~~~~~
drivers/input/misc/adv_swbutton.c:281:42: note: format string is defined here
pr_debug(PREFIX "pressed_interval: %lu ms\n",
~~^
%u
vim +/pr_debug +281 drivers/input/misc/adv_swbutton.c
213
214 /*-------------------------------------------------------------------------
215 * Driver Interface
216 *--------------------------------------------------------------------------
217 */
218 static void acpi_button_notify(struct acpi_device *device, u32 event)
219 {
220 struct acpi_button *button = acpi_driver_data(device);
221 struct input_dev *input;
222
223 int i, keycode, BTN_KEYCODE, lkey_number = swbtn_cfg.lkey_number;
224 ktime_t calltime, delta, lasttime, l_time;
225 unsigned long long duration;
226
227 pr_debug(PREFIX "%s, event:0x%x\n", __func__, event);
228
229 switch (event) {
230 case ACPI_BUTTON_NOTIFY_SWBTN_RELEASE:
231 del_timer(&button->swbtn_trigger_timer);
232
233 if (button->last_state != KEY_DOWN)
234 return;
235
236 input = button->input;
237
238 calltime = ktime_get();
239 lasttime = button->last_time;
240 button->last_time = calltime;
241
242 if (ktime_to_ns(lasttime) == 0)
243 lasttime = calltime;
244
245 delta = ktime_sub(calltime, lasttime); //ns
246 duration = (unsigned long long)
247 (ktime_to_ns(delta) >> 10) >> 10; //ms
248 pr_debug(PREFIX "duration time %llu ms\n", duration);
249
250 BTN_KEYCODE = BTN_TRIGGER_HAPPY;
251 if (button->doubleclick && duration < SWBTN_TRIGGER_DELAY) {
252 pr_debug(PREFIX "double click %llu s\n",
253 duration >> 10);
254
255 BTN_KEYCODE = BTN_TRIGGER_HAPPY2;
256 } else if (duration >= 0 && duration < SWBTN_TRIGGER_DELAY) {
257 pr_debug(PREFIX "click %llu s\n", duration >> 10);
258
259 button->last_state = BTN_TRIGGER_HAPPY;
260 swbtn_init_timer(button);
261 } else {
262 for (i = 0; i < lkey_number; i++) {
263 unsigned int p_intval =
264 swbtn_cfg.pressed_interval[i];
265 unsigned int diff = swbtn_cfg.tolerance;
266 int j = i + 1;
267
268 if (p_intval < diff ||
269 p_intval < SWBTN_TRIGGER_DELAY)
270 break;
271 if ((j) < lkey_number) {
272 unsigned int n_intval =
273 swbtn_cfg.pressed_interval[j];
274
275 if ((p_intval + diff) >
276 (n_intval - diff))
277 diff = (n_intval
278 - p_intval) / 2;
279 }
280
> 281 pr_debug(PREFIX "pressed_interval: %lu ms\n",
282 p_intval);
283
284 if ((swbtn_cfg.open_interval &&
285 j == lkey_number &&
286 duration > (p_intval - diff)) ||
287 (duration > (p_intval - diff) &&
288 duration < (p_intval + diff))) {
289 pr_debug(PREFIX "long pressed %llu s\n",
290 duration >> 10);
291
292 BTN_KEYCODE = swbtn_keycodes[i + 2];
293 break;
294 }
295 }
296 }
297
298 if (!button->doubleclick &&
299 (duration >= 0 &&
300 duration < SWBTN_TRIGGER_DELAY))
301 return;
302
303 keycode = test_bit(BTN_KEYCODE, input->keybit) ?
304 BTN_KEYCODE : KEY_UNKNOWN;
305 pr_debug(PREFIX "released keycode: 0x%x", keycode);
306
307 button->last_state = keycode;
308 button->doubleclick = false;
309
310 input_report_key(input, keycode, 1);
311 input_sync(input);
312
313 input_report_key(input, keycode, 0);
314 input_sync(input);
315
316 break;
317 case ACPI_BUTTON_NOTIFY_SWBTN_PRESSED:
318 l_time = ktime_to_ns(button->last_time);
319
320 input = button->input;
321
322 calltime = ktime_get();
323 lasttime = l_time == 0 ? calltime : button->last_time;
324
325 delta = ktime_sub(calltime, lasttime); //ns
326 duration = (unsigned long long)
327 (ktime_to_ns(delta) >> 10) >> 10; //ms
328
329 button->doubleclick = (button->last_state ==
330 BTN_TRIGGER_HAPPY &&
331 duration > 0 &&
332 duration < SWBTN_DOUBLE_TRIGGER_DELAY);
333
334 button->last_time = calltime;
335 button->last_state = KEY_DOWN;
336
337 pr_debug(PREFIX "pressed software button, duration %llu ms",
338 duration);
339 pr_debug(PREFIX " is double click: %s\n",
340 (button->doubleclick) ? "true" : "false");
341
342 break;
343 default:
344 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
345 "Unsupported event [0x%x]\n", event));
346 break;
347 }
348 }
349
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 70258 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [V1, 1/1] Input/misc: add support for Advantech software defined button
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
2020-02-27 5:37 ` [V1, 1/1] " kbuild test robot
@ 2020-02-27 7:06 ` kbuild test robot
2020-02-27 7:22 ` [V1,1/1] " Greg Kroah-Hartman
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2020-02-27 7:06 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 2822 bytes --]
Hi,
I love your patch! Perhaps something to improve:
[auto build test WARNING on input/next]
[also build test WARNING on linus/master v5.6-rc3 next-20200226]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/ycho1399-gmail-com/Input-misc-add-support-for-Advantech-software-defined-button/20200227-112039
base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
config: i386-allyesconfig (attached as .config)
compiler: gcc-7 (Debian 7.5.0-5) 7.5.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
In file included from include/linux/kernel.h:15:0,
from drivers/input/misc/adv_swbutton.c:22:
drivers/input/misc/adv_swbutton.c: In function 'acpi_button_notify':
>> drivers/input/misc/adv_swbutton.c:38:16: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int' [-Wformat=]
#define PREFIX "[AHC] ACPI: "
^
include/linux/printk.h:288:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
include/linux/dynamic_debug.h:143:2: note: in expansion of macro '__dynamic_func_call'
__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
^~~~~~~~~~~~~~~~~~~
include/linux/dynamic_debug.h:153:2: note: in expansion of macro '_dynamic_func_call'
_dynamic_func_call(fmt, __dynamic_pr_debug, \
^~~~~~~~~~~~~~~~~~
include/linux/printk.h:335:2: note: in expansion of macro 'dynamic_pr_debug'
dynamic_pr_debug(fmt, ##__VA_ARGS__)
^~~~~~~~~~~~~~~~
drivers/input/misc/adv_swbutton.c:281:5: note: in expansion of macro 'pr_debug'
pr_debug(PREFIX "pressed_interval: %lu ms\n",
^~~~~~~~
>> drivers/input/misc/adv_swbutton.c:281:14: note: in expansion of macro 'PREFIX'
pr_debug(PREFIX "pressed_interval: %lu ms\n",
^~~~~~
drivers/input/misc/adv_swbutton.c:281:42: note: format string is defined here
pr_debug(PREFIX "pressed_interval: %lu ms\n",
~~^
%u
vim +38 drivers/input/misc/adv_swbutton.c
37
> 38 #define PREFIX "[AHC] ACPI: "
39 #define DRIVER_VERSION "v1.0.0"
40
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 70255 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [V1,1/1] Input/misc: add support for Advantech software defined button
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
2020-02-27 5:37 ` [V1, 1/1] " kbuild test robot
2020-02-27 7:06 ` kbuild test robot
@ 2020-02-27 7:22 ` Greg Kroah-Hartman
2020-02-27 8:11 ` Joe Perches
2020-02-27 8:56 ` Pavel Machek
4 siblings, 0 replies; 6+ messages in thread
From: Greg Kroah-Hartman @ 2020-02-27 7:22 UTC (permalink / raw)
To: ycho1399
Cc: linux-input, voyandrea, andrea.ho, oakley.ding, Dmitry Torokhov,
Mauro Carvalho Chehab, David S. Miller, Rob Herring,
Jonathan Cameron, Luca Weiss, Maximilian Luz, Lee Jones,
Bartosz Golaszewski, Thomas Gleixner, Pavel Machek, linux-kernel
On Thu, Feb 27, 2020 at 03:15:31AM +0000, ycho1399@gmail.com wrote:
> From: "Andrea.Ho" <Andrea.Ho@advantech.com.tw>
>
> Advantech sw_button is a ACPI event trigger button.
>
> With this driver, we can report KEY_EVENTs on the
> Advantech Tabletop Network Appliances products and it has been
> tested in FWA1112VC.
>
> Add the software define button support to report KEY_EVENTs by
> different acts of pressing button (like double-click, long pressed
> and tick) that cloud be get on user interface and trigger the
> customized actions.
>
> Signed-off-by: Andrea.Ho <Andrea.Ho@advantech.com.tw>
> ---
> ...define.patch.EXPERIMENTAL-checkpatch-fixes | 554 ++++++++++++++++++
> MAINTAINERS | 5 +
> drivers/input/misc/Kconfig | 11 +
> drivers/input/misc/Makefile | 2 +-
> drivers/input/misc/adv_swbutton.c | 473 +++++++++++++++
> 5 files changed, 1044 insertions(+), 1 deletion(-)
> create mode 100644 0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
> create mode 100644 drivers/input/misc/adv_swbutton.c
>
> diff --git a/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes b/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
> new file mode 100644
> index 000000000000..45e49aee5b47
> --- /dev/null
> +++ b/0001-Input-misc-add-support-for-Advantech-software-define.patch.EXPERIMENTAL-checkpatch-fixes
<snip>
I doubt you ment to commit the patch itself into the patch :(
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [V1,1/1] Input/misc: add support for Advantech software defined button
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
` (2 preceding siblings ...)
2020-02-27 7:22 ` [V1,1/1] " Greg Kroah-Hartman
@ 2020-02-27 8:11 ` Joe Perches
2020-02-27 8:56 ` Pavel Machek
4 siblings, 0 replies; 6+ messages in thread
From: Joe Perches @ 2020-02-27 8:11 UTC (permalink / raw)
To: ycho1399, linux-input
Cc: voyandrea, andrea.ho, oakley.ding, Dmitry Torokhov,
Mauro Carvalho Chehab, David S. Miller, Rob Herring,
Greg Kroah-Hartman, Jonathan Cameron, Luca Weiss, Maximilian Luz,
Lee Jones, Bartosz Golaszewski, Thomas Gleixner, Pavel Machek,
linux-kernel
On Thu, 2020-02-27 at 03:15 +0000, ycho1399@gmail.com wrote:
> From: "Andrea.Ho" <Andrea.Ho@advantech.com.tw>
>
> Advantech sw_button is a ACPI event trigger button.
>
> With this driver, we can report KEY_EVENTs on the
> Advantech Tabletop Network Appliances products and it has been
> tested in FWA1112VC.
>
> Add the software define button support to report KEY_EVENTs by
> different acts of pressing button (like double-click, long pressed
> and tick) that cloud be get on user interface and trigger the
> customized actions.
[]
> diff --git a/drivers/input/misc/adv_swbutton.c b/drivers/input/misc/adv_swbutton.c
> new file mode 100644
mostly trivia:
> +/*
> + * Switch two elements in array.
> + *
> + * @param xp, yp The array elements need to swap.
> + */
> +void array_swap(unsigned int *xp, unsigned int *yp)
> +{
> + int temp = *xp;
> + *xp = *yp;
> + *yp = temp;
> +}
kernel.h has swap
> +/*
> + * Sorting an array in ascending order
> + *
> + * @param arr The array for sorting.
> + * @param n The array size
> + */
> +void sort_asc(unsigned int arr[], int n)
> +{
> + int i, j, min_idx;
> +
> + for (i = 0; i < n - 1; i++) {
> + min_idx = i;
> + for (j = i + 1; j < n; j++)
> + if (arr[j] < arr[min_idx])
> + min_idx = j;
> +
> + array_swap(&arr[min_idx], &arr[i]);
> + }
> +}
sort.h has a generic sort too
> +
> +/*
> + * initial software button timer to check tick or double click
> + *
> + * @param btn Struct of acpi_button that should be required.
> + */
> +static void swbtn_init_timer(struct acpi_button *btn)
> +{
> + pr_info(PREFIX "swbtn timer start\n");
Many of these printks should be removed and ftrace used
when necessary.
> +static int acpi_button_add(struct acpi_device *device)
> +{
> + struct acpi_button *button;
> + struct input_dev *input;
> + const char *hid = acpi_device_hid(device);
> + char *name, *class;
> + int error, i;
> +
> + pr_info(PREFIX "%s\n", __func__);
> + button = kzalloc(sizeof(*button), GFP_KERNEL);
> + if (!button) {
> + pr_err(PREFIX "alloc acpi_button failed\n");
alloc failure messages aren't really necessary
as a dump_stack() is already done on failure.
[]
> + for (i = (!swbtn_cfg.dclick_enabled);
> + i < (swbtn_cfg.lkey_number + 2); i++) {
> + pr_info(PREFIX "%d. Enabled keycode[0x%x]\n",
> + i, swbtn_keycodes[i]);
Is it really useful to print all enabled keycodes?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [V1,1/1] Input/misc: add support for Advantech software defined button
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
` (3 preceding siblings ...)
2020-02-27 8:11 ` Joe Perches
@ 2020-02-27 8:56 ` Pavel Machek
4 siblings, 0 replies; 6+ messages in thread
From: Pavel Machek @ 2020-02-27 8:56 UTC (permalink / raw)
To: ycho1399
Cc: linux-input, voyandrea, andrea.ho, oakley.ding, Dmitry Torokhov,
Mauro Carvalho Chehab, David S. Miller, Rob Herring,
Greg Kroah-Hartman, Jonathan Cameron, Luca Weiss, Maximilian Luz,
Lee Jones, Bartosz Golaszewski, Thomas Gleixner, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 943 bytes --]
On Thu 2020-02-27 03:15:31, ycho1399@gmail.com wrote:
> From: "Andrea.Ho" <Andrea.Ho@advantech.com.tw>
>
> Advantech sw_button is a ACPI event trigger button.
>
> With this driver, we can report KEY_EVENTs on the
> Advantech Tabletop Network Appliances products and it has been
> tested in FWA1112VC.
>
> Add the software define button support to report KEY_EVENTs by
> different acts of pressing button (like double-click, long pressed
> and tick) that cloud be get on user interface and trigger the
> customized actions.
I'm not sure why you Cc half of the world. What does Dave Miller have
to do with this. Please be more careful (and drop me from the list).
Plus, I'm pretty sure you should not be detecting double clicks (etc)
in the driver.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-02-27 8:56 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-27 3:15 [V1,1/1] Input/misc: add support for Advantech software defined button ycho1399
2020-02-27 5:37 ` [V1, 1/1] " kbuild test robot
2020-02-27 7:06 ` kbuild test robot
2020-02-27 7:22 ` [V1,1/1] " Greg Kroah-Hartman
2020-02-27 8:11 ` Joe Perches
2020-02-27 8:56 ` Pavel Machek
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.