]> git.neil.brown.name Git - history.git/commitdiff
Remove uninformative coments in input.c.
authorVojtech Pavlik <vojtech@suse.cz>
Wed, 28 Aug 2002 21:48:23 +0000 (23:48 +0200)
committerVojtech Pavlik <vojtech@suse.cz>
Wed, 28 Aug 2002 21:48:23 +0000 (23:48 +0200)
Silence hotplug printk()s in input.c
More careful probe and init in atkbd.c and psmouse.c
to avoid triggering bugs in certain keyboards.
Accept old AT (non PS/2) keyboards with limited command set.
Accept Logitech mice which can only do IMPS/2 and not PS2++.
Use a buffer in i8042.c to avoid spinlock deadlocks when
serio_write is called from within serio_interrupt.
Only ask keyboard to resent if the keyboard is there (ie no timeout).
Linus, this should fix both your keyboard and your mouse!

drivers/input/input.c
drivers/input/keyboard/atkbd.c
drivers/input/mouse/psmouse.c
drivers/input/serio/i8042.c

index 37d3689743bc7a35d73716b2db2f63b64c68dfa7..a1a1d0cd1eace002a38f1c6cd76b6a94b82a178e 100644 (file)
@@ -1,29 +1,13 @@
 /*
- * $Id: input.c,v 1.48 2001/12/26 21:08:33 jsimmons Exp $
+ * The input core
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  The input core
+ * Copyright (c) 1999-2002 Vojtech Pavlik
  */
 
 /*
- * 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; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * 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.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/init.h>
@@ -39,7 +23,7 @@
 #include <linux/poll.h>
 #include <linux/device.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
@@ -337,7 +321,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
        int i = 0, j, value;
 
        if (!hotplug_path[0]) {
-               printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+               printk(KERN_ERR "input.c: calling hotplug without a hotplug agent defined\n");
                return;
        }
        if (in_interrupt()) {
@@ -395,16 +379,20 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
 
        envp[i++] = 0;
 
+#ifdef INPUT_DEBUG
        printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
                argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
+#endif
 
        value = call_usermodehelper(argv [0], argv, envp);
 
        kfree(buf);
        kfree(envp);
 
+#ifdef INPUT_DEBUG
        if (value != 0)
-               printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
+               printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);
+#endif
 }
 
 #endif
@@ -415,31 +403,17 @@ void input_register_device(struct input_dev *dev)
        struct input_handle *handle;
        struct input_device_id *id;
 
-/*
- * Add the EV_SYN capability.
- */
-
        set_bit(EV_SYN, dev->evbit);
 
-/*
- * Initialize repeat timer to default values.
- */
-
        init_timer(&dev->timer);
        dev->timer.data = (long) dev;
        dev->timer.function = input_repeat_key;
        dev->rep[REP_DELAY] = HZ/4;
        dev->rep[REP_PERIOD] = HZ/33;
 
-/*
- * Add the device.
- */
        INIT_LIST_HEAD(&dev->h_list);
        list_add_tail(&dev->node,&input_dev_list);
 
-/*
- * Notify handlers.
- */
        list_for_each(node,&input_handler_list) {
                struct input_handler *handler = to_handler(node);
                if ((id = input_match_device(handler->id_table, dev)))
@@ -447,18 +421,10 @@ void input_register_device(struct input_dev *dev)
                                input_link_handle(handle);
        }
 
-/*
- * Notify the hotplug agent.
- */
-
 #ifdef CONFIG_HOTPLUG
        input_call_hotplug("add", dev);
 #endif
 
-/*
- * Notify /proc.
- */
-
 #ifdef CONFIG_PROC_FS
        input_devices_state++;
        wake_up(&input_devices_poll_wait);
@@ -471,22 +437,11 @@ void input_unregister_device(struct input_dev *dev)
 
        if (!dev) return;
 
-/*
- * Turn off power management for the device.
- */
        if (dev->pm_dev)
                pm_unregister(dev->pm_dev);
 
-/*
- * Kill any pending repeat timers.
- */
-
        del_timer_sync(&dev->timer);
 
