PS/2 Intellimouse Patch

Michael Funk (root@uncc.campus.mci.net)
Sat, 26 Jul 1997 02:07:21 -0400 (EDT)


This is a patch for drivers/char/psaux.c, 2.1.47. I'd appreciate any
input or comments. The patch gives users a couple of options if they
happen to be stuck with the Microsoft Intellimouse (the mutant mouse
with the little wheel in place of the third button), of the PS/2
persuasion. The reason this is kernel code is firstly, that the
mouse needs to be initialized before the wheel will do anything.
Prior to initialization it behaves like a standard 2-button PS/2
mouse. To initialize, set the sampling rate to 200, then 100, then
80 (weird, huh?). Afterwards, it generates 4 bytes per mouse event
rather than 3. Clicking the wheel is just like a middle-button click,
and turning the wheel modifies the 4th byte (0x01 or 0xff, depending
on the direction it was turned in). #defining INTELLIMOUSE will modify
psaux_init() to initialize the mouse properly.

The other modification is to aux_interrupt(). Since gpm, AccelX, etc.
have no idea how to talk to this guy, #defining INTELLIMOUSE_EMULATE_PS2
will cause aux_interrupt() to drop every 4th byte read rather than stick
it into the queue. Turning the wheel does nothing, but at least you can
use it as a 3-button mouse.

It might be stated that this monstrosity :) doesn't deserve kernel code,
but consider the reason I wrote it. I was helping the admin at my school
set up a new CS lab, all Linux boxes. We were stuck with 40 Gateway
machines that shipped with these mice, and had to use AccelX for support
of the graphics boards they came with. Buying 40 new mice wasn't an
option. I'm sure there are others in similar situations.

I didn't reverse-engineer it, just wrote the code. It was the guy who
wrote the PS/2 driver for FreeBSD (Kazutaka Yokota) who figured out how
to initialize it. Anyway, here it is, any suggestions are most welcome.

------------------8<----------------8<-------------8<-------------------
--- /usr/src/linux-2.1.47/drivers/char/psaux.c Fri Jul 25 04:46:52 1997
+++ psaux.c Sat Jul 26 00:43:30 1997
@@ -36,24 +36,6 @@

/* #define INITIALIZE_DEVICE */

-/*
- * The following two #defines are for the PS/2 Intellimouse. The first
- * one (INTELLIMOUSE) initializes the mouse properly. The second one
- * (INTELLIMOUSE_EMULATE_PS2) causes the mouse to behave like a standard
- * 3 button PS/2 mouse; clicking the wheel is just like a middle-button
- * click on a standard mouse, but turning the wheel does nothing.
- */
-
-/* #define INTELLIMOUSE */
-/* #define INTELLIMOUSE_EMULATE_PS2 */
-
-#ifdef INTELLIMOUSE_EMULATE_PS2
-#define INTELLIMOUSE
-#endif
-#ifdef INTELLIMOUSE
-#define INITIALIZE_DEVICE
-#endif
-
#include <linux/module.h>

#include <linux/sched.h>
@@ -231,30 +213,13 @@

static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
-#ifdef INTELLIMOUSE_EMULATE_PS2
- static unsigned int called = 0;
- unsigned char byte;
-#endif /* INTELLIMOUSE_EMULATE_PS2 */
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);

if ((inb(KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
return;

-#ifdef INTELLIMOUSE_EMULATE_PS2
- /* Discard every 4th byte for proper emulation. */
- byte = inb(KBD_DATA_REG);
- called++;
-
- if(!(called % 4)) {
- called = 0;
- return;
- }
-
- add_mouse_randomness(queue->buf[head] = byte);
-#else /* INTELLIMOUSE_EMULATE_PS2 */
add_mouse_randomness(queue->buf[head] = inb(KBD_DATA_REG));
-#endif /* INTELLIMOUSE_EMULATE_PS2 */
if (head != maxhead) {
head++;
head &= AUX_BUF_SIZE-1;
@@ -660,14 +625,6 @@
aux_write_ack(AUX_SET_RES);
aux_write_ack(3); /* 8 counts per mm */
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
-#ifdef INTELLIMOUSE
- aux_write_ack(AUX_SET_SAMPLE);
- aux_write_ack(200);
- aux_write_ack(AUX_SET_SAMPLE);
- aux_write_ack(100);
- aux_write_ack(AUX_SET_SAMPLE);
- aux_write_ack(80);
-#endif /* INTELLIMOUSE */
poll_aux_status_nosleep();
#endif /* INITIALIZE_DEVICE */
outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */
------------------8<----------------8<-------------8<-------------------

Michael Funk
<mwfunk@uncc.campus.mci.net>
<mwfunk@uncc.edu>