@@ -379,10 +379,16 @@ static psmouse_ret_t alps_process_byte(s
struct alps_data *priv = psmouse->private;
const struct alps_model_info *model = priv->i;
+ if (psmouse->pktcnt == 1 && psmouse->badparity)
+ return PSMOUSE_BAD_DATA;
+
if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
if (psmouse->pktcnt == 3) {
- alps_report_bare_ps2_packet(psmouse, psmouse->packet,
- true);
+ if (psmouse->badparity) {
+ alps_report_bare_ps2_packet(psmouse,
+ psmouse->packet,
+ true);
+ }
return PSMOUSE_FULL_PACKET;
}
return PSMOUSE_GOOD_DATA;
@@ -392,6 +398,8 @@ static psmouse_ret_t alps_process_byte(s
if ((model->flags & ALPS_PS2_INTERLEAVED) &&
psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
+ if (psmouse->badparity)
+ return PSMOUSE_BAD_DATA;
return alps_handle_interleaved_ps2(psmouse);
}
@@ -410,7 +418,8 @@ static psmouse_ret_t alps_process_byte(s
}
if (psmouse->pktcnt == 6) {
- alps_process_packet(psmouse);
+ if (!psmouse->badparity)
+ alps_process_packet(psmouse);
return PSMOUSE_FULL_PACKET;
}
@@ -325,6 +325,9 @@ static psmouse_ret_t elantech_process_by
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
+ if (psmouse->pktcnt == psmouse->pktsize && psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
if (etd->debug > 1)
elantech_packet_dump(psmouse->packet, psmouse->pktsize);
@@ -188,7 +188,8 @@ static psmouse_ret_t hgpk_process_byte(s
}
if (psmouse->pktcnt >= psmouse->pktsize) {
- hgpk_process_packet(psmouse);
+ if (!psmouse->badparity)
+ hgpk_process_packet(psmouse);
return PSMOUSE_FULL_PACKET;
}
@@ -139,6 +139,9 @@ static psmouse_ret_t lifebook_process_by
unsigned char *packet = psmouse->packet;
bool relative_packet = packet[0] & 0x08;
+ if (psmouse->pktcnt == 1 && psmouse->badparity)
+ return PSMOUSE_BAD_DATA;
+
if (relative_packet || !lifebook_use_6byte_proto) {
if (psmouse->pktcnt != 3)
return PSMOUSE_GOOD_DATA;
@@ -167,6 +170,9 @@ static psmouse_ret_t lifebook_process_by
}
}
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
if (relative_packet) {
if (!dev2)
printk(KERN_WARNING "lifebook.c: got relative packet "
@@ -51,6 +51,9 @@ static psmouse_ret_t ps2pp_process_byte(
* Full packet accumulated, process it
*/
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
/* Logitech extended packet */
@@ -134,6 +134,9 @@ static psmouse_ret_t psmouse_process_byt
* Full packet accumulated, process it
*/
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
/*
* Scroll wheel on IntelliMice, scroll buttons on NetMice
*/
@@ -218,6 +221,7 @@ void psmouse_queue_work(struct psmouse *
static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
{
psmouse->state = new_state;
+ psmouse->badparity = 0;
psmouse->pktcnt = psmouse->out_of_sync_cnt = 0;
psmouse->ps2dev.flags = 0;
psmouse->last = jiffies;
@@ -258,10 +262,12 @@ static int psmouse_handle_byte(struct ps
return -1;
}
}
+ psmouse->badparity = 0;
psmouse->pktcnt = 0;
break;
case PSMOUSE_FULL_PACKET:
+ psmouse->badparity = 0;
psmouse->pktcnt = 0;
if (psmouse->out_of_sync_cnt) {
psmouse->out_of_sync_cnt = 0;
@@ -271,6 +277,7 @@ static int psmouse_handle_byte(struct ps
break;
case PSMOUSE_GOOD_DATA:
+ psmouse->badparity = 0;
break;
}
return 0;
@@ -296,8 +303,12 @@ static irqreturn_t psmouse_interrupt(str
printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
flags & SERIO_TIMEOUT ? " timeout" : "",
flags & SERIO_PARITY ? " bad parity" : "");
- ps2_cmd_aborted(&psmouse->ps2dev);
- goto out;
+ if (flags & SERIO_TIMEOUT) {
+ ps2_cmd_aborted(&psmouse->ps2dev);
+ goto out;
+ } else {
+ psmouse->badparity = 1;
+ }
}
if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
@@ -43,6 +43,7 @@ struct psmouse {
char *vendor;
char *name;
unsigned char packet[8];
+ int badparity;
unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
@@ -638,6 +638,9 @@ static psmouse_ret_t fsp_process_byte(st
* Full packet accumulated, process it
*/
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
case FSP_PKT_TYPE_ABS:
dev_warn(&psmouse->ps2dev.serio->dev,
@@ -554,6 +554,9 @@ static psmouse_ret_t synaptics_process_b
struct synaptics_data *priv = psmouse->private;
if (psmouse->pktcnt >= 6) { /* Full packet received */
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
if (unlikely(priv->pkt_type == SYN_NEWABS))
priv->pkt_type = synaptics_detect_pkt_type(psmouse);
@@ -58,6 +58,9 @@ static psmouse_ret_t touchkit_ps2_proces
if (psmouse->pktcnt != 5)
return PSMOUSE_GOOD_DATA;
+ if (psmouse->badparity)
+ return PSMOUSE_FULL_PACKET;
+
input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));