From: Sascha Hauer <s.hauer@pengutronix.de>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH 07/15] input: Add input core
Date: Wed, 13 Jan 2016 16:37:28 +0100 [thread overview]
Message-ID: <1452699456-1025-8-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1452699456-1025-1-git-send-email-s.hauer@pengutronix.de>
Currently all input driver register themselves as consoles. Consoles are
fine for typing text, but they do not allow to ask for the current
pressed state of buttons or keypads. They also do not support non
printable keys like the function keys.
This patch adds a simple input core. On the driver side it supports
input_report_key_event() to report events (button presses and releases).
On the consumer side it allows getting the current button status via
input_key_get_status(). Also an event driven interface is available
which calls a callback whenever an input event is received.
The input core also registers a console for all registered input
devices which handles passing events to the console and stuff like key
repetition, so this can be removed from the drivers once they are
converted to the input core.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/input/Kconfig | 3 +
drivers/input/Makefile | 1 +
drivers/input/input.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++
include/input/input.h | 34 +++++++++
4 files changed, 240 insertions(+)
create mode 100644 drivers/input/input.c
create mode 100644 include/input/input.h
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 336b9f5..e0368b2 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -5,6 +5,9 @@
menu "Input device support"
depends on !CONSOLE_NONE
+config INPUT
+ bool
+
config KEYBOARD_GPIO
bool "GPIO Buttons"
depends on GENERIC_GPIO
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 40b898c..b9e5a5d 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_INPUT) += input.o
obj-$(CONFIG_KEYBOARD_USB) += usb_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_TWL6030) += twl6030_pwrbtn.o
diff --git a/drivers/input/input.c b/drivers/input/input.c
new file mode 100644
index 0000000..ad7400f
--- /dev/null
+++ b/drivers/input/input.c
@@ -0,0 +1,202 @@
+/*
+ * 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; version 2.
+ *
+ * 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 <common.h>
+#include <init.h>
+#include <kfifo.h>
+#include <poller.h>
+#include <clock.h>
+#include <input/input.h>
+#include <linux/bitmap.h>
+#include <input/keyboard.h>
+#include <dt-bindings/input/linux-event-codes.h>
+
+static LIST_HEAD(input_consumers);
+
+int input_register_notfier(struct input_notifier *in)
+{
+ list_add_tail(&in->list, &input_consumers);
+
+ return 0;
+}
+
+void input_unregister_notfier(struct input_notifier *in)
+{
+ list_del(&in->list);
+}
+
+void input_report_key_event(struct input_device *idev, unsigned int code, int value)
+{
+ struct input_event event;
+ struct input_notifier *in;
+
+ if (code > KEY_MAX)
+ return;
+
+ if (value)
+ set_bit(code, &idev->keys);
+ else
+ clear_bit(code, &idev->keys);
+
+ event.code = code;
+ event.value = value;
+
+ list_for_each_entry(in, &input_consumers, list)
+ in->notify(in, &event);
+}
+
+static LIST_HEAD(input_devices);
+
+int input_device_register(struct input_device *idev)
+{
+ list_add_tail(&idev->list, &input_devices);
+
+ return 0;
+}
+
+void input_device_unregister(struct input_device *idev)
+{
+ list_del(&idev->list);
+}
+
+void input_key_get_status(unsigned long *keys, int bits)
+{
+ struct input_device *idev;
+
+ bitmap_zero(keys, bits);
+
+ if (bits > KEY_MAX)
+ bits = KEY_MAX;
+
+ list_for_each_entry(idev, &input_devices, list)
+ bitmap_or(keys, keys, idev->keys, bits);
+}
+
+struct input_console {
+ struct console_device console;
+ struct input_notifier notifier;
+ struct kfifo *fifo;
+ struct poller_async poller;
+ uint8_t current_key;
+ uint8_t modstate[6];
+};
+
+static int input_console_tstc(struct console_device *cdev)
+{
+ struct input_console *ic = container_of(cdev, struct input_console, console);
+
+ return kfifo_len(ic->fifo) ? 1 : 0;
+}
+
+static int input_console_getc(struct console_device *cdev)
+{
+ struct input_console *ic = container_of(cdev, struct input_console, console);
+ uint8_t c;
+
+ kfifo_getc(ic->fifo, &c);
+
+ return c;
+}
+
+static void input_console_repeat(void *ctx)
+{
+ struct input_console *ic = ctx;
+
+ if (ic->current_key) {
+ kfifo_putc(ic->fifo, ic->current_key);
+ poller_call_async(&ic->poller, 40 * MSECOND,
+ input_console_repeat, ic);
+ }
+}
+
+struct keycode {
+ unsigned char key;
+ unsigned char ascii;
+};
+
+static void input_console_notify(struct input_notifier *in,
+ struct input_event *ev)
+{
+ struct input_console *ic = container_of(in, struct input_console, notifier);
+ uint8_t modstate = 0;
+ unsigned char ascii;
+
+ switch (ev->code) {
+ case KEY_LEFTSHIFT:
+ ic->modstate[0] = ev->value;
+ return;
+ case KEY_RIGHTSHIFT:
+ ic->modstate[1] = ev->value;
+ return;
+ case KEY_LEFTCTRL:
+ ic->modstate[2] = ev->value;
+ return;
+ case KEY_RIGHTCTRL:
+ ic->modstate[3] = ev->value;
+ return;
+ case KEY_LEFTALT:
+ ic->modstate[4] = ev->value;
+ return;
+ case KEY_RIGHTALT:
+ ic->modstate[5] = ev->value;
+ return;
+ case KEY_LEFTMETA:
+ case KEY_RIGHTMETA:
+ return;
+ default:
+ break;
+ }
+
+ if (ic->modstate[0] || ic->modstate[1])
+ modstate |= 1 << 0;
+
+ if (ic->modstate[2] || ic->modstate[3])
+ modstate |= 1 << 1;
+
+ if (ic->modstate[4] || ic->modstate[5])
+ modstate |= 1 << 2;
+
+ if (modstate & (1 << 0))
+ ascii = keycode_bb_shift_keys[ev->code];
+ else
+ ascii = keycode_bb_keys[ev->code];
+
+ pr_debug("map %02x KEY: 0x%04x code: %d\n", modstate, ascii, ev->code);
+
+ if (ev->value) {
+ kfifo_putc(ic->fifo, ascii);
+ ic->current_key = ascii;
+ poller_call_async(&ic->poller, 400 * MSECOND,
+ input_console_repeat, ic);
+ } else {
+ ic->current_key = 0;
+ poller_async_cancel(&ic->poller);
+ }
+}
+
+static struct input_console input_console;
+
+static int input_init(void)
+{
+ struct input_console *ic = &input_console;
+
+ ic->console.tstc = input_console_tstc;
+ ic->console.getc = input_console_getc;
+ ic->console.f_active = CONSOLE_STDIN;
+
+ ic->fifo = kfifo_alloc(32);
+ ic->notifier.notify = input_console_notify;
+ input_register_notfier(&ic->notifier);
+ poller_async_register(&ic->poller);
+
+ return console_register(&ic->console);
+}
+console_initcall(input_init);
diff --git a/include/input/input.h b/include/input/input.h
new file mode 100644
index 0000000..dbf3e7f
--- /dev/null
+++ b/include/input/input.h
@@ -0,0 +1,34 @@
+#ifndef __INPUT_H
+#define __INPUT_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <dt-bindings/input/linux-event-codes.h>
+
+struct input_event {
+ uint16_t code;
+ uint16_t value;
+};
+
+struct input_device {
+ struct list_head list;
+ DECLARE_BITMAP(keys, KEY_CNT);
+};
+
+void input_report_key_event(struct input_device *idev, unsigned int code, int value);
+
+int input_device_register(struct input_device *);
+void input_device_unregister(struct input_device *);
+
+void input_key_get_status(unsigned long *keys, int bits);
+
+struct input_notifier {
+ void (*notify)(struct input_notifier *in, struct input_event *event);
+ struct list_head list;
+};
+
+int input_register_notfier(struct input_notifier *in);
+void input_unregister_notfier(struct input_notifier *in);
+
+#endif /* __INPUT_H */
+
--
2.6.4
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2016-01-13 15:38 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-13 15:37 [PATCH] " Sascha Hauer
2016-01-13 15:37 ` [PATCH 01/15] poller: Fix async poller Sascha Hauer
2016-01-13 15:37 ` [PATCH 02/15] keymap: Fix braces Sascha Hauer
2016-01-13 15:37 ` [PATCH 03/15] keymap: remove exotic and nonprintable keys Sascha Hauer
2016-01-13 15:37 ` [PATCH 04/15] keymap: Add keypad keys Sascha Hauer
2016-01-13 15:37 ` [PATCH 05/15] keymap: Add apostrophe, backslash and home Sascha Hauer
2016-01-13 15:37 ` [PATCH 06/15] keymap: Add keymap for keys with shift pressed Sascha Hauer
2016-01-13 15:37 ` Sascha Hauer [this message]
2017-05-05 10:05 ` [PATCH 07/15] input: Add input core Antony Pavlov
2017-05-05 11:10 ` Sascha Hauer
2016-01-13 15:37 ` [PATCH 08/15] input: usb keyboard: convert to input framework Sascha Hauer
2016-01-13 15:37 ` [PATCH 09/15] input: imx-keypad: Use dev_* functions Sascha Hauer
2016-01-13 15:37 ` [PATCH 10/15] input: move matrix_keypad_build_keymap() to C file Sascha Hauer
2016-01-13 15:37 ` [PATCH 11/15] input: imx-keypad: convert to input framework Sascha Hauer
2016-01-13 15:37 ` [PATCH 12/15] input: Add device tree parsing support for matrix keymap Sascha Hauer
2016-01-13 15:37 ` [PATCH 13/15] input: imx-keypad: Add device tree support Sascha Hauer
2016-01-13 15:37 ` [PATCH 14/15] input: gpio-keys: Use KEY_* keycodes Sascha Hauer
2016-01-13 15:37 ` [PATCH 15/15] input: gpio-keys: convert to input framework Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1452699456-1025-8-git-send-email-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox