From patchwork Sun Aug 26 12:57:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Henrik Rydberg X-Patchwork-Id: 1375141 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 325353FC71 for ; Sun, 26 Aug 2012 12:57:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754484Ab2HZM5L (ORCPT ); Sun, 26 Aug 2012 08:57:11 -0400 Received: from smtprelay-b22.telenor.se ([195.54.99.213]:44568 "EHLO smtprelay-b22.telenor.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753321Ab2HZMxc (ORCPT ); Sun, 26 Aug 2012 08:53:32 -0400 Received: from ipb3.telenor.se (ipb3.telenor.se [195.54.127.166]) by smtprelay-b22.telenor.se (Postfix) with ESMTP id F1824C951; Sun, 26 Aug 2012 14:53:30 +0200 (CEST) X-SENDER-IP: [85.230.170.20] X-LISTENER: [smtp.bredband.net] X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApRZALMbOlBV5qoUPGdsb2JhbABFhRqFI7AtGQEBAQEeGQ0ngiEBBScvEwEPEAhJOQoUBgESiBG7SRSSBQObQI0P X-IronPort-AV: E=Sophos;i="4.77,830,1336341600"; d="scan'208";a="180869197" Received: from c-14aae655.710-13-64736c12.cust.bredbandsbolaget.se (HELO polaris) ([85.230.170.20]) by ipb3.telenor.se with SMTP; 26 Aug 2012 14:53:29 +0200 Received: by polaris (sSMTP sendmail emulation); Sun, 26 Aug 2012 14:58:47 +0200 From: "Henrik Rydberg" To: Dmitry Torokhov , Jiri Kosina Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Henrik Rydberg , Ping Cheng , Benjamin Tissoires Subject: [PATCH v2 10/20] Input: MT - Handle frame synchronization in core Date: Sun, 26 Aug 2012 14:57:28 +0200 Message-Id: <1345985858-445-11-git-send-email-rydberg@euromail.se> X-Mailer: git-send-email 1.7.12 In-Reply-To: <1345985858-445-1-git-send-email-rydberg@euromail.se> References: <1345985858-445-1-git-send-email-rydberg@euromail.se> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Most MT drivers perform the same actions on frame synchronization. Some actions, like dropping unseen contacts, are also unnecessarily complex. Collect common frame synchronization tasks in a new function, input_mt_sync_frame(). Depending on the flags set, it drops unseen contacts and performs pointer emulation. With init flags and frame synchronization in place, most MT drivers can be simplified. First out are the bcm5974 and hid-multitouch drivers, following this patch. Cc: Ping Cheng Cc: Benjamin Tissoires Signed-off-by: Henrik Rydberg --- drivers/input/input-mt.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/input/mt.h | 9 +++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index bbb3304..564be99 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -14,6 +14,14 @@ #define TRKID_SGN ((TRKID_MAX + 1) >> 1) +static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) +{ + if (dev->absinfo && test_bit(src, dev->absbit)) { + dev->absinfo[dst] = dev->absinfo[src]; + dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); + } +} + /** * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking @@ -45,6 +53,28 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); + if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) { + __set_bit(EV_KEY, dev->evbit); + __set_bit(BTN_TOUCH, dev->keybit); + + copy_abs(dev, ABS_X, ABS_MT_POSITION_X); + copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y); + copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE); + } + if (flags & INPUT_MT_POINTER) { + __set_bit(BTN_TOOL_FINGER, dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); + if (num_slots >= 3) + __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); + if (num_slots >= 4) + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); + if (num_slots >= 5) + __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); + __set_bit(INPUT_PROP_POINTER, dev->propbit); + } + if (flags & INPUT_MT_DIRECT) + __set_bit(INPUT_PROP_DIRECT, dev->propbit); + /* Mark slots as 'unused' */ for (i = 0; i < num_slots; i++) input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); @@ -87,12 +117,17 @@ void input_mt_report_slot_state(struct input_dev *dev, struct input_mt_slot *slot; int id; - if (!mt || !active) { + if (!mt) + return; + + slot = &mt->slots[input_abs_get_val(dev, ABS_MT_SLOT)]; + slot->frame = mt->frame; + + if (!active) { input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); return; } - slot = &mt->slots[input_abs_get_val(dev, ABS_MT_SLOT)]; id = input_mt_get_value(slot, ABS_MT_TRACKING_ID); if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type) id = input_mt_new_trkid(mt); @@ -177,3 +212,34 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) } } EXPORT_SYMBOL(input_mt_report_pointer_emulation); + +/** + * input_mt_sync_frame() - synchronize mt frame + * @dev: input device with allocated MT slots + * + * Close the frame and prepare the internal state for a new one. + * Depending on the flags, marks unused slots as inactive and performs + * pointer emulation. + */ +void input_mt_sync_frame(struct input_dev *dev) +{ + struct input_mt *mt = dev->mt; + struct input_mt_slot *s; + + if (!mt) + return; + + if (mt->flags & INPUT_MT_DROP_UNUSED) { + for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { + if (s->frame == mt->frame) + continue; + input_mt_slot(dev, s - mt->slots); + input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); + } + } + + input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER)); + + mt->frame++; +} +EXPORT_SYMBOL(input_mt_sync_frame); diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 03c52ce..a11d485 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -15,12 +15,17 @@ #define TRKID_MAX 0xffff +#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */ +#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */ +#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */ /** * struct input_mt_slot - represents the state of an input MT slot * @abs: holds current values of ABS_MT axes for this slot + * @frame: last frame at which input_mt_report_slot_state() was called */ struct input_mt_slot { int abs[ABS_MT_LAST - ABS_MT_FIRST + 1]; + unsigned int frame; }; /** @@ -28,12 +33,14 @@ struct input_mt_slot { * @trkid: stores MT tracking ID for the next contact * @num_slots: number of MT slots the device uses * @flags: input_mt operation flags + * @frame: increases every time input_mt_sync_frame() is called * @slots: array of slots holding current values of tracked contacts */ struct input_mt { int trkid; int num_slots; unsigned int flags; + unsigned int frame; struct input_mt_slot slots[]; }; @@ -79,4 +86,6 @@ void input_mt_report_slot_state(struct input_dev *dev, void input_mt_report_finger_count(struct input_dev *dev, int count); void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); +void input_mt_sync_frame(struct input_dev *dev); + #endif