-/*
- * Notify handlers.
- */
-
        list_for_each_safe(node,next,&dev->h_list) {
                struct input_handle * handle = to_handle(node);
                list_del_init(&handle->d_node);
@@ -494,23 +449,12 @@ void input_unregister_device(struct input_dev *dev)
                handle->handler->disconnect(handle);
        }
 
-/*
- * Notify the hotplug agent.
- */
-
 #ifdef CONFIG_HOTPLUG
        input_call_hotplug("remove", dev);
 #endif
 
-/*
- * Remove the device.
- */
        list_del_init(&dev->node);
 
-/*
- * Notify /proc.
- */
-
 #ifdef CONFIG_PROC_FS
        input_devices_state++;
        wake_up(&input_devices_poll_wait);
@@ -526,22 +470,12 @@ void input_register_handler(struct input_handler *handler)
        if (!handler) return;
 
        INIT_LIST_HEAD(&handler->h_list);
-/*
- * Add minors if needed.
- */
 
        if (handler->fops != NULL)
                input_table[handler->minor >> 5] = handler;
 
-/*
- * Add the handler.
- */
        list_add_tail(&handler->node,&input_handler_list);
        
-/*
- * Notify it about all existing devices.
- */
-
        list_for_each(node,&input_dev_list) {
                struct input_dev *dev = to_dev(node);
                if ((id = input_match_device(handler->id_table, dev)))
@@ -549,10 +483,6 @@ void input_register_handler(struct input_handler *handler)
                                input_link_handle(handle);
        }
 
-/*
- * Notify /proc.
- */
-
 #ifdef CONFIG_PROC_FS
        input_devices_state++;
        wake_up(&input_devices_poll_wait);
@@ -563,10 +493,6 @@ void input_unregister_handler(struct input_handler *handler)
 {
        struct list_head * node, * next;
 
-
-/*
- * Tell the handler to disconnect from all devices it keeps open.
- */
        list_for_each_safe(node,next,&handler->h_list) {
                struct input_handle * handle = to_handle_h(node);
                list_del_init(&handle->h_node);
@@ -574,21 +500,11 @@ void input_unregister_handler(struct input_handler *handler)
                handler->disconnect(handle);
        }
 
-/*
- * Remove it.
- */
        list_del_init(&handler->node);
 
-/*
- * Remove minors.
- */
        if (handler->fops != NULL)
                input_table[handler->minor >> 5] = NULL;
 
-/*
- * Notify /proc.
- */
-
 #ifdef CONFIG_PROC_FS
        input_devices_state++;
        wake_up(&input_devices_poll_wait);
@@ -644,10 +560,6 @@ void input_unregister_minor(devfs_handle_t handle)
        devfs_unregister(handle);
 }
 
-/*
- * ProcFS interface for the input drivers.
- */
-
 #ifdef CONFIG_PROC_FS
 
 #define SPRINTF_BIT_B(bit, name, max) \
index c1a4781bd9faccad082e93f36f4e869b107793de..5f62532ab71f4f967ff68ae44a772634ab4a2aa9 100644 (file)
@@ -1,27 +1,13 @@
 /*
- * $Id: atkbd.c,v 1.33 2002/02/12 09:34:34 vojtech Exp $
+ * AT and PS/2 keyboard driver
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ * Copyright (c) 1999-2002 Vojtech Pavlik
  */
 
 /*
- * 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; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * 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.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/delay.h>
@@ -33,7 +19,7 @@
 #include <linux/serio.h>
 #include <linux/tqueue.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
 MODULE_PARM(atkbd_set, "1i");
 MODULE_LICENSE("GPL");
@@ -94,9 +80,11 @@ static unsigned char atkbd_set3_keycode[512] = {
 #define ATKBD_CMD_SETLEDS      0x10ed
 #define ATKBD_CMD_GSCANSET     0x11f0
 #define ATKBD_CMD_SSCANSET     0x10f0
-#define ATKBD_CMD_GETID                0x02f2
+#define ATKBD_CMD_GETID                0x01f2
+#define ATKBD_CMD_GETID2       0x0100
 #define ATKBD_CMD_ENABLE       0x00f4
 #define ATKBD_CMD_RESET_DIS    0x00f5
+#define ATKBD_CMD_RESET_BAT    0x01ff
 #define ATKBD_CMD_SETALL_MB    0x00f8
 #define ATKBD_CMD_RESEND       0x00fe
 #define ATKBD_CMD_EX_ENABLE    0x10ea
@@ -147,7 +135,7 @@ static void atkbd_interrupt(struct serio *serio, unsigned char data, unsigned in
 #endif
 
        /* Interface error.  Request that the keyboard resend. */
