From patchwork Tue Apr 13 11:29:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damjan Jovanovic X-Patchwork-Id: 92161 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 o3DBTRDM023102 for ; Tue, 13 Apr 2010 11:29:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753143Ab0DML30 (ORCPT ); Tue, 13 Apr 2010 07:29:26 -0400 Received: from mail-qy0-f201.google.com ([209.85.221.201]:40477 "EHLO mail-qy0-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753021Ab0DML3Z (ORCPT ); Tue, 13 Apr 2010 07:29:25 -0400 Received: by qyk39 with SMTP id 39so6053444qyk.24 for ; Tue, 13 Apr 2010 04:29:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:received:message-id:subject:from:to:cc:content-type; bh=x9dIbgHnJS7mDitoYqHa1Z4dxmcNZkQZUYSpbJmF9JE=; b=tWCCuhI5Y4pQ1MdXa8dg1393Hb08uOnL4wi55KRf1xiNC2i4lF2KxpFffKz5ZSYW74 WUjufB3uLGLykKP5eQ+OB97HwF7UMnAYjSHCc0fjrUR0gmlURJqHmYpkQiVUFeygdN2W F2DHpEav/Ys667VlMpVoABQKONi3sJ/VuBzJU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=CieiH50fdZN6laUTDrJzQ3aSTFz6rsgIFlIAf8pW/OuJLfwCQwyzdCnXBF5+PX6/Y5 LmXLx/NWhtDo3mq1lZ/u6NmQPlqvfejJuGaBJECAo/bH80GFQOX0X1/746F0TreokYgt t2TIhyPg8pSST6roHiLTA7E7HFhONemt3f+60= MIME-Version: 1.0 Received: by 10.229.213.14 with HTTP; Tue, 13 Apr 2010 04:29:20 -0700 (PDT) In-Reply-To: References: Date: Tue, 13 Apr 2010 13:29:20 +0200 Received: by 10.229.228.3 with SMTP id jc3mr7277087qcb.83.1271158160581; Tue, 13 Apr 2010 04:29:20 -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-kernel@vger.kernel.org, linux-input@vger.kernel.org, akpm@linux-foundation.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]); Tue, 13 Apr 2010 11:29:28 +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));