Why the /dev/psaux fix should be included in 2.2.2.

C. Scott Ananian (cananian@lesser-magoo.lcs.mit.edu)
Thu, 4 Feb 1999 22:34:55 -0500 (EST)


I am going to lobby once more briefly for the inclusion of my previously
posted /dev/psaux bugfix into the stable kernel. Take any machine with a
PS/2 port and a 2.2.x kernel. Do:
cat /dev/psaux
[or 'cat /dev/mouse' if /dev/mouse points to /dev/psaux]

A single 0xFA character will show up as soon as you open the device,
before the mouse is moved or anything is done that one would expect to
generate events. This is the ACK to a command sent by the mouse driver.
It should not be user-visible, and no previous stable kernel version has
ever had this behaviour (/dev/psaux spontaneously generating unprompted
characters on open). Thus this is a bug which breaks backwards
compatibility, and should be fixed in a 2.2.x release. This bug kills
mouse-configuration software, who do not expect to see unsolicited ACKs.
gpm ignores it, which is why many people do not see the problem. [You may
have to kill X & gpm before you can see the unsolicited ACK.]

The patch is reposted, attached to this message. It is included in Alan
Cox's kernel patches, but I believe it should be merged into the main
tree, for the reasons discussed above.
--Scott
@ @
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-oOO-(_)-OOo-=-=-=-=-=
C. Scott Ananian: cananian@lcs.mit.edu / Declare the Truth boldly and
Laboratory for Computer Science/Crypto / without hindrance.
Massachusetts Institute of Technology /META-PARRESIAS AKOLUTOS:Acts 28:31
-.-. .-.. .. ..-. ..-. --- .-. -.. ... -.-. --- - - .- -. .- -. .. .- -.
PGP key available via finger and from http://www.pdos.lcs.mit.edu/~cananian

diff -ruHp -X badboys linux/drivers/char-orig/pc_keyb.c linux/drivers/char/pc_keyb.c
--- linux/drivers/char-orig/pc_keyb.c Fri Jan 29 20:26:03 1999
+++ linux/drivers/char/pc_keyb.c Fri Jan 29 22:46:17 1999
@@ -10,6 +10,9 @@
* because they share the same hardware.
* Johan Myreen <jem@iki.fi> 1998-10-08.
*
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ *
*/

#include <linux/config.h>
@@ -74,6 +77,8 @@ static int __init psaux_init(void);

static struct aux_queue *queue; /* Mouse data buffer. */
static int aux_count = 0;
+/* used when we send commands to the mouse that expect an ACK. */
+static volatile unsigned char mouse_reply_expected = 0;

#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
@@ -419,7 +424,10 @@ static unsigned char handle_kbd_event(vo
if (status & KBD_STAT_MOUSE_OBF) {
#ifdef CONFIG_PSMOUSE
/* Mouse data. */
- if (aux_count) {
+ /* Add data to queue unless it's an ACK we were
+ * expecting. */
+ if (aux_count &&
+ (!mouse_reply_expected || scancode!=AUX_ACK)) {
int head = queue->head;
queue->buf[head] = scancode;
add_mouse_randomness(scancode);
@@ -430,7 +438,12 @@ static unsigned char handle_kbd_event(vo
kill_fasync(queue->fasync, SIGIO);
wake_up_interruptible(&queue->proc_list);
}
- }
+ /* if we were expecting an ACK but found
+ * something else, forget about the ACK. */
+ mouse_reply_expected=0;
+ } else if (mouse_reply_expected)
+ /* we found the ACK we were expecting. */
+ mouse_reply_expected--;
#endif
} else {
if (do_acknowledge(scancode))
@@ -770,6 +783,24 @@ static void aux_write_dev(int val)
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}

+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void aux_write_ack(int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ kb_wait();
+ outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+ kb_wait();
+ outb(val, KBD_DATA_REG);
+ /* we expect an ACK in response. */
+ mouse_reply_expected++;
+ kb_wait();
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
static unsigned int get_from_queue(void)
{
unsigned int result;
@@ -834,7 +865,7 @@ static int open_aux(struct inode * inode
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable the
auxiliary port on
controller. */
- aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */

return 0;
@@ -951,11 +982,11 @@ static int __init psaux_init(void)

#ifdef INITIALIZE_MOUSE
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
- aux_write_dev(AUX_SET_SAMPLE);
- aux_write_dev(100); /* 100 samples/sec */
- aux_write_dev(AUX_SET_RES);
- aux_write_dev(3); /* 8 counts per mm */
- aux_write_dev(AUX_SET_SCALE21); /* 2:1 scaling */
+ aux_write_ack(AUX_SET_SAMPLE);
+ aux_write_ack(100); /* 100 samples/sec */
+ aux_write_ack(AUX_SET_RES);
+ aux_write_ack(3); /* 8 counts per mm */
+ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
#endif /* INITIALIZE_MOUSE */
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
diff -ruHp -X badboys linux/drivers/char-orig/pc_keyb.h linux/drivers/char/pc_keyb.h
--- linux/drivers/char-orig/pc_keyb.h Fri Jan 29 20:26:03 1999
+++ linux/drivers/char/pc_keyb.h Fri Jan 29 22:42:24 1999
@@ -115,6 +115,8 @@ extern unsigned char aux_device_present;
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_RESET 0xFF /* Reset aux device */

+#define AUX_ACK 0xFA /* Command byte ACK. */
+
#define AUX_BUF_SIZE 2048

struct aux_queue {
--- linux/CREDITS.orig Fri Jan 29 22:07:15 1999
+++ linux/CREDITS Fri Jan 29 22:08:20 1999
@@ -46,6 +46,7 @@
P: 1024/85AD9EED AD C0 49 08 91 67 DF D7 FA 04 1A EE 09 E8 44 B0
D: Unix98 pty support.
D: APM update to 1.2 spec.
+D: psaux bug-fixes

N: Erik Andersen
E: andersee@debian.org

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/