mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* overriding keyboard driver in a module
@ 2005-07-07  1:41 Genadz Batsyan
  2005-07-07  5:25 ` Dmitry Torokhov
  0 siblings, 1 reply; 2+ messages in thread
From: Genadz Batsyan @ 2005-07-07  1:41 UTC (permalink / raw)
  To: linux-kernel

I'm writing a little tool to allow intercepting keyboard events and 
substituting them with other events / swallowing events / emitting additional 
events on a low level before normal processing by kernel.
http://kbd-mangler.sourceforge.net/

Currently to have precedense over the keyboard driver I'm using a patch 
against drivers/input/keyboard/atkbd.c

Well, I guess, patching kernel is unthinkable for most linux users, so I 
thought, maybe there is a way to do it without the kernel patch.
Is it possible to write a kernel module to intercept keyboard events
and have precedense over the kernel driver?

If anyone is interested, below is my patch.
 I know it's damn dirty (especially the last_dev thingy :-)
but take it easy, it's my first kernel undertaking, a product of a few days, 
and most importantly - it works.

Any kind of suggestions would be appreciated a lot.

-----------------------

--- linux-2.6.11.6-orig/drivers/input/keyboard/atkbd.c	2005-03-26 
04:28:48.000000000 +0100
+++ linux-2.6.11.6-patched/drivers/input/keyboard/atkbd.c	2005-07-01 
22:15:52.000000000 +0200
@@ -34,6 +34,10 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
+
+#define CONFIG_KBD_INTERCEPTOR 1
+
+
 static int atkbd_set = 2;
 module_param_named(set, atkbd_set, int, 0);
 MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 
native)");
@@ -229,18 +233,79 @@
 ATKBD_DEFINE_ATTR(softraw);
 
 
-static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int 
code, int value)
+
+
+
+#ifdef CONFIG_KBD_INTERCEPTOR
+
+typedef int (*KBD_INTERCEPTOR)(int *, int *);
+
+static KBD_INTERCEPTOR kbd_interceptor;
+static struct input_dev *last_dev;
+
+#endif
+
+
+
+
+static void _atkbd_report_key(struct input_dev *dev, int code, int value)
 {
-	input_regs(dev, regs);
 	if (value == 3) {
 		input_report_key(dev, code, 1);
 		input_sync(dev);
 		input_report_key(dev, code, 0);
 	} else
 		input_event(dev, EV_KEY, code, value);
+}
+
+static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int 
code, int value)
+{
+	input_regs(dev, regs);
+
+#ifdef CONFIG_KBD_INTERCEPTOR
+        if (kbd_interceptor && kbd_interceptor(&code, &value))
+        {
+                return;
+        }
+#endif
+	_atkbd_report_key(dev, code, value);
 	input_sync(dev);
 }
 
+#ifdef CONFIG_KBD_INTERCEPTOR
+KBD_INTERCEPTOR kbd_set_interceptor(KBD_INTERCEPTOR interceptor)
+{
+        KBD_INTERCEPTOR old = kbd_interceptor;
+        kbd_interceptor = interceptor;
+        return old;
+}
+
+void kbd_emit_key(int code, int down)
+{
+    if (last_dev)
+        _atkbd_report_key(last_dev, code, down);
+    else
+        printk("kbd_emit_key: input_dev not set\n");
+}
+void kbd_emit_sync()
+{
+    if (last_dev)
+        input_sync(last_dev);
+    else
+        printk("kbd_emit_key: input_dev not set\n");
+}
+
+
+EXPORT_SYMBOL(kbd_set_interceptor);
+EXPORT_SYMBOL(kbd_emit_key);
+EXPORT_SYMBOL(kbd_emit_sync);
+
+#endif
+
+
+
+
+
 /*
  * atkbd_interrupt(). Here takes place processing of data received from
  * the keyboard into events.
@@ -660,6 +725,10 @@
 {
 	struct atkbd *atkbd = serio->private;
 
+#ifdef CONFIG_KBD_INTERCEPTOR
+        last_dev = NULL;
+#endif
+
 	atkbd_disable(atkbd);
 
 	/* make sure we don't have a command in flight */
@@ -847,6 +916,10 @@
 
 	input_register_device(&atkbd->dev);
 
+#ifdef CONFIG_KBD_INTERCEPTOR
+	last_dev = &atkbd->dev;
+#endif
+
 	device_create_file(&serio->dev, &atkbd_attr_extra);
 	device_create_file(&serio->dev, &atkbd_attr_scroll);
 	device_create_file(&serio->dev, &atkbd_attr_set);
@@ -1097,6 +1170,9 @@
 
 int __init atkbd_init(void)
 {
+#ifdef CONFIG_KBD_INTERCEPTOR
+        last_dev = NULL;
+#endif
 	serio_register_driver(&atkbd_drv);
 	return 0;
 }




^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: overriding keyboard driver in a module
  2005-07-07  1:41 overriding keyboard driver in a module Genadz Batsyan
@ 2005-07-07  5:25 ` Dmitry Torokhov
  0 siblings, 0 replies; 2+ messages in thread
From: Dmitry Torokhov @ 2005-07-07  5:25 UTC (permalink / raw)
  To: Genadz Batsyan, linux-kernel

Genadz Batsyan <gbatyan@gmx.net> wrote:
> I'm writing a little tool to allow intercepting keyboard events and 
> substituting them with other events / swallowing events / emitting
> additional 
> events on a low level before normal processing by kernel.
> http://kbd-mangler.sourceforge.net/
> 
> Currently to have precedense over the keyboard driver I'm using a patch 
> against drivers/input/keyboard/atkbd.c
> 
> Well, I guess, patching kernel is unthinkable for most linux users, so I 
> thought, maybe there is a way to do it without the kernel patch.
> Is it possible to write a kernel module to intercept keyboard events
> and have precedense over the kernel driver?
> 

You can try opening corresponding event device (/dev/input/eventX),
grabbing it so nobody except for your process would get any events
from the corresponding keyboard (EVIOCGRAB ioctl), and then read
events, mangle them and inject them back into kernel through uinput
driver.

As an additional plus it should work for any keyboard (or rather any
input device), not only PS/2 keyboard.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-07-07  5:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-07-07  1:41 overriding keyboard driver in a module Genadz Batsyan
2005-07-07  5:25 ` Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®