Commit 0244c60b authored by Vojtech Pavlik's avatar Vojtech Pavlik

Remove uninformative coments in input.c.

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