-       if ((flags & (SERIO_FRAME | SERIO_PARITY)) && atkbd->write) {
+       if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && atkbd->write) {
                printk("atkbd.c: frame/parity error: %02x\n", flags);
                serio_write(serio, ATKBD_CMD_RESEND);
                return;
@@ -360,70 +348,60 @@ static int atkbd_probe(struct atkbd *atkbd)
        unsigned char param[2];
 
 /*
- * Full reset with selftest can on some keyboards be annoyingly slow,
- * so we just do a reset-and-disable on the keyboard, which
- * is considerably faster, but doesn't have to reset everything.
+ * Some systems, where the bit-twiddling when testing the io-lines of the
+ * controller may confuse the keyboard need a full reset of the keyboard. On
+ * these systems the BIOS also usually doesn't do it for us.
  */
 
-       if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_DIS))
+#ifdef CONFIG_KEYBOARD_ATKBD_RESET
+       if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
                printk(KERN_WARNING "atkbd.c: keyboard reset failed\n");
+#endif
 
 /*
- * Next, we check if it's a keyboard. It should send 0xab83
- * (0xab84 on IBM ThinkPad, and 0xaca1 on a NCD Sun layout keyboard,
- * 0xab02 on unxlated i8042 and 0xab03 on unxlated ThinkPad, 0xab7f
- * on Fujitsu Lifebook).
- * If it's a mouse, it'll only send 0x00 (0x03 if it's MS mouse),
- * and we'll time out here, and report an error.
+ * Next we check we can set LEDs on the keyboard. This should work on every
+ * keyboard out there. It also turns the LEDs off, which we want anyway.
  */
 
-       param[0] = param[1] = 0;
-
-       if (atkbd_command(atkbd, param, ATKBD_CMD_GETID))
+       param[0] = 0;
+       if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
                return -1;
 
-       atkbd->id = (param[0] << 8) | param[1];
-
-       if (atkbd->id != 0xab83 && atkbd->id != 0xab84 && atkbd->id != 0xaca1 &&
-           atkbd->id != 0xab7f && atkbd->id != 0xab02 && atkbd->id != 0xab03)
-               printk(KERN_WARNING "atkbd.c: Unusual keyboard ID: %#x on %s\n",
-                       atkbd->id, atkbd->serio->phys);
-
-       return 0;
-}
-
 /*
- * atkbd_initialize() sets the keyboard into a sane state.
+ * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
+ * Some keyboards report different values, but the first byte is always 0xab or
+ * 0xac. Some old AT keyboards don't report anything.
  */
 
-static void atkbd_initialize(struct atkbd *atkbd)
-{
-       unsigned char param;    
+       if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) {
+               atkbd->id = 0xabba;
+               return 0;
+       }
+       if (param[0] != 0xab && param[0] != 0xac)
+               return -1;
+       atkbd->id = param[0] << 8;
+       if (atkbd_command(atkbd, param, ATKBD_CMD_GETID2))
+               return -1;
+       atkbd->id |= param[0];
 
 /*
  * Disable autorepeat. We don't need it, as we do it in software anyway,
- * because that way can get faster repeat, and have less system load
- * (less accesses to the slow ISA hardware). If this fails, we don't care,
- * and will just ignore the repeated keys.
+ * because that way can get faster repeat, and have less system load (less
+ * accesses to the slow ISA hardware). If this fails, we don't care, and will
+ * just ignore the repeated keys.
  */
 
        atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB);
 
 /*
- * We also shut off all the leds. The console code will turn them back on,
- * if needed.
- */
-
-       param = 0;
-       atkbd_command(atkbd, &param, ATKBD_CMD_SETLEDS);
-
-/*
- * Last, we enable the keyboard so that we get keypresses from it.
+ * Last, we enable the keyboard to make sure  that we get keypresses from it.
  */
 
        if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE))
                printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
                        atkbd->serio->phys);
