From patchwork Thu Apr 8 11:34:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damjan Jovanovic X-Patchwork-Id: 91251 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o38BYb8d008459 for ; Thu, 8 Apr 2010 11:34:37 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751900Ab0DHLeg (ORCPT ); Thu, 8 Apr 2010 07:34:36 -0400 Received: from mail-qy0-f179.google.com ([209.85.221.179]:62087 "EHLO mail-qy0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751803Ab0DHLef (ORCPT ); Thu, 8 Apr 2010 07:34:35 -0400 Received: by qyk9 with SMTP id 9so2326983qyk.1 for ; Thu, 08 Apr 2010 04:34:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:received:message-id :subject:from:to:cc:content-type; bh=ktLpqVbEJr4yuj3NnxyNAcA+HsgOI6gRvv5hBK7ZESY=; b=TcxEqhkkxe4JIUNpajh1Xuss02chEhsiPikFCwg9xTXynxti9lU7xtNRav1udWeyGz ZhZSfKWMv6qk1XCJ9qA5QB6YVKbsg2ppQ1iDIX95nWK7dxpw8PYzuL7gf5RqZRdM03P5 jTvHhPtv+AtzptMLn73LeuaW1MQCQiPVJZI98= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:cc:content-type; b=cVQ8HLc/gQ18QW899k3MTQGvoML2VgMyVaNl7N+0KlUeZspLTYeLheikM3evdPX2dS CQJQh96cdo4VeFKyrtneM1SqxT0/g1ezVA8AKOQWjlPOsRoxzXCPaC2D55k8MSZgNkXn +3+nzWobx/psDeHf3RS8RUuNogNJ97kC0RUaE= MIME-Version: 1.0 Received: by 10.229.213.14 with HTTP; Thu, 8 Apr 2010 04:34:28 -0700 (PDT) Date: Thu, 8 Apr 2010 13:34:28 +0200 Received: by 10.229.228.83 with SMTP id jd19mr692091qcb.72.1270726469151; Thu, 08 Apr 2010 04:34:29 -0700 (PDT) Message-ID: Subject: [PATCH] input: handle bad parity PS/2 packets in mouse drivers better From: Damjan Jovanovic To: Alessandro Rubini , dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 08 Apr 2010 11:34:37 +0000 (UTC) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7490f1d..82b34b6 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -378,10 +378,16 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) 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; @@ -391,6 +397,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) 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); } @@ -409,7 +417,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) } if (psmouse->pktcnt == 6) { - alps_process_packet(psmouse); + if (!psmouse->badparity) + alps_process_packet(psmouse); return PSMOUSE_FULL_PACKET; } diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b27684f..813dde7 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -324,6 +324,9 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) 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); diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 9169d15..c06439e 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -187,7 +187,8 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) } if (psmouse->pktcnt >= psmouse->pktsize) { - hgpk_process_packet(psmouse); + if (!psmouse->badparity) + hgpk_process_packet(psmouse); return PSMOUSE_FULL_PACKET; } diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 7c1d7d4..e4d1bac 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -138,6 +138,9 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) 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; @@ -166,6 +169,9 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) } } + if (psmouse->badparity) + return PSMOUSE_FULL_PACKET; + if (relative_packet) { if (!dev2) printk(KERN_WARNING "lifebook.c: got relative packet " diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 543c240..7d41ddb 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -51,6 +51,9 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse) * Full packet accumulated, process it */ + if (psmouse->badparity) + return PSMOUSE_FULL_PACKET; + if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) { /* Logitech extended packet */ diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d..8aa033d 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -133,6 +133,9 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) * Full packet accumulated, process it */ + if (psmouse->badparity) + return PSMOUSE_FULL_PACKET; + /* * Scroll wheel on IntelliMice, scroll buttons on NetMice */ @@ -217,6 +220,7 @@ void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, 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; @@ -257,10 +261,12 @@ static int psmouse_handle_byte(struct psmouse *psmouse) 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; @@ -270,6 +276,7 @@ static int psmouse_handle_byte(struct psmouse *psmouse) break; case PSMOUSE_GOOD_DATA: + psmouse->badparity = 0; break; } return 0; @@ -293,8 +300,12 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, 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)) diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd..93ba9df 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -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; diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 81a6b81..0778d84 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -637,6 +637,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) * 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, diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d3f5243..25ec71c 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -534,6 +534,9 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) 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); diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 909431c..12a1e31 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c @@ -59,6 +59,9 @@ static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) 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));