* [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen
@ 2020-10-30 9:05 Carl Philipp Klemm
2020-10-31 7:15 ` Tony Lindgren
2020-11-03 9:20 ` kernel test robot
0 siblings, 2 replies; 4+ messages in thread
From: Carl Philipp Klemm @ 2020-10-30 9:05 UTC (permalink / raw)
To: Dmitry Torokhov, tony; +Cc: linux-omap, linux-input
Adds a driver for supporting permanet, physically labeled, buttons on
touchscreen surfaces. As are common on android phones designed with android 1.0
to 2.3 in mind. The driver works by attaching to another input device and
creating key events on its device when a press is registerd on a button.
It also provides a mirrored touchscreen device with the same events as the
attached device, but with the touchches that land on buttons filterd away
Buttons are arbitrary rectangles configurable via dts.
Signed-off-by: Carl Philipp Klemm <carl@uvos.xyz>
---
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 362e8a01980c..3d487b8e7d8b 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -318,6 +318,14 @@ config INPUT_CPCAP_PWRBUTTON
To compile this driver as a module, choose M here. The module will
be called cpcap-pwrbutton.
+config INPUT_TOUCHSCREEN_BUTTONS
+ tristate "Touchscreen Buttons"
+ help
+ Say Y here if you want to enable buttons on touchscreen devices.
+
+ To compile this driver as a module, choose M here. The module will
+ be called touchscreen-buttons.
+
config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
depends on X86_32
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a48e5f2d859d..18032a1b2a9c 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -84,4 +84,5 @@ 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_TOUCHSCREEN_BUTTONS) += touchscreen-buttons.o
diff --git a/drivers/input/misc/touchscreen-buttons.c b/drivers/input/misc/touchscreen-buttons.c
new file mode 100644
index 000000000000..3b1b630b4e66
--- /dev/null
+++ b/drivers/input/misc/touchscreen-buttons.c
@@ -0,0 +1,593 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/**
+ * Touchscreen Virutal Button Input Driver
+ *
+ * Copyright (C) 2020 Carl Klemm <carl@uvos.xyz>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * 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/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/input/mt.h>
+#include <linux/device/bus.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+#define EVENT_QUEUE_SIZE 32
+
+struct touchscreen_button {
+ u32 x;
+ u32 y;
+ u32 width;
+ u32 height;
+ u32 keycode;
+ u8 depressed;
+};
+
+struct touchscreen_button_map {
+ struct touchscreen_button *buttons;
+ u32 count;
+ struct device_node *ts_node;
+};
+
+struct event {
+ unsigned int type;
+ unsigned int code;
+ int value;
+};
+
+struct event_queue {
+ struct event events[EVENT_QUEUE_SIZE];
+ unsigned int lastindex;
+};
+
+struct touchscreen_buttons {
+ struct device *dev;
+ struct input_dev *buttons_idev;
+ struct input_dev *filtered_ts_idev;
+ struct touchscreen_button_map *map;
+ struct input_handler *handler;
+ struct input_handle *ts_handle;
+ struct event_queue queue;
+ struct workqueue_struct *workqueue;
+ struct work_struct open_task;
+ struct work_struct close_task;
+ struct work_struct merge_task;
+ struct mutex mutex;
+};
+
+static const struct input_device_id touchscreen_buttons_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = {BIT_MASK(EV_ABS)},
+ },
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = {BIT_MASK(EV_KEY)},
+ },
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = {BIT_MASK(EV_SYN)},
+ },
+ {},
+};
+
+static int touchscreen_buttons_process_syn(const struct event_queue *queue,
+ const struct touchscreen_button_map
+ *map, struct input_dev *idev)
+{
+ u32 i;
+ int x, y, ret, pressed;
+
+ x = INT_MIN;
+ y = INT_MIN;
+ pressed = -1;
+ ret = 0;
+
+ for (i = 0; i < queue->lastindex; ++i) {
+ const struct event *ev;
+
+ ev = &queue->events[i];
+ if (ev->type == EV_ABS && ev->code == ABS_X)
+ x = ev->value;
+ else if (ev->type == EV_ABS && ev->code == ABS_Y)
+ y = ev->value;
+ else if (ev->type == EV_KEY && ev->code == BTN_TOUCH)
+ pressed = ev->value;
+ }
+
+ for (i = 0; i < map->count; ++i) {
+ struct touchscreen_button *button = &map->buttons[i];
+
+ if (pressed == 1 &&
+ button->x <= x &&
+ button->y <= y &&
+ button->width + button->x >= x &&
+ button->height + button->y >= y && button->depressed == 0) {
+ input_report_key(idev, button->keycode, 1);
+ button->depressed = 1;
+ ret = 1;
+ } else if (button->depressed == 1) {
+ if (pressed == 0) {
+ input_report_key(idev, button->keycode, 0);
+ button->depressed = 0;
+ }
+ ret = 2;
+ }
+ }
+
+ if (ret != 0) {
+ input_event(idev, EV_SYN, SYN_REPORT, 0);
+ } else if (ret == 0) {
+ bool buttonpressed = false;
+
+ for (i = 0; i < map->count; ++i)
+ buttonpressed = buttonpressed
+ || map->buttons[i].depressed;
+ if (buttonpressed)
+ ret = 3;
+ }
+
+ return ret;
+}
+
+static void touchscreen_buttons_resend_events(const struct event_queue *queue,
+ struct input_dev *idev)
+{
+ u32 i;
+
+ for (i = 0; i < queue->lastindex; ++i)
+ input_event(idev, queue->events[i].type, queue->events[i].code,
+ queue->events[i].value);
+ input_event(idev, EV_SYN, SYN_REPORT, 0);
+}
+
+static void touchscreen_buttons_copy_mt_slots(struct input_dev *target,
+ struct input_dev *source)
+{
+ if (source->mt && target->mt
+ && source->mt->num_slots == target->mt->num_slots) {
+ memcpy(target->mt->slots, source->mt->slots,
+ sizeof(struct input_mt_slot) * source->mt->num_slots);
+ }
+}
+
+static void touchscreen_buttons_input_event(struct input_handle *handle,
+ unsigned int type,
+ unsigned int code, int value)
+{
+ struct touchscreen_buttons *buttons;
+
+ buttons = handle->private;
+
+ if (type == EV_SYN && code == SYN_REPORT) {
+ if (touchscreen_buttons_process_syn(&buttons->queue,
+ buttons->map,
+ buttons->buttons_idev) == 0)
+ touchscreen_buttons_resend_events(&buttons->queue,
+ buttons->filtered_ts_idev);
+ buttons->queue.lastindex = 0;
+ } else if (buttons->queue.lastindex < EVENT_QUEUE_SIZE
+ && buttons->queue.lastindex >= 0) {
+ buttons->queue.events[buttons->queue.lastindex].type = type;
+ buttons->queue.events[buttons->queue.lastindex].code = code;
+ buttons->queue.events[buttons->queue.lastindex].value = value;
+ ++buttons->queue.lastindex;
+ } else {
+ dev_warn(buttons->dev,
+ "event_qeue overrun, will not capture events until next SYN_REPORT\n");
+ }
+}
+
+static void touchscreen_buttons_merge_capabilitys(struct input_dev *target,
+ struct input_dev *source)
+{
+ unsigned int i;
+
+ mutex_lock(&target->mutex);
+ mutex_lock(&source->mutex);
+ for (i = 0; i < BITS_TO_LONGS(INPUT_PROP_CNT); ++i)
+ target->propbit[i] = target->propbit[i] | source->propbit[i];
+ for (i = 0; i < BITS_TO_LONGS(EV_CNT); ++i)
+ target->evbit[i] = target->evbit[i] | source->evbit[i];
+ for (i = 0; i < BITS_TO_LONGS(KEY_CNT); ++i)
+ target->keybit[i] = target->keybit[i] | source->keybit[i];
+ for (i = 0; i < BITS_TO_LONGS(REL_CNT); ++i)
+ target->relbit[i] = target->relbit[i] | source->relbit[i];
+ for (i = 0; i < BITS_TO_LONGS(ABS_CNT); ++i)
+ target->absbit[i] = target->absbit[i] | source->absbit[i];
+ for (i = 0; i < BITS_TO_LONGS(MSC_CNT); ++i)
+ target->mscbit[i] = target->mscbit[i] | source->mscbit[i];
+ for (i = 0; i < BITS_TO_LONGS(LED_CNT); ++i)
+ target->ledbit[i] = target->ledbit[i] | source->ledbit[i];
+ for (i = 0; i < BITS_TO_LONGS(SND_CNT); ++i)
+ target->sndbit[i] = target->sndbit[i] | source->sndbit[i];
+ for (i = 0; i < BITS_TO_LONGS(FF_CNT); ++i)
+ target->ffbit[i] = target->ffbit[i] | source->ffbit[i];
+ for (i = 0; i < BITS_TO_LONGS(SW_CNT); ++i)
+ target->swbit[i] = target->swbit[i] | source->swbit[i];
+
+ if (*source->evbit & (1 << EV_ABS)) {
+ input_alloc_absinfo(target);
+ for (i = 0; i < ABS_CNT; ++i)
+ target->absinfo[i] = source->absinfo[i];
+ if (source->mt) {
+ input_mt_init_slots(target, source->mt->num_slots,
+ source->mt->flags);
+ touchscreen_buttons_copy_mt_slots(target, source);
+ }
+ }
+ mutex_unlock(&source->mutex);
+ mutex_unlock(&target->mutex);
+}
+
+void merge_task_handler(struct work_struct *work)
+{
+ struct touchscreen_buttons *buttons =
+ container_of(work, struct touchscreen_buttons, merge_task);
+
+ mutex_lock(&buttons->mutex);
+ if (buttons->ts_handle && buttons->ts_handle->dev)
+ touchscreen_buttons_merge_capabilitys(buttons->filtered_ts_idev,
+ buttons->ts_handle->dev);
+ mutex_unlock(&buttons->mutex);
+}
+
+void close_task_handler(struct work_struct *work)
+{
+ struct touchscreen_buttons *buttons =
+ container_of(work, struct touchscreen_buttons, close_task);
+
+ mutex_lock(&buttons->mutex);
+ if (buttons && buttons->ts_handle && buttons->ts_handle->open != 0)
+ input_close_device(buttons->ts_handle);
+ mutex_unlock(&buttons->mutex);
+}
+
+void open_task_handler(struct work_struct *work)
+{
+ struct touchscreen_buttons *buttons =
+ container_of(work, struct touchscreen_buttons, open_task);
+ int error;
+
+ mutex_lock(&buttons->mutex);
+ if (buttons && buttons->ts_handle) {
+ error = input_open_device(buttons->ts_handle);
+ if (error) {
+ dev_err(buttons->dev,
+ "Failed to open input device, error %d\n",
+ error);
+ input_unregister_handle(buttons->ts_handle);
+ kfree(buttons->ts_handle);
+ buttons->ts_handle = NULL;
+ }
+ }
+ mutex_unlock(&buttons->mutex);
+}
+
+static int touchscreen_buttons_input_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct touchscreen_buttons *buttons;
+
+ buttons = handler->private;
+
+ mutex_lock(&buttons->mutex);
+
+ if ((!buttons->ts_handle
+ && device_match_of_node(&dev->dev, buttons->map->ts_node))
+ || (dev->dev.parent
+ && device_match_of_node(dev->dev.parent,
+ buttons->map->ts_node))) {
+ int error;
+
+ dev_info(buttons->dev, "Binding to device: %s\n",
+ dev_name(&dev->dev));
+
+ buttons->ts_handle =
+ kzalloc(sizeof(*buttons->ts_handle), GFP_KERNEL);
+ if (!buttons->ts_handle) {
+ mutex_unlock(&buttons->mutex);
+ return -ENOMEM;
+ }
+
+ buttons->ts_handle->dev = dev;
+ buttons->ts_handle->handler = handler;
+ buttons->ts_handle->name = "touchscreen-buttons";
+ buttons->ts_handle->private = handler->private;
+ buttons->queue.lastindex = 0;
+
+ error = input_register_handle(buttons->ts_handle);
+ if (error) {
+ dev_err(buttons->dev,
+ "Failed to register input handler, error %d\n",
+ error);
+ kfree(buttons->ts_handle);
+ buttons->ts_handle = NULL;
+ mutex_unlock(&buttons->mutex);
+ return error;
+ }
+
+ queue_work(buttons->workqueue, &buttons->merge_task);
+
+ if (buttons->filtered_ts_idev->users > 0
+ && buttons->ts_handle->open == 0)
+ queue_work(buttons->workqueue, &buttons->open_task);
+ }
+
+ mutex_unlock(&buttons->mutex);
+ return 0;
+}
+
+static void touchscreen_buttons_input_disconnect(struct input_handle *handle)
+{
+ struct touchscreen_buttons *buttons;
+
+ buttons = handle->private;
+
+ mutex_lock(&buttons->mutex);
+ if (handle == buttons->ts_handle) {
+ input_close_device(handle);
+ input_unregister_handle(handle);
+ kfree(handle);
+ buttons->ts_handle = NULL;
+ dev_info(buttons->dev,
+ "Touchscreen device disconnected buttons disabled\n");
+ } else {
+ dev_err(buttons->dev,
+ "Unknown device disconnected, %p should be %p", handle,
+ buttons->ts_handle);
+ }
+ mutex_unlock(&buttons->mutex);
+}
+
+static struct touchscreen_button_map
+*touchscreen_buttons_get_devtree_pdata(struct device *dev)
+{
+ struct touchscreen_button_map *map;
+ struct fwnode_handle *child_node;
+ struct device_node *node;
+ int i;
+
+ map = kzalloc(sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return ERR_PTR(-ENOMEM);
+
+ map->count = device_get_child_node_count(dev);
+ if (map->count == 0)
+ return ERR_PTR(-ENODEV);
+
+ map->buttons = kcalloc(map->count, sizeof(*map->buttons), GFP_KERNEL);
+ if (!map->buttons)
+ return ERR_PTR(-ENOMEM);
+
+ node = dev->of_node;
+ map->ts_node = of_parse_phandle(node, "touchscreen_phandle", 0);
+ if (!map->ts_node) {
+ dev_err(dev, "touchscreen_phandle node missing\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ dev_info(dev, "Device_node name: %s\n", map->ts_node->name);
+
+ i = 0;
+ device_for_each_child_node(dev, child_node) {
+ struct touchscreen_button *button;
+
+ button = &map->buttons[i];
+
+ fwnode_property_read_u32(child_node, "x-position", &button->x);
+ fwnode_property_read_u32(child_node, "y-position", &button->y);
+ fwnode_property_read_u32(child_node, "x-size", &button->width);
+ fwnode_property_read_u32(child_node, "y-size", &button->height);
+ fwnode_property_read_u32(child_node, "keycode",
+ &button->keycode);
+ dev_info(dev,
+ "Adding button at x=%u y=%u size %u x %u keycode=%u\n",
+ button->x, button->y, button->width, button->height,
+ button->keycode);
+ ++i;
+ }
+ return map;
+}
+
+int touchscreen_buttons_idev_opened(struct input_dev *idev)
+{
+ struct touchscreen_buttons *buttons;
+
+ buttons = dev_get_drvdata(idev->dev.parent);
+
+ mutex_lock(&buttons->mutex);
+ if (buttons && buttons->ts_handle) {
+ if (buttons->ts_handle->open == 0) {
+ queue_work(buttons->workqueue, &buttons->open_task);
+ dev_dbg(idev->dev.parent, "idev opened\n");
+ } else {
+ dev_info(idev->dev.parent, "idev allready opened\n");
+ }
+ } else {
+ dev_warn(idev->dev.parent,
+ "Input device opend but touchscreen not opened. %p %p\n",
+ buttons, buttons->ts_handle);
+ }
+ mutex_unlock(&buttons->mutex);
+ return 0;
+}
+
+void touchscreen_buttons_idev_closed(struct input_dev *idev)
+{
+ struct touchscreen_buttons *buttons;
+
+ buttons = dev_get_drvdata(idev->dev.parent);
+
+ mutex_lock(&buttons->mutex);
+ if (buttons && buttons->ts_handle && buttons->ts_handle->open != 0) {
+ queue_work(buttons->workqueue, &buttons->close_task);
+ dev_dbg(idev->dev.parent, "idev closed\n");
+ }
+ mutex_unlock(&buttons->mutex);
+}
+
+static int touchscreen_buttons_probe(struct platform_device *pdev)
+{
+ struct touchscreen_buttons *buttons;
+ int error, i;
+
+ buttons = kzalloc(sizeof(*buttons), GFP_KERNEL);
+ if (!buttons)
+ return -ENOMEM;
+
+ dev_set_drvdata(&pdev->dev, buttons);
+
+ buttons->workqueue =
+ create_singlethread_workqueue("touchscreen-buttons-workqueue");
+ INIT_WORK(&buttons->merge_task, merge_task_handler);
+ INIT_WORK(&buttons->open_task, open_task_handler);
+ INIT_WORK(&buttons->close_task, close_task_handler);
+
+ mutex_init(&buttons->mutex);
+
+ buttons->queue.lastindex = 0;
+ buttons->dev = &pdev->dev;
+
+ buttons->map = touchscreen_buttons_get_devtree_pdata(&pdev->dev);
+ if (IS_ERR(buttons->map))
+ return PTR_ERR(buttons->map);
+
+ /*filtered touchscreen device */
+ buttons->filtered_ts_idev = input_allocate_device();
+ if (!buttons->filtered_ts_idev)
+ return -ENOMEM;
+ buttons->filtered_ts_idev->name = "Filtered Touchscreen";
+ buttons->filtered_ts_idev->phys = "touchscreen-buttons/input1";
+ buttons->filtered_ts_idev->dev.parent = buttons->dev;
+ buttons->filtered_ts_idev->open = touchscreen_buttons_idev_opened;
+ buttons->filtered_ts_idev->close = touchscreen_buttons_idev_closed;
+
+ /*buttons input device */
+ buttons->buttons_idev = input_allocate_device();
+ if (!buttons->buttons_idev)
+ return -ENOMEM;
+ buttons->buttons_idev->name = "Touchscreen Buttons";
+ buttons->buttons_idev->phys = "touchscreen-buttons/input0";
+ buttons->buttons_idev->dev.parent = buttons->dev;
+ for (i = 0; i < buttons->map->count; ++i)
+ input_set_capability(buttons->buttons_idev, EV_KEY,
+ buttons->map->buttons[i].keycode);
+
+ /*handler for touchscreen input device */
+ buttons->handler = kzalloc(sizeof(*buttons->handler), GFP_KERNEL);
+
+ buttons->handler->event = touchscreen_buttons_input_event;
+ buttons->handler->connect = touchscreen_buttons_input_connect;
+ buttons->handler->disconnect = touchscreen_buttons_input_disconnect;
+ buttons->handler->name = "touchscreen-buttons";
+ buttons->handler->id_table = touchscreen_buttons_ids;
+ buttons->handler->private = buttons;
+
+ error = input_register_handler(buttons->handler);
+ if (error) {
+ dev_err(&pdev->dev, "Input handler register failed: %d\n",
+ error);
+ return error;
+ }
+
+ error = input_register_device(buttons->buttons_idev);
+ if (error) {
+ dev_err(&pdev->dev, "Input device register failed: %d\n",
+ error);
+ return error;
+ }
+
+ error = input_register_device(buttons->filtered_ts_idev);
+ if (error) {
+ dev_err(&pdev->dev, "Input device register failed: %d\n",
+ error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int touchscreen_buttons_remove(struct platform_device *pdev)
+{
+ struct touchscreen_buttons *buttons;
+ struct input_handle *ts_handle;
+
+ buttons = dev_get_drvdata(&pdev->dev);
+
+ mutex_lock(&buttons->mutex);
+
+ ts_handle = buttons->ts_handle;
+
+ input_unregister_handler(buttons->handler);
+ if (buttons->ts_handle) {
+ if (buttons->ts_handle->open != 0)
+ input_close_device(buttons->ts_handle);
+ input_unregister_handle(buttons->ts_handle);
+ buttons->ts_handle = NULL;
+ }
+
+ mutex_unlock(&buttons->mutex);
+
+ flush_workqueue(buttons->workqueue);
+ destroy_workqueue(buttons->workqueue);
+
+ input_unregister_device(buttons->buttons_idev);
+ input_unregister_device(buttons->filtered_ts_idev);
+
+ kfree(ts_handle);
+
+ if (buttons->map) {
+ kfree(buttons->map->buttons);
+ kfree(buttons->map);
+ }
+ kfree(buttons->handler);
+
+ kfree(buttons);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id touchscreen_buttons_dt_match_table[] = {
+ {.compatible = "touchscreen-buttons"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, touchscreen_buttons_dt_match_table);
+#endif
+
+static struct platform_driver touchscreen_buttons_driver = {
+ .probe = touchscreen_buttons_probe,
+ .remove = touchscreen_buttons_remove,
+ .driver = {
+ .name = "touchscreen-buttons",
+ .of_match_table =
+ of_match_ptr(touchscreen_buttons_dt_match_table),
+ },
+};
+
+module_platform_driver(touchscreen_buttons_driver);
+
+MODULE_ALIAS("platform:touchscreen-buttons");
+MODULE_DESCRIPTION("touchscreen-buttons");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Carl Klemm <carl@uvos.xyz>");
--
Carl Philipp Klemm <philipp@uvos.xyz> <carl@uvos.xyz>
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen
2020-10-30 9:05 [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen Carl Philipp Klemm
@ 2020-10-31 7:15 ` Tony Lindgren
[not found] ` <20201031103722.6efbf69b084ed35d2f700fe9@uvos.xyz>
2020-11-03 9:20 ` kernel test robot
1 sibling, 1 reply; 4+ messages in thread
From: Tony Lindgren @ 2020-10-31 7:15 UTC (permalink / raw)
To: Carl Philipp Klemm; +Cc: Dmitry Torokhov, linux-omap, linux-input
Hi,
* Carl Philipp Klemm <philipp@uvos.xyz> [201030 09:06]:
> Adds a driver for supporting permanet, physically labeled, buttons on
> touchscreen surfaces. As are common on android phones designed with android 1.0
> to 2.3 in mind. The driver works by attaching to another input device and
> creating key events on its device when a press is registerd on a button.
> It also provides a mirrored touchscreen device with the same events as the
> attached device, but with the touchches that land on buttons filterd away
> Buttons are arbitrary rectangles configurable via dts.
Nice to have a generic way for the touchscreen buttons :)
Care to summarize here too what's currently blocking touchscreen buttons
driver only providing the keyboard events as a separate inputdevice
without having to mirror all the touchscreen events?
Regards,
Tony
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen
2020-10-30 9:05 [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen Carl Philipp Klemm
2020-10-31 7:15 ` Tony Lindgren
@ 2020-11-03 9:20 ` kernel test robot
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2020-11-03 9:20 UTC (permalink / raw)
To: Carl Philipp Klemm, Dmitry Torokhov, tony
Cc: kbuild-all, linux-omap, linux-input
[-- Attachment #1: Type: text/plain, Size: 10489 bytes --]
Hi Carl,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on input/next]
[also build test WARNING on omap/for-next balbi-usb/testing/next v5.10-rc2 next-20201103]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Carl-Philipp-Klemm/ARM-dts-motorola-mapphone-common-Add-dts-configureation-for-the-android-buttons-beneath-the-screen/20201030-170644
base: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
config: riscv-randconfig-r013-20201030 (attached as .config)
compiler: riscv32-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/7a00d245fade30bef33d962c11b7bc121c007910
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Carl-Philipp-Klemm/ARM-dts-motorola-mapphone-common-Add-dts-configureation-for-the-android-buttons-beneath-the-screen/20201030-170644
git checkout 7a00d245fade30bef33d962c11b7bc121c007910
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/input/misc/touchscreen-buttons.c: In function 'touchscreen_buttons_input_event':
drivers/input/misc/touchscreen-buttons.c:187:34: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
187 | && buttons->queue.lastindex >= 0) {
| ^~
drivers/input/misc/touchscreen-buttons.c: At top level:
>> drivers/input/misc/touchscreen-buttons.c:240:6: warning: no previous prototype for 'merge_task_handler' [-Wmissing-prototypes]
240 | void merge_task_handler(struct work_struct *work)
| ^~~~~~~~~~~~~~~~~~
>> drivers/input/misc/touchscreen-buttons.c:252:6: warning: no previous prototype for 'close_task_handler' [-Wmissing-prototypes]
252 | void close_task_handler(struct work_struct *work)
| ^~~~~~~~~~~~~~~~~~
>> drivers/input/misc/touchscreen-buttons.c:263:6: warning: no previous prototype for 'open_task_handler' [-Wmissing-prototypes]
263 | void open_task_handler(struct work_struct *work)
| ^~~~~~~~~~~~~~~~~
>> drivers/input/misc/touchscreen-buttons.c:411:5: warning: no previous prototype for 'touchscreen_buttons_idev_opened' [-Wmissing-prototypes]
411 | int touchscreen_buttons_idev_opened(struct input_dev *idev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/input/misc/touchscreen-buttons.c:434:6: warning: no previous prototype for 'touchscreen_buttons_idev_closed' [-Wmissing-prototypes]
434 | void touchscreen_buttons_idev_closed(struct input_dev *idev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +/merge_task_handler +240 drivers/input/misc/touchscreen-buttons.c
239
> 240 void merge_task_handler(struct work_struct *work)
241 {
242 struct touchscreen_buttons *buttons =
243 container_of(work, struct touchscreen_buttons, merge_task);
244
245 mutex_lock(&buttons->mutex);
246 if (buttons->ts_handle && buttons->ts_handle->dev)
247 touchscreen_buttons_merge_capabilitys(buttons->filtered_ts_idev,
248 buttons->ts_handle->dev);
249 mutex_unlock(&buttons->mutex);
250 }
251
> 252 void close_task_handler(struct work_struct *work)
253 {
254 struct touchscreen_buttons *buttons =
255 container_of(work, struct touchscreen_buttons, close_task);
256
257 mutex_lock(&buttons->mutex);
258 if (buttons && buttons->ts_handle && buttons->ts_handle->open != 0)
259 input_close_device(buttons->ts_handle);
260 mutex_unlock(&buttons->mutex);
261 }
262
> 263 void open_task_handler(struct work_struct *work)
264 {
265 struct touchscreen_buttons *buttons =
266 container_of(work, struct touchscreen_buttons, open_task);
267 int error;
268
269 mutex_lock(&buttons->mutex);
270 if (buttons && buttons->ts_handle) {
271 error = input_open_device(buttons->ts_handle);
272 if (error) {
273 dev_err(buttons->dev,
274 "Failed to open input device, error %d\n",
275 error);
276 input_unregister_handle(buttons->ts_handle);
277 kfree(buttons->ts_handle);
278 buttons->ts_handle = NULL;
279 }
280 }
281 mutex_unlock(&buttons->mutex);
282 }
283
284 static int touchscreen_buttons_input_connect(struct input_handler *handler,
285 struct input_dev *dev,
286 const struct input_device_id *id)
287 {
288 struct touchscreen_buttons *buttons;
289
290 buttons = handler->private;
291
292 mutex_lock(&buttons->mutex);
293
294 if ((!buttons->ts_handle
295 && device_match_of_node(&dev->dev, buttons->map->ts_node))
296 || (dev->dev.parent
297 && device_match_of_node(dev->dev.parent,
298 buttons->map->ts_node))) {
299 int error;
300
301 dev_info(buttons->dev, "Binding to device: %s\n",
302 dev_name(&dev->dev));
303
304 buttons->ts_handle =
305 kzalloc(sizeof(*buttons->ts_handle), GFP_KERNEL);
306 if (!buttons->ts_handle) {
307 mutex_unlock(&buttons->mutex);
308 return -ENOMEM;
309 }
310
311 buttons->ts_handle->dev = dev;
312 buttons->ts_handle->handler = handler;
313 buttons->ts_handle->name = "touchscreen-buttons";
314 buttons->ts_handle->private = handler->private;
315 buttons->queue.lastindex = 0;
316
317 error = input_register_handle(buttons->ts_handle);
318 if (error) {
319 dev_err(buttons->dev,
320 "Failed to register input handler, error %d\n",
321 error);
322 kfree(buttons->ts_handle);
323 buttons->ts_handle = NULL;
324 mutex_unlock(&buttons->mutex);
325 return error;
326 }
327
328 queue_work(buttons->workqueue, &buttons->merge_task);
329
330 if (buttons->filtered_ts_idev->users > 0
331 && buttons->ts_handle->open == 0)
332 queue_work(buttons->workqueue, &buttons->open_task);
333 }
334
335 mutex_unlock(&buttons->mutex);
336 return 0;
337 }
338
339 static void touchscreen_buttons_input_disconnect(struct input_handle *handle)
340 {
341 struct touchscreen_buttons *buttons;
342
343 buttons = handle->private;
344
345 mutex_lock(&buttons->mutex);
346 if (handle == buttons->ts_handle) {
347 input_close_device(handle);
348 input_unregister_handle(handle);
349 kfree(handle);
350 buttons->ts_handle = NULL;
351 dev_info(buttons->dev,
352 "Touchscreen device disconnected buttons disabled\n");
353 } else {
354 dev_err(buttons->dev,
355 "Unknown device disconnected, %p should be %p", handle,
356 buttons->ts_handle);
357 }
358 mutex_unlock(&buttons->mutex);
359 }
360
361 static struct touchscreen_button_map
362 *touchscreen_buttons_get_devtree_pdata(struct device *dev)
363 {
364 struct touchscreen_button_map *map;
365 struct fwnode_handle *child_node;
366 struct device_node *node;
367 int i;
368
369 map = kzalloc(sizeof(*map), GFP_KERNEL);
370 if (!map)
371 return ERR_PTR(-ENOMEM);
372
373 map->count = device_get_child_node_count(dev);
374 if (map->count == 0)
375 return ERR_PTR(-ENODEV);
376
377 map->buttons = kcalloc(map->count, sizeof(*map->buttons), GFP_KERNEL);
378 if (!map->buttons)
379 return ERR_PTR(-ENOMEM);
380
381 node = dev->of_node;
382 map->ts_node = of_parse_phandle(node, "touchscreen_phandle", 0);
383 if (!map->ts_node) {
384 dev_err(dev, "touchscreen_phandle node missing\n");
385 return ERR_PTR(-ENODEV);
386 }
387
388 dev_info(dev, "Device_node name: %s\n", map->ts_node->name);
389
390 i = 0;
391 device_for_each_child_node(dev, child_node) {
392 struct touchscreen_button *button;
393
394 button = &map->buttons[i];
395
396 fwnode_property_read_u32(child_node, "x-position", &button->x);
397 fwnode_property_read_u32(child_node, "y-position", &button->y);
398 fwnode_property_read_u32(child_node, "x-size", &button->width);
399 fwnode_property_read_u32(child_node, "y-size", &button->height);
400 fwnode_property_read_u32(child_node, "keycode",
401 &button->keycode);
402 dev_info(dev,
403 "Adding button at x=%u y=%u size %u x %u keycode=%u\n",
404 button->x, button->y, button->width, button->height,
405 button->keycode);
406 ++i;
407 }
408 return map;
409 }
410
> 411 int touchscreen_buttons_idev_opened(struct input_dev *idev)
412 {
413 struct touchscreen_buttons *buttons;
414
415 buttons = dev_get_drvdata(idev->dev.parent);
416
417 mutex_lock(&buttons->mutex);
418 if (buttons && buttons->ts_handle) {
419 if (buttons->ts_handle->open == 0) {
420 queue_work(buttons->workqueue, &buttons->open_task);
421 dev_dbg(idev->dev.parent, "idev opened\n");
422 } else {
423 dev_info(idev->dev.parent, "idev allready opened\n");
424 }
425 } else {
426 dev_warn(idev->dev.parent,
427 "Input device opend but touchscreen not opened. %p %p\n",
428 buttons, buttons->ts_handle);
429 }
430 mutex_unlock(&buttons->mutex);
431 return 0;
432 }
433
> 434 void touchscreen_buttons_idev_closed(struct input_dev *idev)
435 {
436 struct touchscreen_buttons *buttons;
437
438 buttons = dev_get_drvdata(idev->dev.parent);
439
440 mutex_lock(&buttons->mutex);
441 if (buttons && buttons->ts_handle && buttons->ts_handle->open != 0) {
442 queue_work(buttons->workqueue, &buttons->close_task);
443 dev_dbg(idev->dev.parent, "idev closed\n");
444 }
445 mutex_unlock(&buttons->mutex);
446 }
447
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28749 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-11-03 9:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-10-30 9:05 [PATCH v3] ARM: dts: motorola-mapphone-common: Add dts configureation for the android buttons beneath the screen Carl Philipp Klemm
2020-10-31 7:15 ` Tony Lindgren
[not found] ` <20201031103722.6efbf69b084ed35d2f700fe9@uvos.xyz>
2020-10-31 9:55 ` Carl Philipp Klemm
2020-11-03 9:20 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox