Commit aac0e012 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/vojtech/input

into home.osdl.org:/home/torvalds/v2.5/linux
parents 157e3d70 0736b22a
...@@ -788,6 +788,10 @@ running once the system is up. ...@@ -788,6 +788,10 @@ running once the system is up.
psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions psmouse_noext [HW,MOUSE] Disable probing for PS2 mouse protocol extensions
psmouse_resetafter=
[HW,MOUSE] Try to reset Synaptics Touchpad after so many
bad packets (0 = never).
pss= [HW,OSS] Personal Sound System (ECHO ESC614) pss= [HW,OSS] Personal Sound System (ECHO ESC614)
Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq> Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
......
...@@ -205,7 +205,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode) ...@@ -205,7 +205,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
INPUT_KEYCODE(dev, scancode) = keycode; INPUT_KEYCODE(dev, scancode) = keycode;
for (i = 0; i < dev->keycodemax; i++) for (i = 0; i < dev->keycodemax; i++)
if(INPUT_KEYCODE(dev, scancode) == oldkey) if(keycode == oldkey)
break; break;
if (i == dev->keycodemax) if (i == dev->keycodemax)
clear_bit(oldkey, dev->keybit); clear_bit(oldkey, dev->keybit);
......
...@@ -208,7 +208,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -208,7 +208,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct evdev *evdev = list->evdev; struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev; struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs; struct input_absinfo abs;
int i, t, u; int i, t, u, v;
if (!evdev->exist) return -ENODEV; if (!evdev->exist) return -ENODEV;
...@@ -239,14 +239,12 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -239,14 +239,12 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCSKEYCODE: case EVIOCSKEYCODE:
if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (get_user(t, ((int *) arg) + 0)) return -EFAULT;
if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
if (get_user(v, ((int *) arg) + 1)) return -EFAULT;
u = INPUT_KEYCODE(dev, t); u = INPUT_KEYCODE(dev, t);
if (get_user(INPUT_KEYCODE(dev, t), ((int *) arg) + 1)) return -EFAULT; INPUT_KEYCODE(dev, t) = v;
for (i = 0; i < dev->keycodemax; i++) if (v == u) break;
for (i = 0; i < dev->keycodemax; i++)
if(INPUT_KEYCODE(dev, t) == u) break;
if (i == dev->keycodemax) clear_bit(u, dev->keybit); if (i == dev->keycodemax) clear_bit(u, dev->keybit);
set_bit(INPUT_KEYCODE(dev, t), dev->keybit); set_bit(v, dev->keybit);
return 0; return 0;
case EVIOCSFF: case EVIOCSFF:
......
...@@ -426,8 +426,10 @@ void input_register_device(struct input_dev *dev) ...@@ -426,8 +426,10 @@ void input_register_device(struct input_dev *dev)
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; if (!dev->rep[REP_DELAY])
dev->rep[REP_PERIOD] = HZ/33; dev->rep[REP_DELAY] = HZ/4;
if (!dev->rep[REP_PERIOD])
dev->rep[REP_PERIOD] = HZ/33;
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);
......
This diff is collapsed.
...@@ -166,8 +166,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, ...@@ -166,8 +166,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
iforce->expect_packet = 0; iforce->expect_packet = 0;
iforce->ecmd = cmd; iforce->ecmd = cmd;
memcpy(iforce->edata, data, IFORCE_MAX_LENGTH); memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
if (waitqueue_active(&iforce->wait)) wake_up(&iforce->wait);
wake_up(&iforce->wait);
} }
#endif #endif
...@@ -264,7 +263,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet) ...@@ -264,7 +263,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait); add_wait_queue(&iforce->wait, &wait);
if (usb_submit_urb(iforce->ctrl, GFP_KERNEL)) { if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait); remove_wait_queue(&iforce->wait, &wait);
return -1; return -1;
......
...@@ -116,8 +116,7 @@ static void iforce_usb_out(struct urb *urb, struct pt_regs *regs) ...@@ -116,8 +116,7 @@ static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
iforce_usb_xmit(iforce); iforce_usb_xmit(iforce);
if (waitqueue_active(&iforce->wait)) wake_up(&iforce->wait);
wake_up(&iforce->wait);
} }
static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs) static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
...@@ -125,8 +124,7 @@ static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs) ...@@ -125,8 +124,7 @@ static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
struct iforce *iforce = urb->context; struct iforce *iforce = urb->context;
if (urb->status) return; if (urb->status) return;
iforce->ecmd = 0xff00 | urb->actual_length; iforce->ecmd = 0xff00 | urb->actual_length;
if (waitqueue_active(&iforce->wait)) wake_up(&iforce->wait);
wake_up(&iforce->wait);
} }
static int iforce_usb_probe(struct usb_interface *intf, static int iforce_usb_probe(struct usb_interface *intf,
......
...@@ -13,7 +13,8 @@ config INPUT_KEYBOARD ...@@ -13,7 +13,8 @@ config INPUT_KEYBOARD
config KEYBOARD_ATKBD config KEYBOARD_ATKBD
tristate "AT keyboard support" if EMBEDDED || !X86 tristate "AT keyboard support" if EMBEDDED || !X86
default y default y if INPUT=y && INPUT_KEYBOARD=y && SERIO=y
default m
depends on INPUT && INPUT_KEYBOARD && SERIO depends on INPUT && INPUT_KEYBOARD && SERIO
help help
Say Y here if you want to use a standard AT or PS/2 keyboard. Usually Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/timer.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
...@@ -40,8 +41,8 @@ static int atkbd_reset = 1; ...@@ -40,8 +41,8 @@ static int atkbd_reset = 1;
static unsigned char atkbd_set2_keycode[512] = { static unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85, 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41, 85,
0, 56, 42,182, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90, 0, 56, 42,182, 29, 16, 2, 89, 0, 0, 44, 31, 30, 17, 3, 90,
0, 46, 45, 32, 18, 5, 4, 91, 0, 57, 47, 33, 20, 19, 6, 0, 0, 46, 45, 32, 18, 5, 4, 91, 90, 57, 47, 33, 20, 19, 6, 0,
0, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0, 91, 49, 48, 35, 34, 21, 7, 0, 0, 0, 50, 36, 22, 8, 9, 0,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0, 122, 89, 40,120, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 0,
85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121, 0,123, 85, 86, 90, 91, 92, 93, 14, 94, 95, 79,183, 75, 71,121, 0,123,
...@@ -87,10 +88,10 @@ static unsigned char atkbd_set3_keycode[512] = { ...@@ -87,10 +88,10 @@ static unsigned char atkbd_set3_keycode[512] = {
#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 0x02f2
#define ATKBD_CMD_SETREP 0x10f3
#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 0x02ff #define ATKBD_CMD_RESET_BAT 0x02ff
#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
#define ATKBD_CMD_EX_SETLEDS 0x20eb #define ATKBD_CMD_EX_SETLEDS 0x20eb
...@@ -114,12 +115,14 @@ struct atkbd { ...@@ -114,12 +115,14 @@ struct atkbd {
unsigned char keycode[512]; unsigned char keycode[512];
struct input_dev dev; struct input_dev dev;
struct serio *serio; struct serio *serio;
struct timer_list timer;
char name[64]; char name[64];
char phys[32]; char phys[32];
unsigned char cmdbuf[4]; unsigned char cmdbuf[4];
unsigned char cmdcnt; unsigned char cmdcnt;
unsigned char set; unsigned char set;
unsigned char release; unsigned char release;
int lastkey;
volatile signed char ack; volatile signed char ack;
unsigned char emul; unsigned char emul;
unsigned short id; unsigned short id;
...@@ -142,6 +145,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -142,6 +145,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags); printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
#endif #endif
#if !defined(__i386__) && !defined (__x86_64__)
if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && 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);
...@@ -151,6 +155,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -151,6 +155,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (!flags) if (!flags)
atkbd->resend = 0; atkbd->resend = 0;
#endif
switch (code) { switch (code) {
case ATKBD_RET_ACK: case ATKBD_RET_ACK:
...@@ -195,6 +200,14 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -195,6 +200,14 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd->set, code, serio->phys, atkbd->release ? "released" : "pressed"); atkbd->set, code, serio->phys, atkbd->release ? "released" : "pressed");
break; break;
default: default:
if (!atkbd->release) {
mod_timer(&atkbd->timer,
jiffies + (test_bit(atkbd->keycode[code],
&atkbd->dev.key) ? HZ/33 : HZ/4) + HZ/100);
atkbd->lastkey = atkbd->keycode[code];
}
input_regs(&atkbd->dev, regs); input_regs(&atkbd->dev, regs);
input_report_key(&atkbd->dev, atkbd->keycode[code], !atkbd->release); input_report_key(&atkbd->dev, atkbd->keycode[code], !atkbd->release);
input_sync(&atkbd->dev); input_sync(&atkbd->dev);
...@@ -205,6 +218,13 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -205,6 +218,13 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void atkbd_force_key_up(unsigned long data)
{
struct atkbd *atkbd = (void *) data;
input_report_key(&atkbd->dev, atkbd->lastkey, 0);
input_sync(&atkbd->dev);
}
/* /*
* atkbd_sendbyte() sends a byte to the keyboard, and waits for * atkbd_sendbyte() sends a byte to the keyboard, and waits for
* acknowledge. It doesn't handle resends according to the keyboard * acknowledge. It doesn't handle resends according to the keyboard
...@@ -214,7 +234,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, ...@@ -214,7 +234,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte) static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte)
{ {
int timeout = 10000; /* 100 msec */ int timeout = 20000; /* 200 msec */
atkbd->ack = 0; atkbd->ack = 0;
#ifdef ATKBD_DEBUG #ifdef ATKBD_DEBUG
...@@ -322,13 +342,50 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co ...@@ -322,13 +342,50 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
} }
/* /*
* Enable keyboard. * atkbd_probe() probes for an AT keyboard on a serio port.
*/ */
static void atkbd_enable(struct atkbd *atkbd)
static int atkbd_probe(struct atkbd *atkbd)
{ {
if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) unsigned char param[2];
printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
atkbd->serio->phys); /*
* 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_reset)
if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys);
/*
* 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. If a mouse is connected, this
* should make sure we don't try to set the LEDs on it.
*/
if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) {
/*
* If the get ID command failed, we check if we can at least set the LEDs on
* the keyboard. This should work on every keyboard out there. It also turns
* the LEDs off, which we want anyway.
*/
param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
return -1;
atkbd->id = 0xabba;
return 0;
}
if (param[0] != 0xab && param[0] != 0xac)
return -1;
atkbd->id = (param[0] << 8) | param[1];
return 0;
} }
/* /*
...@@ -365,102 +422,56 @@ static int atkbd_set_3(struct atkbd *atkbd) ...@@ -365,102 +422,56 @@ static int atkbd_set_3(struct atkbd *atkbd)
return 4; return 4;
} }
/* if (atkbd_set != 3)
* Try to set the set we want. return 2;
*/
param[0] = atkbd_set; param[0] = 3;
if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET)) if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET))
return 2; return 2;
/*
* Read set number. Beware here. Some keyboards always send '2'
* or some other number regardless into what mode they have been
* attempted to be set. Other keyboards treat the '0' command as
* 'set to set 0', and not 'report current set' as they should.
* In that case we time out, and return 2.
*/
param[0] = 0; param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET)) if (atkbd_command(atkbd, param, ATKBD_CMD_GSCANSET))
return 2; return 2;
/* if (param[0] != 3)
* Here we return the set number the keyboard reports about return 2;
* itself.
*/
return (param[0] == 3) ? 3 : 2; return 3;
} }
/* static int atkbd_enable(struct atkbd *atkbd)
* atkbd_probe() probes for an AT keyboard on a serio port.
*/
static int atkbd_probe(struct atkbd *atkbd)
{ {
unsigned char param[2]; unsigned char param[1];
/*
* 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_reset)
if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
printk(KERN_WARNING
"atkbd.c: keyboard reset failed on %s\n",
atkbd->serio->phys);
/* /*
* Then we check the keyboard ID. We should get 0xab83 under normal conditions. * Set the LEDs to a defined state.
* Some keyboards report different values, but the first byte is always 0xab or
* 0xac. Some old AT keyboards don't report anything.
*/ */
if (atkbd_command(atkbd, param, ATKBD_CMD_GETID)) { param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
return -1;
/* /*
* If the get ID command failed, we check if we can at least set the LEDs on * Set autorepeat to fastest possible.
* the keyboard. This should work on every keyboard out there. It also turns
* the LEDs off, which we want anyway.
*/ */
param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
return -1;
atkbd->id = 0xabba;
return 0;
}
if (param[0] != 0xab && param[0] != 0xac) param[0] = 0;
if (atkbd_command(atkbd, param, ATKBD_CMD_SETREP))
return -1; return -1;
atkbd->id = (param[0] << 8) | param[1];
/* /*
* Set the LEDs to a defined state. * Enable the keyboard to receive keystrokes.
*/ */
param[0] = 0; if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) {
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
atkbd->serio->phys);
return -1; return -1;
}
return 0; return 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.
*
* This command is for scancode set 3 only.
*/
static void atkbd_disable_autorepeat(struct atkbd *atkbd)
{
atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB);
}
/* /*
* atkbd_cleanup() restores the keyboard state so that BIOS is happy after a * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
* reboot. * reboot.
...@@ -485,7 +496,7 @@ static void atkbd_disconnect(struct serio *serio) ...@@ -485,7 +496,7 @@ static void atkbd_disconnect(struct serio *serio)
} }
/* /*
* atkbd_connect() is called when the serio module finds an interface * atkbd_connect() is called when the serio module finds and interface
* that isn't handled yet by an appropriate device driver. We check if * that isn't handled yet by an appropriate device driver. We check if
* there is an AT keyboard out there and if yes, we register ourselves * there is an AT keyboard out there and if yes, we register ourselves
* to the input module. * to the input module.
...@@ -513,6 +524,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -513,6 +524,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
} else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); } else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
atkbd->dev.rep[REP_DELAY] = HZ/4 + HZ/50;
atkbd->dev.rep[REP_PERIOD] = HZ/33;
atkbd->serio = serio; atkbd->serio = serio;
init_input_dev(&atkbd->dev); init_input_dev(&atkbd->dev);
...@@ -525,6 +539,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -525,6 +539,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
serio->private = atkbd; serio->private = atkbd;
init_timer(&atkbd->timer);
atkbd->timer.data = (long) atkbd;
atkbd->timer.function = atkbd_force_key_up;
if (serio_open(serio, dev)) { if (serio_open(serio, dev)) {
kfree(atkbd); kfree(atkbd);
return; return;
...@@ -539,9 +557,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -539,9 +557,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
} }
atkbd->set = atkbd_set_3(atkbd); atkbd->set = atkbd_set_3(atkbd);
if (atkbd->set == 3)
atkbd_disable_autorepeat(atkbd);
atkbd_enable(atkbd); atkbd_enable(atkbd);
} else { } else {
atkbd->set = 2; atkbd->set = 2;
atkbd->id = 0xab00; atkbd->id = 0xab00;
......
...@@ -19,9 +19,7 @@ config MOUSE_PS2 ...@@ -19,9 +19,7 @@ config MOUSE_PS2
Say Y here if you have a PS/2 mouse connected to your system. This Say Y here if you have a PS/2 mouse connected to your system. This
includes the standard 2 or 3-button PS/2 mouse, as well as PS/2 includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
mice with wheels and extra buttons, Microsoft, Logitech or Genius mice with wheels and extra buttons, Microsoft, Logitech or Genius
compatible. Support for Synaptics TouchPads is also included. compatible.
For Synaptics TouchPad support in XFree86 you'll need this XFree86
driver: http://w1.894.telia.com/~u89404340/touchpad/index.html
If unsure, say Y. If unsure, say Y.
...@@ -30,6 +28,22 @@ config MOUSE_PS2 ...@@ -30,6 +28,22 @@ config MOUSE_PS2
The module will be called psmouse. If you want to compile it as a The module will be called psmouse. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://w1.894.telia.com/~u89404340/touchpad/index.html
The gpm program is not yet able to interpret the data from this
driver, so if you need to use the touchpad in the console, you have to
say N for now.
config MOUSE_SERIAL config MOUSE_SERIAL
tristate "Serial mouse" tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE && SERIO depends on INPUT && INPUT_MOUSE && SERIO
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pm.h>
#include "psmouse.h" #include "psmouse.h"
#include "synaptics.h" #include "synaptics.h"
#include "logips2pp.h" #include "logips2pp.h"
...@@ -29,6 +30,8 @@ MODULE_PARM(psmouse_resolution, "i"); ...@@ -29,6 +30,8 @@ MODULE_PARM(psmouse_resolution, "i");
MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi."); MODULE_PARM_DESC(psmouse_resolution, "Resolution, in dpi.");
MODULE_PARM(psmouse_smartscroll, "i"); MODULE_PARM(psmouse_smartscroll, "i");
MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); MODULE_PARM_DESC(psmouse_smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
MODULE_PARM(psmouse_resetafter, "i");
MODULE_PARM_DESC(psmouse_resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define PSMOUSE_LOGITECH_SMARTSCROLL 1 #define PSMOUSE_LOGITECH_SMARTSCROLL 1
...@@ -36,11 +39,12 @@ MODULE_LICENSE("GPL"); ...@@ -36,11 +39,12 @@ MODULE_LICENSE("GPL");
static int psmouse_noext; static int psmouse_noext;
int psmouse_resolution; int psmouse_resolution;
int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL; int psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
unsigned int psmouse_resetafter;
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"}; static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
/* /*
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and * psmouse_process_packet() analyzes the PS/2 mouse packet contents and
* reports relevant events to the input module. * reports relevant events to the input module.
*/ */
...@@ -108,6 +112,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -108,6 +112,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
{ {
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
if (psmouse->state == PSMOUSE_IGNORE)
goto out;
if (psmouse->acking) { if (psmouse->acking) {
switch (data) { switch (data) {
case PSMOUSE_RET_ACK: case PSMOUSE_RET_ACK:
...@@ -132,20 +139,35 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -132,20 +139,35 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
} }
if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
printk(KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n", psmouse->pktcnt); printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
psmouse->name, psmouse->phys, psmouse->pktcnt);
psmouse->pktcnt = 0; psmouse->pktcnt = 0;
} }
psmouse->last = jiffies; psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data; psmouse->packet[psmouse->pktcnt++] = data;
if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
psmouse_process_packet(psmouse, regs); if (psmouse->pktcnt == 1)
psmouse->pktcnt = 0; goto out;
goto out;
if (psmouse->pktcnt == 2) {
if (psmouse->packet[1] == PSMOUSE_RET_ID) {
psmouse->state = PSMOUSE_IGNORE;
serio_rescan(serio);
goto out;
}
if (psmouse->type == PSMOUSE_SYNAPTICS) {
/* neither 0xAA nor 0x00 are valid first bytes
* for a packet in absolute mode
*/
psmouse->pktcnt = 0;
goto out;
}
}
} }
if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) { if (psmouse->type == PSMOUSE_SYNAPTICS) {
/* /*
* The synaptics driver has its own resync logic, * The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time. * so it needs to receive all bytes one at a time.
...@@ -155,8 +177,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -155,8 +177,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out; goto out;
} }
if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) { if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
serio_rescan(serio); psmouse_process_packet(psmouse, regs);
psmouse->pktcnt = 0;
goto out; goto out;
} }
out: out:
...@@ -200,7 +223,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -200,7 +223,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
psmouse->cmdcnt = receive; psmouse->cmdcnt = receive;
if (command == PSMOUSE_CMD_RESET_BAT) if (command == PSMOUSE_CMD_RESET_BAT)
timeout = 2000000; /* 2 sec */ timeout = 4000000; /* 4 sec */
if (command & 0xff) if (command & 0xff)
if (psmouse_sendbyte(psmouse, command & 0xff)) if (psmouse_sendbyte(psmouse, command & 0xff))
...@@ -227,7 +250,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) ...@@ -227,7 +250,7 @@ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
for (i = 0; i < receive; i++) for (i = 0; i < receive; i++)
param[i] = psmouse->cmdbuf[(receive - 1) - i]; param[i] = psmouse->cmdbuf[(receive - 1) - i];
if (psmouse->cmdcnt) if (psmouse->cmdcnt)
return (psmouse->cmdcnt = 0) - 1; return (psmouse->cmdcnt = 0) - 1;
return 0; return 0;
...@@ -450,14 +473,18 @@ static void psmouse_initialize(struct psmouse *psmouse) ...@@ -450,14 +473,18 @@ static void psmouse_initialize(struct psmouse *psmouse)
*/ */
psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM); psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
}
/* /*
* Last, we enable the mouse so that we get reports from it. * psmouse_activate() enables the mouse so that we get motion reports from it.
*/ */
static void psmouse_activate(struct psmouse *psmouse)
{
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys); printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
psmouse->state = PSMOUSE_ACTIVATED;
} }
/* /*
...@@ -478,12 +505,38 @@ static void psmouse_cleanup(struct serio *serio) ...@@ -478,12 +505,38 @@ static void psmouse_cleanup(struct serio *serio)
static void psmouse_disconnect(struct serio *serio) static void psmouse_disconnect(struct serio *serio)
{ {
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
psmouse->state = PSMOUSE_IGNORE;
synaptics_disconnect(psmouse);
input_unregister_device(&psmouse->dev); input_unregister_device(&psmouse->dev);
serio_close(serio); serio_close(serio);
synaptics_disconnect(psmouse);
kfree(psmouse); kfree(psmouse);
} }
/*
* Reinitialize mouse hardware after software suspend.
*/
static int psmouse_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
{
struct psmouse *psmouse = dev->data;
struct serio_dev *ser_dev = psmouse->serio->dev;
synaptics_disconnect(psmouse);
/* We need to reopen the serio port to reinitialize the i8042 controller */
serio_close(psmouse->serio);
serio_open(psmouse->serio, ser_dev);
/* Probe and re-initialize the mouse */
psmouse_probe(psmouse);
psmouse_initialize(psmouse);
synaptics_pt_init(psmouse);
psmouse_activate(psmouse);
return 0;
}
/* /*
* psmouse_connect() is a callback from the serio module when * psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found. * an unhandled serio port is found.
...@@ -492,8 +545,10 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -492,8 +545,10 @@ static void psmouse_disconnect(struct serio *serio)
static void psmouse_connect(struct serio *serio, struct serio_dev *dev) static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
{ {
struct psmouse *psmouse; struct psmouse *psmouse;
struct pm_dev *pmdev;
if ((serio->type & SERIO_TYPE) != SERIO_8042) if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
(serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
return; return;
if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
...@@ -506,6 +561,7 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -506,6 +561,7 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->state = PSMOUSE_NEW_DEVICE;
psmouse->serio = serio; psmouse->serio = serio;
psmouse->dev.private = psmouse; psmouse->dev.private = psmouse;
...@@ -522,6 +578,12 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -522,6 +578,12 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
return; return;
} }
pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
if (pmdev) {
psmouse->dev.pm_dev = pmdev;
pmdev->data = psmouse;
}
sprintf(psmouse->devname, "%s %s %s", sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0", sprintf(psmouse->phys, "%s/input0",
...@@ -539,6 +601,10 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) ...@@ -539,6 +601,10 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
synaptics_pt_init(psmouse);
psmouse_activate(psmouse);
} }
static struct serio_dev psmouse_dev = { static struct serio_dev psmouse_dev = {
...@@ -567,9 +633,16 @@ static int __init psmouse_smartscroll_setup(char *str) ...@@ -567,9 +633,16 @@ static int __init psmouse_smartscroll_setup(char *str)
return 1; return 1;
} }
static int __init psmouse_resetafter_setup(char *str)
{
get_option(&str, &psmouse_resetafter);
return 1;
}
__setup("psmouse_noext", psmouse_noext_setup); __setup("psmouse_noext", psmouse_noext_setup);
__setup("psmouse_resolution=", psmouse_resolution_setup); __setup("psmouse_resolution=", psmouse_resolution_setup);
__setup("psmouse_smartscroll=", psmouse_smartscroll_setup); __setup("psmouse_smartscroll=", psmouse_smartscroll_setup);
__setup("psmouse_resetafter=", psmouse_resetafter_setup);
#endif #endif
......
...@@ -13,9 +13,15 @@ ...@@ -13,9 +13,15 @@
#define PSMOUSE_CMD_RESET_BAT 0x02ff #define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa #define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ID 0x00
#define PSMOUSE_RET_ACK 0xfa #define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe #define PSMOUSE_RET_NAK 0xfe
/* psmouse states */
#define PSMOUSE_NEW_DEVICE 0
#define PSMOUSE_ACTIVATED 1
#define PSMOUSE_IGNORE 2
struct psmouse { struct psmouse {
void *private; void *private;
struct input_dev dev; struct input_dev dev;
...@@ -29,6 +35,7 @@ struct psmouse { ...@@ -29,6 +35,7 @@ struct psmouse {
unsigned char type; unsigned char type;
unsigned char model; unsigned char model;
unsigned long last; unsigned long last;
unsigned char state;
char acking; char acking;
volatile char ack; volatile char ack;
char error; char error;
...@@ -36,16 +43,17 @@ struct psmouse { ...@@ -36,16 +43,17 @@ struct psmouse {
char phys[32]; char phys[32];
}; };
#define PSMOUSE_PS2 1 #define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2 #define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3 #define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4 #define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5 #define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6 #define PSMOUSE_IMEX 6
#define PSMOUSE_SYNAPTICS 7 #define PSMOUSE_SYNAPTICS 7
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
extern int psmouse_smartscroll; extern int psmouse_smartscroll;
extern unsigned int psmouse_resetafter;
#endif /* _PSMOUSE_H */ #endif /* _PSMOUSE_H */
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_init(struct psmouse *psmouse); extern int synaptics_init(struct psmouse *psmouse);
extern int synaptics_pt_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse); extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics queries */ /* synaptics queries */
...@@ -22,12 +23,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse); ...@@ -22,12 +23,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06 #define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09
/* synatics modes */ /* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7) #define SYN_BIT_ABSOLUTE_MODE (1 << 7)
#define SYN_BIT_HIGH_RATE (1 << 6) #define SYN_BIT_HIGH_RATE (1 << 6)
#define SYN_BIT_SLEEP_MODE (1 << 3) #define SYN_BIT_SLEEP_MODE (1 << 3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2) #define SYN_BIT_DISABLE_GESTURE (1 << 2)
#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1)
#define SYN_BIT_W_MODE (1 << 0) #define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */ /* synaptics model ID bits */
...@@ -42,11 +45,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse); ...@@ -42,11 +45,14 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
/* synaptics capability bits */ /* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) #define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) #define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) #define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
/* synaptics modes query bits */ /* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
...@@ -62,6 +68,10 @@ extern void synaptics_disconnect(struct psmouse *psmouse); ...@@ -62,6 +68,10 @@ extern void synaptics_disconnect(struct psmouse *psmouse);
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) #define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47) #define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/* synaptics special commands */
#define SYN_PS_SET_MODE2 0x14
#define SYN_PS_CLIENT_CMD 0x28
/* /*
* A structure to describe the state of the touchpad hardware (buttons and pad) * A structure to describe the state of the touchpad hardware (buttons and pad)
*/ */
...@@ -75,21 +85,28 @@ struct synaptics_hw_state { ...@@ -75,21 +85,28 @@ struct synaptics_hw_state {
int right; int right;
int up; int up;
int down; int down;
int b0;
int b1;
int b2;
int b3;
int b4;
int b5;
int b6;
int b7;
}; };
struct synaptics_data { struct synaptics_data {
/* Data read from the touchpad */ /* Data read from the touchpad */
unsigned long int model_id; /* Model-ID */ unsigned long int model_id; /* Model-ID */
unsigned long int capabilities; /* Capabilities */ unsigned long int capabilities; /* Capabilities */
unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */ unsigned long int identity; /* Identification */
/* Data for normal processing */ /* Data for normal processing */
unsigned char proto_buf[6]; /* Buffer for Packet */ unsigned int out_of_sync; /* # of packets out of sync */
unsigned char last_byte; /* last received byte */
int inSync; /* Packets in sync */
int proto_buf_tail;
int old_w; /* Previous w value */ int old_w; /* Previous w value */
struct serio *ptport; /* pass-through port */
}; };
#endif /* _SYNAPTICS_H */ #endif /* _SYNAPTICS_H */
...@@ -49,7 +49,9 @@ MODULE_LICENSE("GPL"); ...@@ -49,7 +49,9 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(serio_interrupt);
EXPORT_SYMBOL(serio_register_port); EXPORT_SYMBOL(serio_register_port);
EXPORT_SYMBOL(serio_register_slave_port);
EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_unregister_slave_port);
EXPORT_SYMBOL(serio_register_device); EXPORT_SYMBOL(serio_register_device);
EXPORT_SYMBOL(serio_unregister_device); EXPORT_SYMBOL(serio_unregister_device);
EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_open);
...@@ -166,6 +168,17 @@ void serio_register_port(struct serio *serio) ...@@ -166,6 +168,17 @@ void serio_register_port(struct serio *serio)
up(&serio_sem); up(&serio_sem);
} }
/*
* Same as serio_register_port but does not try to acquire serio_sem.
* Should be used when registering a serio from other input device's
* connect() function.
*/
void serio_register_slave_port(struct serio *serio)
{
list_add_tail(&serio->node, &serio_list);
serio_find_dev(serio);
}
void serio_unregister_port(struct serio *serio) void serio_unregister_port(struct serio *serio)
{ {
down(&serio_sem); down(&serio_sem);
...@@ -175,6 +188,18 @@ void serio_unregister_port(struct serio *serio) ...@@ -175,6 +188,18 @@ void serio_unregister_port(struct serio *serio)
up(&serio_sem); up(&serio_sem);
} }
/*
* Same as serio_unregister_port but does not try to acquire serio_sem.
* Should be used when unregistering a serio from other input device's
* disconnect() function.
*/
void serio_unregister_slave_port(struct serio *serio)
{
list_del_init(&serio->node);
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
}
void serio_register_device(struct serio_dev *dev) void serio_register_device(struct serio_dev *dev)
{ {
struct serio *serio; struct serio *serio;
...@@ -204,9 +229,11 @@ void serio_unregister_device(struct serio_dev *dev) ...@@ -204,9 +229,11 @@ void serio_unregister_device(struct serio_dev *dev)
/* called from serio_dev->connect/disconnect methods under serio_sem */ /* called from serio_dev->connect/disconnect methods under serio_sem */
int serio_open(struct serio *serio, struct serio_dev *dev) int serio_open(struct serio *serio, struct serio_dev *dev)
{ {
if (serio->open(serio))
return -1;
serio->dev = dev; serio->dev = dev;
if (serio->open(serio)) {
serio->dev = NULL;
return -1;
}
return 0; return 0;
} }
......
...@@ -751,7 +751,7 @@ struct ff_effect { ...@@ -751,7 +751,7 @@ struct ff_effect {
#define LONG(x) ((x)/BITS_PER_LONG) #define LONG(x) ((x)/BITS_PER_LONG)
#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \ #define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
((dev->keycodesize == 1) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode]))) ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
#define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0) #define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0)
......
...@@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio); ...@@ -65,7 +65,9 @@ void serio_rescan(struct serio *serio);
irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs); irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
void serio_register_port(struct serio *serio); void serio_register_port(struct serio *serio);
void serio_register_slave_port(struct serio *serio);
void serio_unregister_port(struct serio *serio); void serio_unregister_port(struct serio *serio);
void serio_unregister_slave_port(struct serio *serio);
void serio_register_device(struct serio_dev *dev); void serio_register_device(struct serio_dev *dev);
void serio_unregister_device(struct serio_dev *dev); void serio_unregister_device(struct serio_dev *dev);
...@@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(struct serio *serio) ...@@ -104,6 +106,7 @@ static __inline__ void serio_cleanup(struct serio *serio)
#define SERIO_RS232 0x02000000UL #define SERIO_RS232 0x02000000UL
#define SERIO_HIL_MLC 0x03000000UL #define SERIO_HIL_MLC 0x03000000UL
#define SERIO_PC9800 0x04000000UL #define SERIO_PC9800 0x04000000UL
#define SERIO_PS_PSTHRU 0x05000000UL
#define SERIO_PROTO 0xFFUL #define SERIO_PROTO 0xFFUL
#define SERIO_MSC 0x01 #define SERIO_MSC 0x01
......
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