+
+       return 0;
 }
 
 /*
@@ -524,9 +502,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
        input_register_device(&atkbd->dev);
 
        printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
-
-       if (atkbd->write)
-               atkbd_initialize(atkbd);
 }
 
 
index b27d9e505c7721a0bae9eebc5e4e97417b717b60..20adeed4b2fcf8ddda27c415a6e302b7e72a60c5 100644 (file)
@@ -1,27 +1,13 @@
 /*
- * $Id: psmouse.c,v 1.18 2002/03/13 10:03:43 vojtech Exp $
+ * PS/2 mouse driver
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ * Copyright (c) 1999-2002 Vojtech Pavlik
  */
 
 /*
- * 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; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * 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.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/delay.h>
@@ -33,7 +19,7 @@
 #include <linux/init.h>
 #include <linux/tqueue.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("PS/2 mouse driver");
 MODULE_LICENSE("GPL");
 
@@ -43,6 +29,7 @@ MODULE_LICENSE("GPL");
 #define PSMOUSE_CMD_SETSTREAM  0x00ea
 #define PSMOUSE_CMD_POLL       0x03eb  
 #define PSMOUSE_CMD_GETID      0x01f2
+#define PSMOUSE_CMD_GETID2     0x0100
 #define PSMOUSE_CMD_SETRATE    0x10f3
 #define PSMOUSE_CMD_ENABLE     0x00f4
 #define PSMOUSE_CMD_RESET_DIS  0x00f6
@@ -313,7 +300,7 @@ static int psmouse_extensions(struct psmouse *psmouse)
        param[0] = 0;
        psmouse->vendor = "Generic";
        psmouse->name = "Mouse";
-       psmouse->model = 2;
+       psmouse->model = 0;
 
 /*
  * Try Genius NetMouse magic init.
@@ -327,13 +314,13 @@ static int psmouse_extensions(struct psmouse *psmouse)
        psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
 
        if (param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55) {
-               psmouse->vendor = "Genius";
-               psmouse->name = "Mouse";
 
                set_bit(BTN_EXTRA, psmouse->dev.keybit);
                set_bit(BTN_SIDE, psmouse->dev.keybit);
                set_bit(REL_WHEEL, psmouse->dev.relbit);
 
+               psmouse->vendor = "Genius";
+               psmouse->name = "Wheel Mouse";
                return PSMOUSE_GENPS;
        }
 
@@ -356,7 +343,6 @@ static int psmouse_extensions(struct psmouse *psmouse)
                static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
                                                        76, 80, 81, 83, 88, 96, 97, -1 };
                psmouse->vendor = "Logitech";
-               psmouse->name = "Mouse";
                psmouse->model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
 
                if (param[1] < 3)
@@ -367,46 +353,53 @@ static int psmouse_extensions(struct psmouse *psmouse)
                psmouse->type = PSMOUSE_PS2;
 
                for (i = 0; logitech_ps2pp[i] != -1; i++)
-                       if (logitech_ps2pp[i] == psmouse->model) psmouse->type = PSMOUSE_PS2PP;
+                       if (logitech_ps2pp[i] == psmouse->model)
+                               psmouse->type = PSMOUSE_PS2PP;
 
-               if (psmouse->type != PSMOUSE_PS2PP) return PSMOUSE_PS2;
+               if (psmouse->type == PSMOUSE_PS2PP) {
 
-               for (i = 0; logitech_4btn[i] != -1; i++)
-                       if (logitech_4btn[i] == psmouse->model) set_bit(BTN_SIDE, psmouse->dev.keybit);
+                       for (i = 0; logitech_4btn[i] != -1; i++)
+                               if (logitech_4btn[i] == psmouse->model)
+                                       set_bit(BTN_SIDE, psmouse->dev.keybit);
 
-               for (i = 0; logitech_wheel[i] != -1; i++)
-                       if (logitech_wheel[i] == psmouse->model) set_bit(REL_WHEEL, psmouse->dev.relbit);
+                       for (i = 0; logitech_wheel[i] != -1; i++)
+                               if (logitech_wheel[i] == psmouse->model) {
+                                       set_bit(REL_WHEEL, psmouse->dev.relbit);
+                                       psmouse->name = "Wheel Mouse";
+                               }
 
 /*
  * Do Logitech PS2++ / PS2T++ magic init.
  */
 
-               if (psmouse->model == 97) { /* TouchPad 3 */
+                       if (psmouse->model == 97) { /* TouchPad 3 */
 
-                       set_bit(REL_WHEEL, psmouse->dev.relbit);
-                       set_bit(REL_HWHEEL, psmouse->dev.relbit);
+                               set_bit(REL_WHEEL, psmouse->dev.relbit);
+                               set_bit(REL_HWHEEL, psmouse->dev.relbit);
 
-                       param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */
-                       psmouse_command(psmouse, param, 0x30d1);
-                       param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
-                       psmouse_command(psmouse, param, 0x30d1);
-                       param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
-                       psmouse_command(psmouse, param, 0x30d1);
+                               param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */
+                               psmouse_command(psmouse, param, 0x30d1);
+                               param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
+                               psmouse_command(psmouse, param, 0x30d1);
+                               param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
+                               psmouse_command(psmouse, param, 0x30d1);
 
-                       param[0] = 0;
-                       if (!psmouse_command(psmouse, param, 0x13d1) &&
-                               param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14)
-                               return PSMOUSE_PS2TPP;
+                               param[0] = 0;
+                               if (!psmouse_command(psmouse, param, 0x13d1) &&
+                                       param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14)
+                                       return PSMOUSE_PS2TPP;
 
-               } else {
-                       psmouse_ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
-                       psmouse_ps2pp_cmd(psmouse, param, 0xDB);
+                       } else {
+                               param[0] = param[1] = param[2] = 0;
 
-                       if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 &&
-                               (param[2] & 3) == ((param[1] >> 2) & 3))
-                                       return PSMOUSE_PS2PP;
-               }
+                               psmouse_ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
+                               psmouse_ps2pp_cmd(psmouse, param, 0xDB);
 
+                               if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 &&
+                                       (param[2] & 3) == ((param[1] >> 2) & 3))
+                                               return PSMOUSE_PS2PP;
+                       }
+               }
        }
 
 /*
@@ -426,7 +419,7 @@ static int psmouse_extensions(struct psmouse *psmouse)
                set_bit(REL_WHEEL, psmouse->dev.relbit);
 
 /*
- * Try IntelliMouse Explorer magic init.
+ * Try IntelliMouse/Explorer magic init.
  */
 
                param[0] = 200;
@@ -439,29 +432,22 @@ static int psmouse_extensions(struct psmouse *psmouse)
 
                if (param[0] == 4) {
 
-                       psmouse->vendor = "Microsoft";
-                       psmouse->name = "IntelliMouse Explorer";
-
                        set_bit(BTN_SIDE, psmouse->dev.keybit);
                        set_bit(BTN_EXTRA, psmouse->dev.keybit);
 
+                       psmouse->name = "Explorer Mouse";
                        return PSMOUSE_IMEX;
                }
 
-               psmouse->vendor = "Microsoft";
-               psmouse->name = "IntelliMouse";
-
+               psmouse->name = "Wheel Mouse";
                return PSMOUSE_IMPS;
        }
 
 /*
- * Okay, all failed, we have a standard mouse here. The number of the buttons is
- * still a question, though.
+ * Okay, all failed, we have a standard mouse here. The number of the buttons
+ * is still a question, though. We assume 3.
  */
 
-       psmouse->vendor = "Generic";
-       psmouse->name = "Mouse";
-
        return PSMOUSE_PS2;
 }
 
@@ -474,14 +460,7 @@ static int psmouse_probe(struct psmouse *psmouse)
        unsigned char param[2];
 
 /*
- * First we reset and disable the mouse.
- */
-
-       if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
-               return -1;
-
-/*
- * Next, we check if it's a mouse. It should send 0x00 or 0x03
+ * First, we check if it's a mouse. It should send 0x00 or 0x03
  * in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
  */
 
@@ -490,9 +469,21 @@ static int psmouse_probe(struct psmouse *psmouse)
        if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETID))
                return -1;
 
+       if (param[0] == 0xab || param[0] == 0xac) {
+               psmouse_command(psmouse, param, PSMOUSE_CMD_GETID2);
+               return -1;
+       }
+
        if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
                return -1;
 
+/*
+ * Then we reset and disable the mouse so that it doesn't generate events.
+ */
+
+       if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
+               return -1;
+
 /*
  * And here we try to determine if it has any extensions over the
  * basic PS/2 3-button mouse.
@@ -602,9 +593,9 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
        psmouse->dev.name = psmouse->devname;
        psmouse->dev.phys = psmouse->phys;
        psmouse->dev.id.bustype = BUS_I8042;
-       psmouse->dev.id.vendor = psmouse->type;
-       psmouse->dev.id.product = psmouse->model;
-       psmouse->dev.id.version = 0x0100;
+       psmouse->dev.id.vendor = 0x0002;
+       psmouse->dev.id.product = psmouse->type;
+       psmouse->dev.id.version = psmouse->model;
 
        input_register_device(&psmouse->dev);
        
index 1df8d64e8a0077597926809c6a60285e92c3b8a3..6ce58860296560050ce33b83404f222ae33070c5 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "i8042.h"
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
 MODULE_LICENSE("GPL");
 
@@ -347,6 +347,11 @@ static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        unsigned long flags;
        unsigned char str, data;
        unsigned int dfl;
+       struct {
+               int data;
+               int str;
+       } buffer[I8042_BUFFER_SIZE];
+       int i, j = 0;
 
 #ifdef CONFIG_VT
        kbd_pt_regs = regs;
@@ -354,20 +359,31 @@ static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        spin_lock_irqsave(&i8042_lock, flags);
 
-       while ((str = i8042_read_status()) & I8042_STR_OBF) {
+       while (j < I8042_BUFFER_SIZE && 
+           (buffer[j].str = i8042_read_status()) & I8042_STR_OBF)
+               buffer[j++].data = i8042_read_data();
+
+       spin_unlock_irqrestore(&i8042_lock, flags);
+
+       for (i = 0; i < j; i++) {
+
+               str = buffer[i].str;
+               data = buffer[i].data;
 
-               data = i8042_read_data();
                dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
                      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
 
 #ifdef I8042_DEBUG_IO
-               printk(KERN_DEBUG "i8042.c: %02x <- i8042 (interrupt, %s, %d) [%d]\n",
-                       data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, (int) (jiffies - i8042_start));
+               printk(KERN_DEBUG "i8042.c: %02x <- i8042 (interrupt, %s, %d%s%s) [%d]\n",
+                       data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, 
+                       dfl & SERIO_PARITY ? ", bad parity" : "",
+                       dfl & SERIO_TIMEOUT ? ", timeout" : "",
+                       (int) (jiffies - i8042_start));
 #endif
 
-               if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) {
-                       serio_interrupt(&i8042_aux_port, data, dfl);
-               } else {
+               if (i8042_aux_values.exists && (buffer[i].str & I8042_STR_AUXDATA)) {
+                       serio_interrupt(&i8042_aux_port, buffer[i].data, dfl);
+               } else 
                        if (i8042_kbd_values.exists) {
                                if (!i8042_direct) {
                                        if (data > 0x7f) {
@@ -385,10 +401,8 @@ static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                }
                                serio_interrupt(&i8042_kbd_port, data, dfl);
                        }
-               }
        }
 
-       spin_unlock_irqrestore(&i8042_lock, flags);
 }
 
 /*