2003-05-08 19:00:12

by Khalid Aziz

[permalink] [raw]
Subject: Re: [RFC][PATCH] "Disable Trackpad while typing" on Notebooks withh aPS/2 Trackpad

This patch makes it impossible to perform any operation that requires
pressing a key on the keyboard while clicking a mouse button - for
example bringing up X-terminal menu with CTRL-<middle button>. I am sure
there are other similar combination used by other software. You would
think 1 second after the CTRL key is pressed (which is when a keyboard
event is generated), mouse will be re-enabled and you should be able to
click mouse buttons as long as you do not let go of the key. Does not
seem to work that way. Mouse stays disabled as long as the key is
pressed.

--
Khalid

Hans-Georg Thien wrote:
>
> Sorry for this long text and my bad english. And please be kind to me -
> it is my very first posting to this mailing list ...
>
> I have written a *very small* patch against the linux 2.4.20 kernel and
> I want to submit it now.
>
> The short story
> ---------------
> The trackpad on the MacIntosh iBook Notebooks have a feature that
> prevents unintended trackpad input while typing on the keyboard. There
> are no mouse-moves or mouse-taps for a short period of time after each
> keystroke.
>
> I believe that many people with i386 notebooks would like this feature
> and I want to give it to the linux community.
>
> First I had the idea of writing a loadable kernel module "trackpad" that
> implements that feature and is loadable via
>
> insmod keybd_irq=? mouse_irq=? delay=?
>
> The long story
> --------------
> My first approach was - because I came from the bad old M$-DOS times -
> write something like a "terminate and stay resident program"
>
> Procedure LoadModule
> Save the currentlly installed handlers for keyboard and mouse.
> Install your own interrupt handlers for keyboard and mouse.
> End
>
> Procedure UnloadModule
> Stop and remove "reset-timer" if necessary
> Restore the saved interrupt handlers for keyboard and mouse
> End
>
> Procedure KbdHandler
> Stop or modify "reset-timer" if necessary
> Set global variable block_mouse_events=1
> Start a timer that resets block_mouse_events=0 after ??? mSec
> Call the old keyboard interrupt handler
> End
>
> Proceure MouseHandler
> if block_mouse_events>0 then
> call ACK(mouse irq) if necessary
> do nothing
> else
> call old mouse interrupt handler
> End
>
> So I bought the book "Linux Device Drivers" written by Alessandro Rubini
> & Jonathan Corbert. It is an excellent book about LKM, but I couldn't
> find a way to "save and restore" irq-handlers as in the design
> described above.
>
> That's why I requested a little help in the newsgroup at
> comp.os.linux.development.system. This ended up with some people who
> said "don't mess around with irq-handlers in that way".
>
> While trying to gain a deeper understanding of irq-handling - espically
> for mouse and keyboard handlers - I found out that the keyboard and
> mouse interrupts are handled *both* in
> /usr/src/linux/drivers/char/pc_keyb.c.
>
> Ok, that is only true for PS/2 mice, but the majority of notebooks on
> the market have a PS/2 trackpad. On modifiying the pc_keyb.c file there
> is no longer a need to save/restore Interrupt handlers or to call them
> indirecty via a function pointer. Unfortunatly it has to be compiled in
> the kernel and cannot be written as a LKM module.
>
> But anyway - I sad down and got a working solution very quickly! I'm
> very glad with it! I needed not more than 45 minutes to get this
> working! Works in textmode (gpm) and under X11 as expected!
>
> Testing
> -------
> I have tested my patch only on my own notebook (Compaq M300). It would
> help a lot if there are some volunteers...
>
> Future Plans
> ------------
> [x] make the "disable trackpad time" configurable via the /proc
> filesystem. Do you think that /proc/sys/kernel/trackpad is a good place
> for it? There are other files under the /proc/sys/kernel directory that
> fall in the category "keyboard handling", e.g. ctrl-alt-del or sysrq.
>
> [x] make a /proc entry to allow "disable trackpad" and "enable
> trackpad". That would allow to turn the builtin trackpad off when an
> external mouse is pluged in, and to re-enable it when an external mouse
> is unplugged again.
>
--

====================================================================
Khalid Aziz Linux and Open Source Lab
(970)898-9214 Hewlett-Packard
[email protected] Fort Collins, CO

"The Linux kernel is subject to relentless development"
- Alessandro Rubini


2003-05-09 11:33:06

by Hans-Georg Thien

[permalink] [raw]
Subject: Re: [RFC][PATCH] "Disable Trackpad while typing" on Notebooks withh aPS/2 Trackpad

--- /usr/src/linux-2.4.20/Documentation/Configure.help Fri Nov 29 00:53:08 2002
+++ /usr/src/linux/Documentation/Configure.help Thu May 1 02:12:04 2003
@@ -17752,6 +17752,16 @@
<ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.

+Disable trackpad while typing
+CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ For people with a notebook that have a build in trackpad.
+
+ It prevents unintended mouse moves and mouse taps while typing on
+ the notebook keyboard.
+
+ The majority of notebooks on the market have a PS/2 trackpad.
+ So you will probably say "Y" if you have a notebook with a trackpad.
+
C&T 82C710 mouse port support (as on TI Travelmate)
CONFIG_82C710_MOUSE
This is a certain kind of PS/2 mouse used on the TI Travelmate. If
--- /usr/src/linux-2.4.20/drivers/char/Config.in Fri Nov 29 00:53:12 2002
+++ /usr/src/linux/drivers/char/Config.in Thu May 1 02:30:45 2003
@@ -170,6 +170,13 @@
tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
if [ "$CONFIG_MOUSE" != "n" ]; then
bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+
+ if [ "$CONFIG_PSMOUSE" = "y" ]
+ then
+ bool ' Disable Trackpad while typing on Notebooks' CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ fi
+
+
tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD
tristate ' MK712 touch screen support' CONFIG_MK712_MOUSE
--- /usr/src/linux-2.4.20/drivers/char/pc_keyb.c Fri Nov 29 00:53:12 2002
+++ /usr/src/linux/drivers/char/pc_keyb.c Fri May 9 15:17:45 2003
@@ -13,6 +13,11 @@
* Code fixes to handle mouse ACKs properly.
* C. Scott Ananian <[email protected]> 1999-01-29.
*
+ * Implemented the "disable trackpad while typing" feature. This prevents
+ * unintended mouse moves and mouse taps while typing on the keyboard on
+ * notebooks with a PS/2 trackpad.
+ * Hans-Georg Thien <[email protected]> 2003-04-30.
+ *
*/

#include <linux/config.h>
@@ -67,6 +72,11 @@
static void aux_write_ack(int val);
static void __aux_write_ack(int val);
static int aux_reconnect = 0;
+
+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+static int last_kbd_event = 0; /* used to hold timestamp of last kbd event */
+#endif
+
#endif

#ifndef kbd_controller_present
@@ -449,6 +459,11 @@
return;
}

+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ /* do nothing if time since last kbd event is less then 1Sec */
+ if ( abs(jiffies - last_kbd_event) < HZ ) return;
+#endif
+
prev_code = scancode;
add_mouse_randomness(scancode);
if (aux_count) {
@@ -469,6 +484,17 @@

static inline void handle_keyboard_event(unsigned char scancode)
{
+
+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ static unsigned char prev_scancode=0;
+
+ if (scancode != prev_scancode)
+ {
+ last_kbd_event = jiffies;
+ prev_scancode=scancode;
+ }
+#endif
+
#ifdef CONFIG_VT
kbd_exists = 1;
if (do_acknowledge(scancode))


Attachments:
trackpad-2.4.20.diff (3.04 kB)

2003-05-27 20:32:29

by Hans-Georg Thien

[permalink] [raw]
Subject: Re: [RFC][PATCH] "Disable Trackpad while typing" on Notebooks withh aPS/2 Trackpad

--- /usr/src/linux-2.4.20/Documentation/Configure.help Fri Nov 29 00:53:08 2002
+++ /usr/src/linux/Documentation/Configure.help Wed May 28 00:04:44 2003
@@ -17752,6 +17752,44 @@
<ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.

+Disable trackpad while typing
+CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ For people with a notebook that have a build in trackpad.
+
+ It prevents unintended mouse moves and mouse taps while typing on
+ the notebook keyboard.
+
+ The majority of notebooks on the market have a PS/2 trackpad.
+ So you will probably say "Y" if you have a notebook with a trackpad.
+
+ Also note that you can control the behaviour of the trackpad via the
+ /proc/tty/ps2-trackpad file, e.g.
+
+ Set the delay time to 2 Secs (default is 10 ==> 1 Sec)
+
+ echo "delay 20" > /proc/tty/ps2-trackpad
+
+
+ Completely disable the trackpad (default 0). Useful if you plug in an
+ external mouse.
+
+ echo "disable 1" > /proc/tty/ps2-trackpad
+
+
+ Escape the keyboard scancode for the key. These scancodes are passed
+ without a delay. (defaults are the scancodes for CTRL and SHIFT keys).
+
+ This is useful for some applications ( like xterm ) which are using
+ keydown-click events.
+
+ You can use showkey -s to find out the scancodes of your own keys.
+ Apply "escape 0x0??" twice to unescape a scancode. For keys with
+ multiple scancodes you must use the *last* generated scancode.
+
+ Example: define an escape for HOME-KeyDown
+
+ echo "escape 0x047" > /proc/tty/ps2-trackpad
+
C&T 82C710 mouse port support (as on TI Travelmate)
CONFIG_82C710_MOUSE
This is a certain kind of PS/2 mouse used on the TI Travelmate. If
--- /usr/src/linux-2.4.20/drivers/char/Config.in Fri Nov 29 00:53:12 2002
+++ /usr/src/linux/drivers/char/Config.in Thu May 1 02:30:45 2003
@@ -170,6 +170,13 @@
tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
if [ "$CONFIG_MOUSE" != "n" ]; then
bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+
+ if [ "$CONFIG_PSMOUSE" = "y" ]
+ then
+ bool ' Disable Trackpad while typing on Notebooks' CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ fi
+
+
tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD
tristate ' MK712 touch screen support' CONFIG_MK712_MOUSE
--- /usr/src/linux-2.4.20/drivers/char/pc_keyb.c Fri Nov 29 00:53:12 2002
+++ /usr/src/linux/drivers/char/pc_keyb.c Tue May 27 23:08:46 2003
@@ -13,6 +13,11 @@
* Code fixes to handle mouse ACKs properly.
* C. Scott Ananian <[email protected]> 1999-01-29.
*
+ * Implemented the "disable trackpad while typing" feature. This prevents
+ * unintended mouse moves and mouse taps while typing on the keyboard on
+ * notebooks with a PS/2 trackpad.
+ * Hans-Georg Thien <[email protected]> 2003-04-30.
+ *
*/

#include <linux/config.h>
@@ -35,7 +40,7 @@
#include <linux/smp_lock.h>
#include <linux/kd.h>
#include <linux/pm.h>
-
+#include <linux/proc_fs.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
@@ -102,6 +107,125 @@
#define MAX_RETRIES 60 /* some aux operations take long time*/
#endif /* CONFIG_PSMOUSE */

+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+
+static int last_kbd_event = 0; /* timestamp of last kbd event */
+static int last_kbd_scancode = 0;
+static int trackpad_disable = 0;
+static int trackpad_delay = HZ; /* default delay is 1Sec */
+
+static unsigned char trackpad_escape[256/8]; /* 256-Bit vector of keyboard scancodes to ignore */
+
+
+static int trackpad_write_proc(struct file *file,
+ const char *buf,
+ unsigned long len,
+ void *data)
+{
+
+/*
+ * handle write requests to /proc/tty/ps2-trackpad
+ */
+ char lbuf[32];
+ int tmp;
+ int success = 0;
+
+ if (len > sizeof(lbuf)-1) return -EINVAL;
+
+ if (copy_from_user(lbuf, buf, len)) return -EFAULT;
+
+ lbuf[len] = '\0';
+
+ if (sscanf(lbuf, "delay %d", &tmp)) {
+ trackpad_delay = (tmp * HZ) / 10; /* convert 1/10Sec to jiffies */
+ success=1;
+ }
+
+ if (sscanf(lbuf, "disable %d", &tmp)) {
+ trackpad_disable = tmp ? 1 : 0;
+ success=1;
+ }
+
+ if (sscanf(lbuf, "escape 0x%x", &tmp)) {
+ if ((tmp < 0) || (tmp > 255)) return -EINVAL;
+ change_bit(tmp, trackpad_escape);
+ success=1;
+ }
+
+ if (!success) return -EINVAL;
+
+ return len;
+}
+
+static int trackpad_read_proc(char *buf, char **start, off_t ofs,
+ int count, int *eof, void *data)
+{
+
+/*
+ * handle read requests to /proc/tty/ps2-trackpad
+ */
+
+ int len = 0;
+ int i;
+
+ len += sprintf(buf+len, "delay %d\n",
+ (trackpad_delay * 10) / HZ); /* convert jiffies to 1/10Sec */
+ len += sprintf(buf+len, "disable %d\n", trackpad_disable);
+
+ for (i = 0; i < sizeof(trackpad_escape) * 8; i++) {
+ if (test_bit(i, trackpad_escape)) {
+ len += sprintf(buf+len, "escape 0x0%x\n", i);
+ }
+ }
+
+ *eof = 1;
+ buf[len+1] = '\0';
+ return len;
+}
+
+static int trackpad_config_setup(void)
+{
+
+/*
+ * create read-write entries in /proc/tty/ps2-trackpad and setup some
+ * defaults for the trackpad handling
+ */
+
+ struct proc_dir_entry *trackpad_proc_entry;
+
+ trackpad_proc_entry=create_proc_entry("tty/ps2-trackpad", 0, NULL);
+
+ if (trackpad_proc_entry == NULL) return -1;
+
+ trackpad_proc_entry->mode |= S_IWUGO;
+ trackpad_proc_entry->read_proc = trackpad_read_proc;
+ trackpad_proc_entry->write_proc = trackpad_write_proc;
+
+
+ /* set keyboard scancodes to ignore */
+ memset(trackpad_escape, 0, sizeof(trackpad_escape));
+ set_bit(0x1d, trackpad_escape); /* CTRL-L/CTRL-R keydown */
+ set_bit(0x2a, trackpad_escape); /* SHIFT-L keydown */
+ set_bit(0x36, trackpad_escape); /* SHIFT-R keydown */
+#if 0
+ set_bit(0x38, trackpad_escape); /* ALT-L/ALT-R keydown */
+ set_bit(0x01, trackpad_escape); /* ESC keydown */
+ set_bit(0x47, trackpad_escape); /* HOME keydown */
+ set_bit(0x48, trackpad_escape); /* CURSORUP keydown */
+ set_bit(0x49, trackpad_escape); /* PAGEUP keydown */
+ set_bit(0x4b, trackpad_escape); /* CURSOR-L keydown */
+ set_bit(0x4d, trackpad_escape); /* CURSOR-R keydown */
+ set_bit(0x4f, trackpad_escape); /* END keydown */
+ set_bit(0x50, trackpad_escape); /* CURSORDOWN keydown */
+ set_bit(0x51, trackpad_escape); /* PAGEDOWN keydown */
+ set_bit(0x5d, trackpad_escape); /* MENU keydown */
+#endif
+
+ return 0;
+}
+
+#endif /* CONFIG_DISABLE_TRACKPAD_WHILE_TYPING */
+
/*
* Wait for keyboard controller input buffer to drain.
*
@@ -449,6 +573,15 @@
return;
}

+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ if (trackpad_disable) return;
+
+ if (!test_bit(last_kbd_scancode, trackpad_escape)) {
+ /* do nothing if time since last kbd event is less then trackpad_delay */
+ if (abs(jiffies - last_kbd_event) < trackpad_delay) return;
+ }
+#endif
+
prev_code = scancode;
add_mouse_randomness(scancode);
if (aux_count) {
@@ -469,6 +602,12 @@

static inline void handle_keyboard_event(unsigned char scancode)
{
+
+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ last_kbd_event = jiffies;
+ last_kbd_scancode = scancode;
+#endif
+
#ifdef CONFIG_VT
kbd_exists = 1;
if (do_acknowledge(scancode))
@@ -1219,6 +1358,10 @@
kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */

+#ifdef CONFIG_DISABLE_TRACKPAD_WHILE_TYPING
+ trackpad_config_setup();
+#endif
+
return 0;
}




Attachments:
trackpad-2.4.20.diff (8.05 kB)

2003-05-27 20:57:16

by wwp

[permalink] [raw]
Subject: Re: [RFC][PATCH] "Disable Trackpad while typing" on Notebooks withh aPS/2 Trackpad

Hi Hans-Georg Thien,


On Tue, 27 May 2003 22:47:06 +0200 Hans-Georg Thien <[email protected]>
wrote:

> Hans-Georg Thien wrote:
[snip]
> It it is now possible to adjust some settings via
>
> echo ???? > /proc/tty/ps2-trackpad
>
> (1) Set the delay time to 2 Secs (default is 10 ==> 1 Sec)
>
> echo "delay 20" > /proc/tty/ps2-trackpad
>
>
> (2) Completely disable the trackpad (default 0). Useful if you plug in
> an external mouse.
>
> echo "disable 1" > /proc/tty/ps2-trackpad
>
> (3) Escape the keyboard scancode for a key. These scancodes are
[snip]

Sounds good, thanx for your work, guy :-).
Do you think/know if this patch will be merged to the official tree?


Regards,

--
wwp

2003-05-29 11:50:51

by Hans-Georg Thien

[permalink] [raw]
Subject: Re: [RFC][PATCH] "Disable Trackpad while typing" on Notebooks withh aPS/2 Trackpad

wwp wrote:
> Hi Hans-Georg Thien,
>
>
> On Tue, 27 May 2003 22:47:06 +0200 Hans-Georg Thien <[email protected]>
> wrote:
>
>
>>Hans-Georg Thien wrote:
>
> [snip]
>
>>It it is now possible to adjust some settings via
>>
>> echo ???? > /proc/tty/ps2-trackpad
>>
>>(1) Set the delay time to 2 Secs (default is 10 ==> 1 Sec)
>>
>> echo "delay 20" > /proc/tty/ps2-trackpad
>>
>>
>>(2) Completely disable the trackpad (default 0). Useful if you plug in
>>an external mouse.
>>
>> echo "disable 1" > /proc/tty/ps2-trackpad
>>
>>(3) Escape the keyboard scancode for a key. These scancodes are
>
> [snip]
>
> Sounds good, thanx for your work, guy :-).
> Do you think/know if this patch will be merged to the official tree?
>
I hope, of course ... If you know a way to enforce it - let me know!

