From: Dmitry Torokhov move "reconnect after so many errors" handling from synaptics driver to psmouse so it can be used by other PS/2 protcol drivers (but so far only synaptics knows how to validate incoming data) --- 25-akpm/Documentation/kernel-parameters.txt | 4 - 25-akpm/drivers/input/mouse/psmouse-base.c | 61 +++++++++++++++++++--------- 25-akpm/drivers/input/mouse/psmouse.h | 9 +++- 25-akpm/drivers/input/mouse/synaptics.c | 24 +++-------- 25-akpm/drivers/input/mouse/synaptics.h | 3 - 5 files changed, 62 insertions(+), 39 deletions(-) diff -puN Documentation/kernel-parameters.txt~new-set-of-input-patches-psmouse-reconnect-after-error Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~new-set-of-input-patches-psmouse-reconnect-after-error 2004-04-27 01:31:50.757332456 -0700 +++ 25-akpm/Documentation/kernel-parameters.txt 2004-04-27 01:31:50.766331088 -0700 @@ -896,8 +896,8 @@ running once the system is up. psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports per second. psmouse.resetafter= - [HW,MOUSE] Try to reset Synaptics Touchpad after so many - bad packets (0 = never). + [HW,MOUSE] Try to reset the device after so many bad packets + (0 = never). psmouse.resolution= [HW,MOUSE] Set desired mouse resolution, in dpi. psmouse.smartscroll= diff -puN drivers/input/mouse/psmouse-base.c~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/psmouse-base.c --- 25/drivers/input/mouse/psmouse-base.c~new-set-of-input-patches-psmouse-reconnect-after-error 2004-04-27 01:31:50.759332152 -0700 +++ 25-akpm/drivers/input/mouse/psmouse-base.c 2004-04-27 01:31:50.768330784 -0700 @@ -43,9 +43,9 @@ int psmouse_smartscroll = 1; module_param_named(smartscroll, psmouse_smartscroll, bool, 0); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); -unsigned int psmouse_resetafter; +static unsigned int psmouse_resetafter; module_param_named(resetafter, psmouse_resetafter, uint, 0); -MODULE_PARM_DESC(resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never)."); +MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); __obsolete_setup("psmouse_noext"); __obsolete_setup("psmouse_resolution="); @@ -56,15 +56,22 @@ __obsolete_setup("psmouse_rate="); static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"}; /* - * psmouse_process_packet() analyzes the PS/2 mouse packet contents and - * reports relevant events to the input module. + * psmouse_process_byte() analyzes the PS/2 data stream and reports + * relevant events to the input module once full packet has arrived. */ -static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs) +static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs) { struct input_dev *dev = &psmouse->dev; unsigned char *packet = psmouse->packet; + if (psmouse->pktcnt < 3 + (psmouse->type >= PSMOUSE_GENPS)) + return PSMOUSE_GOOD_DATA; + +/* + * Full packet accumulated, process it + */ + input_regs(dev, regs); /* @@ -112,6 +119,8 @@ static void psmouse_process_packet(struc input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0); input_sync(dev); + + return PSMOUSE_FULL_PACKET; } /* @@ -123,6 +132,7 @@ static irqreturn_t psmouse_interrupt(str unsigned char data, unsigned int flags, struct pt_regs *regs) { struct psmouse *psmouse = serio->private; + psmouse_ret_t rc; if (psmouse->state == PSMOUSE_IGNORE) goto out; @@ -193,19 +203,33 @@ static irqreturn_t psmouse_interrupt(str } } - if (psmouse->type == PSMOUSE_SYNAPTICS) { - /* - * The synaptics driver has its own resync logic, - * so it needs to receive all bytes one at a time. - */ - synaptics_process_byte(psmouse, regs); - goto out; - } + rc = psmouse->type == PSMOUSE_SYNAPTICS ? + synaptics_process_byte(psmouse, regs) : psmouse_process_byte(psmouse, regs); - if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { - psmouse_process_packet(psmouse, regs); - psmouse->pktcnt = 0; - goto out; + switch (rc) { + case PSMOUSE_BAD_DATA: + printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); + psmouse->pktcnt = 0; + + if (++psmouse->out_of_sync == psmouse_resetafter) { + psmouse->state = PSMOUSE_IGNORE; + printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); + serio_reconnect(psmouse->serio); + } + break; + + case PSMOUSE_FULL_PACKET: + psmouse->pktcnt = 0; + if (psmouse->out_of_sync) { + psmouse->out_of_sync = 0; + printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", + psmouse->name, psmouse->phys); + } + break; + + case PSMOUSE_GOOD_DATA: + break; } out: return IRQ_HANDLED; @@ -677,7 +701,8 @@ static int psmouse_reconnect(struct seri old_type = psmouse->type; psmouse->state = PSMOUSE_CMD_MODE; - psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0; + psmouse->type = psmouse->acking = 0; + psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0; if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) return -1; diff -puN drivers/input/mouse/psmouse.h~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/psmouse.h --- 25/drivers/input/mouse/psmouse.h~new-set-of-input-patches-psmouse-reconnect-after-error 2004-04-27 01:31:50.760332000 -0700 +++ 25-akpm/drivers/input/mouse/psmouse.h 2004-04-27 01:31:50.768330784 -0700 @@ -22,6 +22,13 @@ #define PSMOUSE_ACTIVATED 1 #define PSMOUSE_IGNORE 2 +/* psmouse protocol handler return codes */ +typedef enum { + PSMOUSE_BAD_DATA, + PSMOUSE_GOOD_DATA, + PSMOUSE_FULL_PACKET +} psmouse_ret_t; + struct psmouse; struct psmouse_ptport { @@ -45,6 +52,7 @@ struct psmouse { unsigned char type; unsigned char model; unsigned long last; + unsigned long out_of_sync; unsigned char state; char acking; volatile char ack; @@ -69,6 +77,5 @@ int psmouse_reset(struct psmouse *psmous extern int psmouse_smartscroll; extern unsigned int psmouse_rate; -extern unsigned int psmouse_resetafter; #endif /* _PSMOUSE_H */ diff -puN drivers/input/mouse/synaptics.c~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/synaptics.c --- 25/drivers/input/mouse/synaptics.c~new-set-of-input-patches-psmouse-reconnect-after-error 2004-04-27 01:31:50.762331696 -0700 +++ 25-akpm/drivers/input/mouse/synaptics.c 2004-04-27 01:31:50.769330632 -0700 @@ -599,6 +599,9 @@ static int synaptics_validate_byte(unsig static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; + if (idx < 0 || idx > 4) + return 0; + switch (pkt_type) { case SYN_NEWABS: case SYN_NEWABS_RELAXED: @@ -629,7 +632,7 @@ static unsigned char synaptics_detect_pk return SYN_NEWABS_STRICT; } -void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) +psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) { struct input_dev *dev = &psmouse->dev; struct synaptics_data *priv = psmouse->private; @@ -637,11 +640,6 @@ void synaptics_process_byte(struct psmou input_regs(dev, regs); if (psmouse->pktcnt >= 6) { /* Full packet received */ - if (priv->out_of_sync) { - priv->out_of_sync = 0; - printk(KERN_NOTICE "Synaptics driver resynced.\n"); - } - if (unlikely(priv->pkt_type == SYN_NEWABS)) priv->pkt_type = synaptics_detect_pkt_type(psmouse); @@ -649,16 +647,10 @@ void synaptics_process_byte(struct psmou synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet); else synaptics_process_packet(psmouse); - psmouse->pktcnt = 0; - } else if (psmouse->pktcnt && - !synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type)) { - printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt); - psmouse->pktcnt = 0; - if (++priv->out_of_sync == psmouse_resetafter) { - psmouse->state = PSMOUSE_IGNORE; - printk(KERN_NOTICE "synaptics: issuing reconnect request\n"); - serio_reconnect(psmouse->serio); - } + return PSMOUSE_FULL_PACKET; } + + return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; } diff -puN drivers/input/mouse/synaptics.h~new-set-of-input-patches-psmouse-reconnect-after-error drivers/input/mouse/synaptics.h --- 25/drivers/input/mouse/synaptics.h~new-set-of-input-patches-psmouse-reconnect-after-error 2004-04-27 01:31:50.763331544 -0700 +++ 25-akpm/drivers/input/mouse/synaptics.h 2004-04-27 01:31:50.769330632 -0700 @@ -9,7 +9,7 @@ #ifndef _SYNAPTICS_H #define _SYNAPTICS_H -extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); +extern psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); extern int synaptics_detect(struct psmouse *psmouse); extern int synaptics_init(struct psmouse *psmouse); extern void synaptics_reset(struct psmouse *psmouse); @@ -103,7 +103,6 @@ struct synaptics_data { unsigned long int identity; /* Identification */ /* Data for normal processing */ - unsigned int out_of_sync; /* # of packets out of sync */ int old_w; /* Previous w value */ unsigned char pkt_type; /* packet type - old, new, etc */ }; _