From patchwork Thu Jan 31 16:22:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 2074371 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 45ABBDF2E5 for ; Thu, 31 Jan 2013 16:24:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755393Ab3AaQXG (ORCPT ); Thu, 31 Jan 2013 11:23:06 -0500 Received: from mail-wg0-f45.google.com ([74.125.82.45]:34305 "EHLO mail-wg0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753695Ab3AaQXB (ORCPT ); Thu, 31 Jan 2013 11:23:01 -0500 Received: by mail-wg0-f45.google.com with SMTP id dq12so2210594wgb.12 for ; Thu, 31 Jan 2013 08:22:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=P8vUd+GCx6m7gKiMm4WhmTR5ZqhAscfF0rx9I/JNQDY=; b=KuLqllrGWRdDkvDH7gWPWAgdb5vj3BQKgQhqWROCTkKL2JpDqL3GiJfJB/yrwBuk8a NIX01oP7Xc6xPziCptqaTVB/VBgIYgBUwtJGil6T4CSu49xgyZc5rdq/Qf+ifksyg3hW meT2JcZPc+T8d7GSxmW/SaVDAnhcaz8S31Iw/TdT98rZ/mcwcmDlREoLOdGdMB+tY2ms 7sUgsd0IoMy+sCfipsIV5GUE9Rfo1zsyVREQIKtuoclTxBHNIqCdk3DiTr2WENi+iQB/ FwX9KQVP5Tqz7coq/qQc180MNp6dHqz35FBdLZini4JyvkwZ2Xry9BBIPvVN8VPpK8cm 0rkQ== X-Received: by 10.180.106.34 with SMTP id gr2mr16016011wib.18.1359649379687; Thu, 31 Jan 2013 08:22:59 -0800 (PST) Received: from localhost.localdomain.com (lan31-8-82-247-176-67.fbx.proxad.net. [82.247.176.67]) by mx.google.com with ESMTPS id ec3sm9846164wib.1.2013.01.31.08.22.57 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 31 Jan 2013 08:22:58 -0800 (PST) From: Benjamin Tissoires To: Benjamin Tissoires , Dmitry Torokhov , Henrik Rydberg , Jiri Kosina , Stephane Chatty , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/9] HID: multitouch: add support for Nexio 42" panel Date: Thu, 31 Jan 2013 17:22:25 +0100 Message-Id: <1359649351-11092-4-git-send-email-benjamin.tissoires@gmail.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1359649351-11092-1-git-send-email-benjamin.tissoires@gmail.com> References: <1359649351-11092-1-git-send-email-benjamin.tissoires@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org This device is the worst device I saw. It keeps TipSwitch and InRange at 1 for fingers that are not touching the panel. The solution is to rely on the field ContactCount, which is accurate as the correct information are packed at the begining of the frame. Unfortunately, CountactCount is most of the time at the end of the report. The solution is to pick it when we have the whole report in raw_event. Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index dad56aa..0935012 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -597,6 +597,9 @@ #define USB_VENDOR_ID_NEC 0x073e #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 +#define USB_VENDOR_ID_NEXIO 0x1870 +#define USB_DEVICE_ID_NEXIO_MULTITOUCH_420 0x010d + #define USB_VENDOR_ID_NEXTWINDOW 0x1926 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 092c09b..c9b8fe5 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -54,6 +54,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_NO_AREA (1 << 9) #define MT_QUIRK_IGNORE_DUPLICATES (1 << 10) #define MT_QUIRK_HOVERING (1 << 11) +#define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) struct mt_slot { __s32 x, y, cx, cy, p, w, h; @@ -83,6 +84,7 @@ struct mt_device { struct mt_class mtclass; /* our mt device class */ struct mt_fields *fields; /* temporary placeholder for storing the multitouch fields */ + __s32 *contactcount; /* contact count value in the report */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ @@ -112,6 +114,7 @@ struct mt_device { #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 #define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 #define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 +#define MT_CLS_ALWAYS_TRUE 0x000a /* vendor specific classes */ #define MT_CLS_3M 0x0101 @@ -171,6 +174,9 @@ static struct mt_class mt_classes[] = { { .name = MT_CLS_INRANGE_CONTACTNUMBER, .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTNUMBER }, + { .name = MT_CLS_ALWAYS_TRUE, + .quirks = MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_CONTACT_CNT_ACCURATE }, /* * vendor specific classes @@ -251,6 +257,9 @@ static ssize_t mt_set_quirks(struct device *dev, td->mtclass.quirks = val; + if (!td->contactcount) + td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; + return count; } @@ -461,6 +470,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, td->last_field_index = field->index; return 1; case HID_DG_CONTACTCOUNT: + td->contactcount = field->value + usage->usage_index; td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: @@ -525,6 +535,10 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input) */ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) { + if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) && + td->num_received >= td->num_expected) + return; + if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) { int slotnum = mt_compute_slot(td, input); struct mt_slot *s = &td->curdata; @@ -635,12 +649,6 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, td->curdata.h = value; break; case HID_DG_CONTACTCOUNT: - /* - * Includes multi-packet support where subsequent - * packets are sent with zero contactcount. - */ - if (value) - td->num_expected = value; break; case HID_DG_TOUCH: /* do nothing */ @@ -676,6 +684,13 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) if (!(hid->claimed & HID_CLAIMED_INPUT)) return; + /* + * Includes multi-packet support where subsequent + * packets are sent with zero contactcount. + */ + if (td->contactcount && *td->contactcount) + td->num_expected = *td->contactcount; + for (r = 0; r < report->maxfield; r++) { field = report->field[r]; count = field->report_count; @@ -750,11 +765,15 @@ static void mt_post_parse_default_settings(struct mt_device *td) static void mt_post_parse(struct mt_device *td) { struct mt_fields *f = td->fields; + struct mt_class *cls = &td->mtclass; if (td->touches_by_report > 0) { int field_count_per_touch = f->length / td->touches_by_report; td->last_slot_field = f->usages[field_count_per_touch - 1]; } + + if (!td->contactcount) + cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; } static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) @@ -1087,6 +1106,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, + /* Nexio panels */ + { .driver_data = MT_CLS_ALWAYS_TRUE, + MT_USB_DEVICE(USB_VENDOR_ID_NEXIO, + USB_DEVICE_ID_NEXIO_MULTITOUCH_420)}, + /* Panasonic panels */ { .driver_data = MT_CLS_PANASONIC, MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,