2003-09-30 20:51:45

by Hans-Georg Thien

[permalink] [raw]
Subject: [PORT to 2.6.x] "Disable Trackpad while typing" on Notebooks with a PS/2 Trackpad

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I have written a patch against the linux 2.4.x kernel and I want to port
it to the 2.6.x Kernel now.

What it is
- ----------
The trackpad on the MacIntosh iBook notebooks have a feature that
prevents unintended trackpad input while typing on the keyboard. There
are no mouse-moves or mouse-taps for a short period of time after each
keystroke.

I thougt that was a nice-to-have for my i386 notebook and have
implemented it ( with some very important help of other people, namely
Torsten Foertsch ).

This feature is fully configurable via a proc entry.

How it currently works
- ----------------------

In the 2.4.x kernel the handling of keyboard and PS/2 mouse where both
done in linux/drivers/char/pc_keyb.c. So it was easy to apply a patch
without touching other files.

It simply stores a timestamp whenever a key event occurs. If a mouse
event occurs it compares the timestamp of the mouse event with stored
timestamp of the key event. If the delta of these timestamps is less
than a treshold value, than this mouse event is simply discarded. There
where some things more to consider about, but I think you have the idea.

Where I need help now
- ---------------------
Since I do not want to touch the keyboard driver, I wonder if there is
better way to get the timestamp when the last keyboard event occured?

Maybe a function call, a callback function where I can register to the
be notified when a event occurs, a global accessible variable, a proc
entry or something like that.

Any ideas ?

- - Hans

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (MingW32)

iD8DBQE/eezq2xSpXPjN/jsRAgyAAJ9djvaiYsgiR4pOf4GRJ2xNKCUa5QCdFreB
4/iOjaoS+3XX0dL8DFGEaJk=
=zh+9
-----END PGP SIGNATURE-----