All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.