linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 v3 00/20] Input and HID updates for 3.7
@ 2012-09-01 19:46 Henrik Rydberg
  2012-09-01 19:46 ` [PATCH v3 01/20] Input: Break out MT data Henrik Rydberg
                   ` (20 more replies)
  0 siblings, 21 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Hi Dmitry, Jiri,

Here is the third version of the patchset for 3.7. I think we are
getting close. Changes in short:

Patch 2: Folded the size estimate removal into this patch, since the
other estimates are still needed for MT-A devices.

Patch 5: Reworked to handle SYN_MT events the 'old' way.
Patch 10: Reworked to allow for a proper device-to-slot mapping.
Patch 15: Remove the old size estimate when converting to MT-B.

Patch 18: New patch, carefully perform finalization per input device.
Patch 19: Shortened version of touch state removal.

Patch 20: New patch, fixing a long-standing bug for devices capable of
more than ten touches.

Several bugs removed, thanks to everyone involved in finding
those. The set has been more thoroughly tested, but still needs
further scrutiny from Benjamin.

Thanks,
Henrik

Henrik Rydberg (20):
  Input: Break out MT data
  Input: Improve the events-per-packet estimate
  Input: Make sure we follow all EV_KEY events
  Input: Move autorepeat to the event-passing phase
  Input: Send events one packet at a time
  Input: evdev - Add the events() callback
  Input: MT - Add flags to input_mt_init_slots()
  Input: MT - Handle frame synchronization in core
  Input: MT - Add in-kernel tracking
  Input: MT - Get slot by key
  Input: bcm5974 - only setup button urb for TYPE1 devices
  Input: bcm5974 - Preparatory renames
  Input: bcm5974 - Drop pressure and width emulation
  Input: bcm5974 - Drop the logical dimensions
  Input: bcm5974 - Convert to MT-B
  HID: Only dump input if someone is listening
  HID: Add an input configured notification callback
  HID: hid-multitouch: Simplify setup and frame synchronization
  HID: hid-multitouch: Remove the redundant touch state
  HID: hid-multitouch: Add missing contact count detection

 drivers/hid/hid-core.c                   |   3 +-
 drivers/hid/hid-input.c                  |  11 +-
 drivers/hid/hid-magicmouse.c             |   2 +-
 drivers/hid/hid-multitouch.c             | 157 ++++++---------
 drivers/input/evdev.c                    |  78 +++++---
 drivers/input/input-mt.c                 | 294 +++++++++++++++++++++++++---
 drivers/input/input.c                    | 245 ++++++++++++++++--------
 drivers/input/misc/uinput.c              |   2 +-
 drivers/input/mouse/alps.c               |   2 +-
 drivers/input/mouse/bcm5974.c            | 317 ++++++++++++-------------------
 drivers/input/mouse/elantech.c           |   4 +-
 drivers/input/mouse/sentelic.c           |   2 +-
 drivers/input/mouse/synaptics.c          |   4 +-
 drivers/input/tablet/wacom_wac.c         |   6 +-
 drivers/input/touchscreen/atmel_mxt_ts.c |   2 +-
 drivers/input/touchscreen/cyttsp_core.c  |   2 +-
 drivers/input/touchscreen/edt-ft5x06.c   |   2 +-
 drivers/input/touchscreen/egalax_ts.c    |   2 +-
 drivers/input/touchscreen/ili210x.c      |   2 +-
 drivers/input/touchscreen/mms114.c       |   2 +-
 drivers/input/touchscreen/penmount.c     |   2 +-
 drivers/input/touchscreen/wacom_w8001.c  |   2 +-
 include/linux/hid.h                      |   3 +
 include/linux/input.h                    |  33 +++-
 include/linux/input/mt.h                 |  55 +++++-
 25 files changed, 778 insertions(+), 456 deletions(-)

-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 01/20] Input: Break out MT data
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
@ 2012-09-01 19:46 ` Henrik Rydberg
  2012-09-13  5:15   ` Dmitry Torokhov
  2012-09-01 19:46 ` [PATCH v3 02/20] Input: Improve the events-per-packet estimate Henrik Rydberg
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Move all MT-related things to a separate place. This saves some
bytes for non-mt input devices, and prepares for new MT features.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/evdev.c    | 10 ++++++----
 drivers/input/input-mt.c | 47 +++++++++++++++++++++++++++--------------------
 drivers/input/input.c    |  9 ++++-----
 include/linux/input.h    |  9 ++-------
 include/linux/input/mt.h | 16 ++++++++++++++--
 5 files changed, 53 insertions(+), 38 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6c58bff..a0692c5 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -653,20 +653,22 @@ static int evdev_handle_mt_request(struct input_dev *dev,
 				   unsigned int size,
 				   int __user *ip)
 {
-	const struct input_mt_slot *mt = dev->mt;
+	const struct input_mt *mt = dev->mt;
 	unsigned int code;
 	int max_slots;
 	int i;
 
 	if (get_user(code, &ip[0]))
 		return -EFAULT;
-	if (!input_is_mt_value(code))
+	if (!mt || !input_is_mt_value(code))
 		return -EINVAL;
 
 	max_slots = (size - sizeof(__u32)) / sizeof(__s32);
-	for (i = 0; i < dev->mtsize && i < max_slots; i++)
-		if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i]))
+	for (i = 0; i < mt->num_slots && i < max_slots; i++) {
+		int value = input_mt_get_value(&mt->slots[i], code);
+		if (put_user(value, &ip[1 + i]))
 			return -EFAULT;
+	}
 
 	return 0;
 }
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 70a16c7..c6df704 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -27,26 +27,28 @@
  */
 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
 {
+	struct input_mt *mt = dev->mt;
 	int i;
 
 	if (!num_slots)
 		return 0;
-	if (dev->mt)
-		return dev->mtsize != num_slots ? -EINVAL : 0;
+	if (mt)
+		return mt->num_slots != num_slots ? -EINVAL : 0;
 
-	dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
-	if (!dev->mt)
+	mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
+	if (!mt)
 		return -ENOMEM;
 
-	dev->mtsize = num_slots;
+	mt->num_slots = 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);
 	input_set_events_per_packet(dev, 6 * num_slots);
 
 	/* Mark slots as 'unused' */
 	for (i = 0; i < num_slots; i++)
-		input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
+		input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
 
+	dev->mt = mt;
 	return 0;
 }
 EXPORT_SYMBOL(input_mt_init_slots);
@@ -62,9 +64,7 @@ void input_mt_destroy_slots(struct input_dev *dev)
 {
 	kfree(dev->mt);
 	dev->mt = NULL;
-	dev->mtsize = 0;
 	dev->slot = 0;
-	dev->trkid = 0;
 }
 EXPORT_SYMBOL(input_mt_destroy_slots);
 
@@ -83,18 +83,19 @@ EXPORT_SYMBOL(input_mt_destroy_slots);
 void input_mt_report_slot_state(struct input_dev *dev,
 				unsigned int tool_type, bool active)
 {
-	struct input_mt_slot *mt;
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *slot;
 	int id;
 
-	if (!dev->mt || !active) {
+	if (!mt || !active) {
 		input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
 		return;
 	}
 
-	mt = &dev->mt[dev->slot];
-	id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
-	if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
-		id = input_mt_new_trkid(dev);
+	slot = &mt->slots[dev->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);
 
 	input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
 	input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
@@ -135,13 +136,19 @@ EXPORT_SYMBOL(input_mt_report_finger_count);
  */
 void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 {
-	struct input_mt_slot *oldest = NULL;
-	int oldid = dev->trkid;
-	int count = 0;
-	int i;
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *oldest;
+	int oldid, count, i;
+
+	if (!mt)
+		return;
+
+	oldest = 0;
+	oldid = mt->trkid;
+	count = 0;
 
-	for (i = 0; i < dev->mtsize; ++i) {
-		struct input_mt_slot *ps = &dev->mt[i];
+	for (i = 0; i < mt->num_slots; ++i) {
+		struct input_mt_slot *ps = &mt->slots[i];
 		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
 
 		if (id < 0)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8921c61..6e90705 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -174,7 +174,7 @@ static int input_handle_abs_event(struct input_dev *dev,
 		 * "Stage" the event; we'll flush it later, when we
 		 * get actual touch data.
 		 */
-		if (*pval >= 0 && *pval < dev->mtsize)
+		if (dev->mt && *pval >= 0 && *pval < dev->mt->num_slots)
 			dev->slot = *pval;
 
 		return INPUT_IGNORE_EVENT;
@@ -185,8 +185,7 @@ static int input_handle_abs_event(struct input_dev *dev,
 	if (!is_mt_event) {
 		pold = &dev->absinfo[code].value;
 	} else if (dev->mt) {
-		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
-		pold = &mtslot->abs[code - ABS_MT_FIRST];
+		pold = &dev->mt->slots[dev->slot].abs[code - ABS_MT_FIRST];
 	} else {
 		/*
 		 * Bypass filtering for multi-touch events when
@@ -1751,8 +1750,8 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
 	int i;
 	unsigned int events;
 
-	if (dev->mtsize) {
-		mt_slots = dev->mtsize;
+	if (dev->mt) {
+		mt_slots = dev->mt->num_slots;
 	} else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
 		mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
 			   dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
diff --git a/include/linux/input.h b/include/linux/input.h
index 725dcd0..76d6788 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1203,11 +1203,8 @@ struct ff_effect {
  *	software autorepeat
  * @timer: timer for software autorepeat
  * @rep: current values for autorepeat parameters (delay, rate)
- * @mt: pointer to array of struct input_mt_slot holding current values
- *	of tracked contacts
- * @mtsize: number of MT slots the device uses
+ * @mt: pointer to multitouch state
  * @slot: MT slot currently being transmitted
- * @trkid: stores MT tracking ID for the current contact
  * @absinfo: array of &struct input_absinfo elements holding information
  *	about absolute axes (current value, min, max, flat, fuzz,
  *	resolution)
@@ -1287,10 +1284,8 @@ struct input_dev {
 
 	int rep[REP_CNT];
 
-	struct input_mt_slot *mt;
-	int mtsize;
+	struct input_mt *mt;
 	int slot;
-	int trkid;
 
 	struct input_absinfo *absinfo;
 
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index f867375..4ae275c 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -23,6 +23,18 @@ struct input_mt_slot {
 	int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
 };
 
+/**
+ * struct input_mt - state of tracked contacts
+ * @trkid: stores MT tracking ID for the next contact
+ * @num_slots: number of MT slots the device uses
+ * @slots: array of slots holding current values of tracked contacts
+ */
+struct input_mt {
+	int trkid;
+	int num_slots;
+	struct input_mt_slot slots[];
+};
+
 static inline void input_mt_set_value(struct input_mt_slot *slot,
 				      unsigned code, int value)
 {
@@ -38,9 +50,9 @@ static inline int input_mt_get_value(const struct input_mt_slot *slot,
 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
 void input_mt_destroy_slots(struct input_dev *dev);
 
-static inline int input_mt_new_trkid(struct input_dev *dev)
+static inline int input_mt_new_trkid(struct input_mt *mt)
 {
-	return dev->trkid++ & TRKID_MAX;
+	return mt->trkid++ & TRKID_MAX;
 }
 
 static inline void input_mt_slot(struct input_dev *dev, int slot)
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 02/20] Input: Improve the events-per-packet estimate
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
  2012-09-01 19:46 ` [PATCH v3 01/20] Input: Break out MT data Henrik Rydberg
@ 2012-09-01 19:46 ` Henrik Rydberg
  2012-09-13  5:16   ` Dmitry Torokhov
  2012-09-01 19:46 ` [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events Henrik Rydberg
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

The events-per-packet estimate has so far been used by MT devices
only. This patch adjusts the packet buffer size to also accomodate the
KEY and MSC events.  Keyboards normally send one or two keys at a
time. MT devices normally send a number of button keys along with the
MT information.  The buffer size chosen here covers those cases, and
matches the default buffer size in evdev. Since the input estimate is
now preferred, remove the special input-mt estimate.

Reviewed-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input-mt.c |  1 -
 drivers/input/input.c    | 10 +++++++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index c6df704..58bde77 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -42,7 +42,6 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
 	mt->num_slots = 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);
-	input_set_events_per_packet(dev, 6 * num_slots);
 
 	/* Mark slots as 'unused' */
 	for (i = 0; i < num_slots; i++)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 6e90705..8ebf116 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1777,6 +1777,9 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
 		if (test_bit(i, dev->relbit))
 			events++;
 
+	/* Make room for KEY and MSC events */
+	events += 7;
+
 	return events;
 }
 
@@ -1815,6 +1818,7 @@ int input_register_device(struct input_dev *dev)
 {
 	static atomic_t input_no = ATOMIC_INIT(0);
 	struct input_handler *handler;
+	unsigned int packet_size;
 	const char *path;
 	int error;
 
@@ -1827,9 +1831,9 @@ int input_register_device(struct input_dev *dev)
 	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
 	input_cleanse_bitmasks(dev);
 
-	if (!dev->hint_events_per_packet)
-		dev->hint_events_per_packet =
-				input_estimate_events_per_packet(dev);
+	packet_size = input_estimate_events_per_packet(dev);
+	if (dev->hint_events_per_packet < packet_size)
+		dev->hint_events_per_packet = packet_size;
 
 	/*
 	 * If delay and period are pre-set by the driver, then autorepeating
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
  2012-09-01 19:46 ` [PATCH v3 01/20] Input: Break out MT data Henrik Rydberg
  2012-09-01 19:46 ` [PATCH v3 02/20] Input: Improve the events-per-packet estimate Henrik Rydberg
@ 2012-09-01 19:46 ` Henrik Rydberg
  2012-09-13  5:19   ` Dmitry Torokhov
  2012-09-01 19:46 ` [PATCH v3 04/20] Input: Move autorepeat to the event-passing phase Henrik Rydberg
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

For some EV_KEY types, sending a larger-than-one value causes the
input state to oscillate. This patch makes sure this cannot happen,
clearing up the autorepeat bypass logic in the process.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8ebf116..4d64500 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -239,24 +239,30 @@ static void input_handle_event(struct input_dev *dev,
 		break;
 
 	case EV_KEY:
-		if (is_event_supported(code, dev->keybit, KEY_MAX) &&
-		    !!test_bit(code, dev->key) != value) {
+		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
+
+			/* auto-repeat bypasses state updates */
+			if (value == 2) {
+				disposition = INPUT_PASS_TO_HANDLERS;
+				break;
+			}
+
+			if (!!test_bit(code, dev->key) != !!value) {
 
-			if (value != 2) {
 				__change_bit(code, dev->key);
+				disposition = INPUT_PASS_TO_HANDLERS;
+
 				if (value)
 					input_start_autorepeat(dev, code);
 				else
 					input_stop_autorepeat(dev);
 			}
-
-			disposition = INPUT_PASS_TO_HANDLERS;
 		}
 		break;
 
 	case EV_SW:
 		if (is_event_supported(code, dev->swbit, SW_MAX) &&
-		    !!test_bit(code, dev->sw) != value) {
+		    !!test_bit(code, dev->sw) != !!value) {
 
 			__change_bit(code, dev->sw);
 			disposition = INPUT_PASS_TO_HANDLERS;
@@ -283,7 +289,7 @@ static void input_handle_event(struct input_dev *dev,
 
 	case EV_LED:
 		if (is_event_supported(code, dev->ledbit, LED_MAX) &&
-		    !!test_bit(code, dev->led) != value) {
+		    !!test_bit(code, dev->led) != !!value) {
 
 			__change_bit(code, dev->led);
 			disposition = INPUT_PASS_TO_ALL;
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 04/20] Input: Move autorepeat to the event-passing phase
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (2 preceding siblings ...)
  2012-09-01 19:46 ` [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events Henrik Rydberg
@ 2012-09-01 19:46 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 05/20] Input: Send events one packet at a time Henrik Rydberg
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:46 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Preparing to split event filtering and event passing, move the
autorepeat function to the point where the event is actually passed.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input.c | 46 +++++++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4d64500..a57c4a5 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -69,6 +69,22 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
 	return value;
 }
 
+static void input_start_autorepeat(struct input_dev *dev, int code)
+{
+	if (test_bit(EV_REP, dev->evbit) &&
+	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
+	    dev->timer.data) {
+		dev->repeat_key = code;
+		mod_timer(&dev->timer,
+			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
+	}
+}
+
+static void input_stop_autorepeat(struct input_dev *dev)
+{
+	del_timer(&dev->timer);
+}
+
 /*
  * Pass event first through all filters and then, if event has not been
  * filtered out, through all open handles. This function is called with
@@ -105,6 +121,15 @@ static void input_pass_event(struct input_dev *dev,
 	}
 
 	rcu_read_unlock();
+
+	/* trigger auto repeat for key events */
+	if (type == EV_KEY && value != 2) {
+		if (value)
+			input_start_autorepeat(dev, code);
+		else
+			input_stop_autorepeat(dev);
+	}
+
 }
 
 /*
@@ -142,22 +167,6 @@ static void input_repeat_key(unsigned long data)
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void input_start_autorepeat(struct input_dev *dev, int code)
-{
-	if (test_bit(EV_REP, dev->evbit) &&
-	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
-	    dev->timer.data) {
-		dev->repeat_key = code;
-		mod_timer(&dev->timer,
-			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
-	}
-}
-
-static void input_stop_autorepeat(struct input_dev *dev)
-{
-	del_timer(&dev->timer);
-}
-
 #define INPUT_IGNORE_EVENT	0
 #define INPUT_PASS_TO_HANDLERS	1
 #define INPUT_PASS_TO_DEVICE	2
@@ -251,11 +260,6 @@ static void input_handle_event(struct input_dev *dev,
 
 				__change_bit(code, dev->key);
 				disposition = INPUT_PASS_TO_HANDLERS;
-
-				if (value)
-					input_start_autorepeat(dev, code);
-				else
-					input_stop_autorepeat(dev);
 			}
 		}
 		break;
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 05/20] Input: Send events one packet at a time
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (3 preceding siblings ...)
  2012-09-01 19:46 ` [PATCH v3 04/20] Input: Move autorepeat to the event-passing phase Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-13  6:56   ` Dmitry Torokhov
  2012-09-01 19:47 ` [PATCH v3 06/20] Input: evdev - Add the events() callback Henrik Rydberg
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

On heavy event loads, such as a multitouch driver, the irqsoff latency
can be as high as 250 us.  By accumulating a frame worth of data
before passing it on, the latency can be dramatically reduced.  As a
side effect, the special EV_SYN handling can be removed, since the
frame is now atomic.

This patch adds the events() handler callback and uses it if it
exists. The latency is improved by 50 us even without the callback.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input.c | 176 +++++++++++++++++++++++++++++++++++---------------
 include/linux/input.h |  24 ++++++-
 2 files changed, 144 insertions(+), 56 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index a57c4a5..5b66b2f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex);
 
 static struct input_handler *input_table[8];
 
+static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
+
 static inline int is_event_supported(unsigned int code,
 				     unsigned long *bm, unsigned int max)
 {
@@ -90,46 +92,81 @@ static void input_stop_autorepeat(struct input_dev *dev)
  * filtered out, through all open handles. This function is called with
  * dev->event_lock held and interrupts disabled.
  */
-static void input_pass_event(struct input_dev *dev,
-			     unsigned int type, unsigned int code, int value)
+static unsigned int input_to_handler(struct input_handle *handle,
+			struct input_value *vals, unsigned int count)
 {
-	struct input_handler *handler;
-	struct input_handle *handle;
+	struct input_handler *handler = handle->handler;
+	struct input_value *end = vals;
+	struct input_value *v;
 
-	rcu_read_lock();
+	for (v = vals; v != vals + count; v++) {
+		if (handler->filter &&
+		    handler->filter(handle, v->type, v->code, v->value))
+			continue;
+		if (end != v)
+			*end = *v;
+		end++;
+	}
 
-	handle = rcu_dereference(dev->grab);
-	if (handle)
-		handle->handler->event(handle, type, code, value);
-	else {
-		bool filtered = false;
+	count = end - vals;
+	if (!count)
+		return 0;
 
-		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
-			if (!handle->open)
-				continue;
+	if (handler->events)
+		handler->events(handle, vals, count);
+	else
+		for (v = vals; v != end; v++)
+			handler->event(handle, v->type, v->code, v->value);
+
+	return count;
+}
 
-			handler = handle->handler;
-			if (!handler->filter) {
-				if (filtered)
-					break;
+/*
+ * Pass values first through all filters and then, if event has not been
+ * filtered out, through all open handles. This function is called with
+ * dev->event_lock held and interrupts disabled.
+ */
+static void input_pass_values(struct input_dev *dev,
+			      struct input_value *vals, unsigned int count)
+{
+	struct input_handle *handle;
+	struct input_value *v;
 
-				handler->event(handle, type, code, value);
+	if (!count)
+		return;
 
-			} else if (handler->filter(handle, type, code, value))
-				filtered = true;
-		}
+	rcu_read_lock();
+
+	handle = rcu_dereference(dev->grab);
+	if (handle) {
+		count = input_to_handler(handle, vals, count);
+	} else {
+		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+			if (handle->open)
+				count = input_to_handler(handle, vals, count);
 	}
 
 	rcu_read_unlock();
 
+	add_input_randomness(vals->type, vals->code, vals->value);
+
 	/* trigger auto repeat for key events */
-	if (type == EV_KEY && value != 2) {
-		if (value)
-			input_start_autorepeat(dev, code);
-		else
-			input_stop_autorepeat(dev);
+	for (v = vals; v != vals + count; v++) {
+		if (v->type == EV_KEY && v->value != 2) {
+			if (v->value)
+				input_start_autorepeat(dev, v->code);
+			else
+				input_stop_autorepeat(dev);
+		}
 	}
+}
+
+static void input_pass_event(struct input_dev *dev,
+			     unsigned int type, unsigned int code, int value)
+{
+	struct input_value vals[] = { { type, code, value } };
 
+	input_pass_values(dev, vals, ARRAY_SIZE(vals));
 }
 
 /*
@@ -146,18 +183,12 @@ static void input_repeat_key(unsigned long data)
 
 	if (test_bit(dev->repeat_key, dev->key) &&
 	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
+		struct input_value vals[] =  {
+			{ EV_KEY, dev->repeat_key, 2 },
+			input_value_sync
+		};
 
-		input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
-
-		if (dev->sync) {
-			/*
-			 * Only send SYN_REPORT if we are not in a middle
-			 * of driver parsing a new hardware packet.
-			 * Otherwise assume that the driver will send
-			 * SYN_REPORT once it's done.
-			 */
-			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
-		}
+		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 
 		if (dev->rep[REP_PERIOD])
 			mod_timer(&dev->timer, jiffies +
@@ -170,6 +201,8 @@ static void input_repeat_key(unsigned long data)
 #define INPUT_IGNORE_EVENT	0
 #define INPUT_PASS_TO_HANDLERS	1
 #define INPUT_PASS_TO_DEVICE	2
+#define INPUT_SLOT		4
+#define INPUT_FLUSH		8
 #define INPUT_PASS_TO_ALL	(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
 
 static int input_handle_abs_event(struct input_dev *dev,
@@ -215,14 +248,14 @@ static int input_handle_abs_event(struct input_dev *dev,
 	/* Flush pending "slot" event */
 	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
 		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
-		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
+		return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
 	}
 
 	return INPUT_PASS_TO_HANDLERS;
 }
 
-static void input_handle_event(struct input_dev *dev,
-			       unsigned int type, unsigned int code, int value)
+static int input_get_disposition(struct input_dev *dev,
+			  unsigned int type, unsigned int code, int value)
 {
 	int disposition = INPUT_IGNORE_EVENT;
 
@@ -235,13 +268,9 @@ static void input_handle_event(struct input_dev *dev,
 			break;
 
 		case SYN_REPORT:
-			if (!dev->sync) {
-				dev->sync = true;
-				disposition = INPUT_PASS_TO_HANDLERS;
-			}
+			disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH;
 			break;
 		case SYN_MT_REPORT:
-			dev->sync = false;
 			disposition = INPUT_PASS_TO_HANDLERS;
 			break;
 		}
@@ -326,14 +355,48 @@ static void input_handle_event(struct input_dev *dev,
 		break;
 	}
 
-	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
-		dev->sync = false;
+	return disposition;
+}
+
+static void input_handle_event(struct input_dev *dev,
+			       unsigned int type, unsigned int code, int value)
+{
+	int disposition;
+
+	disposition = input_get_disposition(dev, type, code, value);
 
 	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
 		dev->event(dev, type, code, value);
 
-	if (disposition & INPUT_PASS_TO_HANDLERS)
-		input_pass_event(dev, type, code, value);
+	if (!dev->vals)
+		return;
+
+	if (disposition & INPUT_PASS_TO_HANDLERS) {
+		struct input_value *v;
+
+		if (disposition & INPUT_SLOT) {
+			v = &dev->vals[dev->num_vals++];
+			v->type = EV_ABS;
+			v->code = ABS_MT_SLOT;
+			v->value = dev->slot;
+		}
+
+		v = &dev->vals[dev->num_vals++];
+		v->type = type;
+		v->code = code;
+		v->value = value;
+	}
+
+	if (disposition & INPUT_FLUSH) {
+		if (dev->num_vals >= 2)
+			input_pass_values(dev, dev->vals, dev->num_vals);
+		dev->num_vals = 0;
+	} else if (dev->num_vals >= dev->max_vals - 2) {
+		dev->vals[dev->num_vals++] = input_value_sync;
+		input_pass_values(dev, dev->vals, dev->num_vals);
+		dev->num_vals = 0;
+	}
+
 }
 
 /**
@@ -361,7 +424,6 @@ void input_event(struct input_dev *dev,
 	if (is_event_supported(type, dev->evbit, EV_MAX)) {
 
 		spin_lock_irqsave(&dev->event_lock, flags);
-		add_input_randomness(type, code, value);
 		input_handle_event(dev, type, code, value);
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
@@ -840,10 +902,12 @@ int input_set_keycode(struct input_dev *dev,
 	if (test_bit(EV_KEY, dev->evbit) &&
 	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
 	    __test_and_clear_bit(old_keycode, dev->key)) {
+		struct input_value vals[] =  {
+			{ EV_KEY, old_keycode, 0 },
+			input_value_sync
+		};
 
-		input_pass_event(dev, EV_KEY, old_keycode, 0);
-		if (dev->sync)
-			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 	}
 
  out:
@@ -1425,6 +1489,7 @@ static void input_dev_release(struct device *device)
 	input_ff_destroy(dev);
 	input_mt_destroy_slots(dev);
 	kfree(dev->absinfo);
+	kfree(dev->vals);
 	kfree(dev);
 
 	module_put(THIS_MODULE);
@@ -1845,6 +1910,11 @@ int input_register_device(struct input_dev *dev)
 	if (dev->hint_events_per_packet < packet_size)
 		dev->hint_events_per_packet = packet_size;
 
+	dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
+	dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
+	if (!dev->vals)
+		return -ENOMEM;
+
 	/*
 	 * If delay and period are pre-set by the driver, then autorepeating
 	 * is handled by the driver itself and we don't do it in input.c.
diff --git a/include/linux/input.h b/include/linux/input.h
index 76d6788..797f335 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1169,6 +1169,18 @@ struct ff_effect {
 #include <linux/mod_devicetable.h>
 
 /**
+ * struct input_value - input value representation
+ * @type: type of value (EV_KEY, EV_ABS, etc)
+ * @code: the value code
+ * @value: the value
+ */
+struct input_value {
+	__u16 type;
+	__u16 code;
+	__s32 value;
+};
+
+/**
  * struct input_dev - represents an input device
  * @name: name of the device
  * @phys: physical path to the device in the system hierarchy
@@ -1241,7 +1253,6 @@ struct ff_effect {
  *	last user closes the device
  * @going_away: marks devices that are in a middle of unregistering and
  *	causes input_open_device*() fail with -ENODEV.
- * @sync: set to %true when there were no new events since last EV_SYN
  * @dev: driver model's view of this device
  * @h_list: list of input handles associated with the device. When
  *	accessing the list dev->mutex must be held
@@ -1307,12 +1318,14 @@ struct input_dev {
 	unsigned int users;
 	bool going_away;
 
-	bool sync;
-
 	struct device dev;
 
 	struct list_head	h_list;
 	struct list_head	node;
+
+	unsigned int num_vals;
+	unsigned int max_vals;
+	struct input_value *vals;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
@@ -1373,6 +1386,9 @@ struct input_handle;
  * @event: event handler. This method is being called by input core with
  *	interrupts disabled and dev->event_lock spinlock held and so
  *	it may not sleep
+ * @events: event sequence handler. This method is being called by
+ *	input core with interrupts disabled and dev->event_lock
+ *	spinlock held and so it may not sleep
  * @filter: similar to @event; separates normal event handlers from
  *	"filters".
  * @match: called after comparing device's id with handler's id_table
@@ -1409,6 +1425,8 @@ struct input_handler {
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
+	void (*events)(struct input_handle *handle,
+		       const struct input_value *vals, unsigned int count);
 	bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 	bool (*match)(struct input_handler *handler, struct input_dev *dev);
 	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 06/20] Input: evdev - Add the events() callback
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (4 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 05/20] Input: Send events one packet at a time Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 07/20] Input: MT - Add flags to input_mt_init_slots() Henrik Rydberg
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

By sending a full frame of events at the same time, the irqsoff
latency at heavy load is brought down from 200 us to 100 us.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/evdev.c | 68 +++++++++++++++++++++++++++++++++++----------------
 1 file changed, 47 insertions(+), 21 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a0692c5..118d030 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -54,16 +54,9 @@ struct evdev_client {
 static struct evdev *evdev_table[EVDEV_MINORS];
 static DEFINE_MUTEX(evdev_table_mutex);
 
-static void evdev_pass_event(struct evdev_client *client,
-			     struct input_event *event,
-			     ktime_t mono, ktime_t real)
+static void __pass_event(struct evdev_client *client,
+			 const struct input_event *event)
 {
-	event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
-					mono : real);
-
-	/* Interrupts are disabled, just acquire the lock. */
-	spin_lock(&client->buffer_lock);
-
 	client->buffer[client->head++] = *event;
 	client->head &= client->bufsize - 1;
 
@@ -86,42 +79,74 @@ static void evdev_pass_event(struct evdev_client *client,
 		client->packet_head = client->head;
 		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
+}
+
+static void evdev_pass_values(struct evdev_client *client,
+			const struct input_value *vals, unsigned int count,
+			ktime_t mono, ktime_t real)
+{
+	struct evdev *evdev = client->evdev;
+	const struct input_value *v;
+	struct input_event event;
+	bool wakeup = false;
+
+	event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
+				      mono : real);
+
+	/* Interrupts are disabled, just acquire the lock. */
+	spin_lock(&client->buffer_lock);
+
+	for (v = vals; v != vals + count; v++) {
+		event.type = v->type;
+		event.code = v->code;
+		event.value = v->value;
+		__pass_event(client, &event);
+		if (v->type == EV_SYN && v->code == SYN_REPORT)
+			wakeup = true;
+	}
 
 	spin_unlock(&client->buffer_lock);
+
+	if (wakeup)
+		wake_up_interruptible(&evdev->wait);
 }
 
 /*
- * Pass incoming event to all connected clients.
+ * Pass incoming events to all connected clients.
  */
-static void evdev_event(struct input_handle *handle,
-			unsigned int type, unsigned int code, int value)
+static void evdev_events(struct input_handle *handle,
+			 const struct input_value *vals, unsigned int count)
 {
 	struct evdev *evdev = handle->private;
 	struct evdev_client *client;
-	struct input_event event;
 	ktime_t time_mono, time_real;
 
 	time_mono = ktime_get();
 	time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
 
-	event.type = type;
-	event.code = code;
-	event.value = value;
-
 	rcu_read_lock();
 
 	client = rcu_dereference(evdev->grab);
 
 	if (client)
-		evdev_pass_event(client, &event, time_mono, time_real);
+		evdev_pass_values(client, vals, count, time_mono, time_real);
 	else
 		list_for_each_entry_rcu(client, &evdev->client_list, node)
-			evdev_pass_event(client, &event, time_mono, time_real);
+			evdev_pass_values(client, vals, count,
+					  time_mono, time_real);
 
 	rcu_read_unlock();
+}
 
-	if (type == EV_SYN && code == SYN_REPORT)
-		wake_up_interruptible(&evdev->wait);
+/*
+ * Pass incoming event to all connected clients.
+ */
+static void evdev_event(struct input_handle *handle,
+			unsigned int type, unsigned int code, int value)
+{
+	struct input_value vals[] = { { type, code, value } };
+
+	evdev_events(handle, vals, 1);
 }
 
 static int evdev_fasync(int fd, struct file *file, int on)
@@ -1050,6 +1075,7 @@ MODULE_DEVICE_TABLE(input, evdev_ids);
 
 static struct input_handler evdev_handler = {
 	.event		= evdev_event,
+	.events		= evdev_events,
 	.connect	= evdev_connect,
 	.disconnect	= evdev_disconnect,
 	.fops		= &evdev_fops,
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 07/20] Input: MT - Add flags to input_mt_init_slots()
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (5 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 06/20] Input: evdev - Add the events() callback Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 08/20] Input: MT - Handle frame synchronization in core Henrik Rydberg
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Preparing to move more repeated code into the mt core, add a flags
argument to the input_mt_slots_init() function.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-magicmouse.c             | 2 +-
 drivers/hid/hid-multitouch.c             | 2 +-
 drivers/input/input-mt.c                 | 4 +++-
 drivers/input/misc/uinput.c              | 2 +-
 drivers/input/mouse/alps.c               | 2 +-
 drivers/input/mouse/elantech.c           | 4 ++--
 drivers/input/mouse/sentelic.c           | 2 +-
 drivers/input/mouse/synaptics.c          | 4 ++--
 drivers/input/tablet/wacom_wac.c         | 6 +++---
 drivers/input/touchscreen/atmel_mxt_ts.c | 2 +-
 drivers/input/touchscreen/cyttsp_core.c  | 2 +-
 drivers/input/touchscreen/edt-ft5x06.c   | 2 +-
 drivers/input/touchscreen/egalax_ts.c    | 2 +-
 drivers/input/touchscreen/ili210x.c      | 2 +-
 drivers/input/touchscreen/mms114.c       | 2 +-
 drivers/input/touchscreen/penmount.c     | 2 +-
 drivers/input/touchscreen/wacom_w8001.c  | 2 +-
 include/linux/input/mt.h                 | 5 ++++-
 18 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 7364726..25ddf3e 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -392,7 +392,7 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
 
 	__set_bit(EV_ABS, input->evbit);
 
-	error = input_mt_init_slots(input, 16);
+	error = input_mt_init_slots(input, 16, 0);
 	if (error)
 		return error;
 	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 59c8b5c..c400d90 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -390,7 +390,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		case HID_DG_CONTACTID:
 			if (!td->maxcontacts)
 				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
-			input_mt_init_slots(hi->input, td->maxcontacts);
+			input_mt_init_slots(hi->input, td->maxcontacts, 0);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			td->touches_by_report++;
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 58bde77..7041737 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -25,7 +25,8 @@
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
-int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
+			unsigned int flags)
 {
 	struct input_mt *mt = dev->mt;
 	int i;
@@ -40,6 +41,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
 		return -ENOMEM;
 
 	mt->num_slots = num_slots;
+	mt->flags = flags;
 	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);
 
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 7360568..6b17975 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -405,7 +405,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 			goto exit;
 		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
 			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-			input_mt_init_slots(dev, nslot);
+			input_mt_init_slots(dev, nslot, 0);
 		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
 			input_set_events_per_packet(dev, 60);
 		}
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4a1347e..cf5af1f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1620,7 +1620,7 @@ int alps_init(struct psmouse *psmouse)
 	case ALPS_PROTO_V3:
 	case ALPS_PROTO_V4:
 		set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
-		input_mt_init_slots(dev1, 2);
+		input_mt_init_slots(dev1, 2, 0);
 		input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0);
 		input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0);
 
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 4790110..1e8e42f 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1004,7 +1004,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 					     ETP_WMAX_V2, 0, 0);
 		}
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		break;
@@ -1035,7 +1035,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 				     ETP_WMAX_V2, 0, 0);
 		/* Multitouch capable pad, up to 5 fingers. */
-		input_mt_init_slots(dev, ETP_MAX_FINGERS);
+		input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 3f5649f..b47155d 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -960,7 +960,7 @@ static int fsp_set_input_params(struct psmouse *psmouse)
 
 		input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
 		input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
 	}
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14eaece..37033ad 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1232,7 +1232,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
 	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
 		/* Image sensors can report per-contact pressure */
@@ -1244,7 +1244,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
 		/* Non-image sensors with AGM use semi-mt */
 		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
 	}
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 0020419..5837d07 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1530,7 +1530,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 			__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 			__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
 
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 
 			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			                     0, 255, 0, 0);
@@ -1575,7 +1575,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
 	case TABLETPC2FG:
 		if (features->device_type == BTN_TOOL_FINGER) {
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 			input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
 					0, MT_TOOL_MAX, 0, 0);
 			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
@@ -1631,7 +1631,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
 			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 
 			if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
 				__set_bit(BTN_TOOL_TRIPLETAP,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4623cc6..e92615d 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1152,7 +1152,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
 
 	/* For multi touch */
 	num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
-	error = input_mt_init_slots(input_dev, num_mt_slots);
+	error = input_mt_init_slots(input_dev, num_mt_slots, 0);
 	if (error)
 		goto err_free_object;
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index f030d9e..8e60437 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -571,7 +571,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, CY_MAXZ, 0, 0);
 
-	input_mt_init_slots(input_dev, CY_MAX_ID);
+	input_mt_init_slots(input_dev, CY_MAX_ID, 0);
 
 	error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
 				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 9afc777..7b786e7 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -778,7 +778,7 @@ static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client,
 			     0, tsdata->num_x * 64 - 1, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y,
 			     0, tsdata->num_y * 64 - 1, 0, 0);
-	error = input_mt_init_slots(input, MAX_SUPPORT_POINTS);
+	error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0);
 	if (error) {
 		dev_err(&client->dev, "Unable to init MT slots.\n");
 		goto err_free_mem;
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 70524dd..c1e3460 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -204,7 +204,7 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
 			     ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
 	input_set_abs_params(input_dev,
 			     ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0);
-	input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS);
+	input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0);
 
 	input_set_drvdata(input_dev, ts);
 
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index c004417..4ac6976 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -252,7 +252,7 @@ static int __devinit ili210x_i2c_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
 
 	/* Multi touch */
-	input_mt_init_slots(input, MAX_TOUCHES);
+	input_mt_init_slots(input, MAX_TOUCHES, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
 
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 49c44bb..560cf09 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -404,7 +404,7 @@ static int __devinit mms114_probe(struct i2c_client *client,
 	input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0);
 
 	/* For multi touch */
-	input_mt_init_slots(input_dev, MMS114_MAX_TOUCH);
+	input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, MMS114_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 4ccde45..b49f0b8 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -264,7 +264,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
 	input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
 
 	if (pm->maxcontacts > 1) {
-		input_mt_init_slots(pm->dev, pm->maxcontacts);
+		input_mt_init_slots(pm->dev, pm->maxcontacts, 0);
 		input_set_abs_params(pm->dev,
 				     ABS_MT_POSITION_X, 0, max_x, 0, 0);
 		input_set_abs_params(pm->dev,
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 8f9ad2f..9a83be6 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -471,7 +471,7 @@ static int w8001_setup(struct w8001 *w8001)
 		case 5:
 			w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
 
-			input_mt_init_slots(dev, 2);
+			input_mt_init_slots(dev, 2, 0);
 			input_set_abs_params(dev, ABS_MT_POSITION_X,
 						0, touch.x, 0, 0);
 			input_set_abs_params(dev, ABS_MT_POSITION_Y,
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index 4ae275c..03c52ce 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -27,11 +27,13 @@ struct input_mt_slot {
  * struct input_mt - state of tracked contacts
  * @trkid: stores MT tracking ID for the next contact
  * @num_slots: number of MT slots the device uses
+ * @flags: input_mt operation flags
  * @slots: array of slots holding current values of tracked contacts
  */
 struct input_mt {
 	int trkid;
 	int num_slots;
+	unsigned int flags;
 	struct input_mt_slot slots[];
 };
 
@@ -47,7 +49,8 @@ static inline int input_mt_get_value(const struct input_mt_slot *slot,
 	return slot->abs[code - ABS_MT_FIRST];
 }
 
-int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
+			unsigned int flags);
 void input_mt_destroy_slots(struct input_dev *dev);
 
 static inline int input_mt_new_trkid(struct input_mt *mt)
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 08/20] Input: MT - Handle frame synchronization in core
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (6 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 07/20] Input: MT - Add flags to input_mt_init_slots() Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 09/20] Input: MT - Add in-kernel tracking Henrik Rydberg
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina
  Cc: linux-input, linux-kernel, Henrik Rydberg, Benjamin Tissoires

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: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 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 7041737..769c76d 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);
@@ -88,12 +118,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[dev->slot];
+	slot->frame = mt->frame;
+
+	if (!active) {
 		input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
 		return;
 	}
 
-	slot = &mt->slots[dev->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);
@@ -178,3 +213,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
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 09/20] Input: MT - Add in-kernel tracking
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (7 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 08/20] Input: MT - Handle frame synchronization in core Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 10/20] Input: MT - Get slot by key Henrik Rydberg
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

With the INPUT_MT_TRACK flag set, the function input_mt_assign_slots()
can be used to match a new set of contacts against the currently used
slots. The algorithm used is based on Lagrange relaxation, and performs
very well in practice; slower than mtdev for a few corner cases, but
faster in most commonly occuring cases.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input-mt.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/input/mt.h |  21 +++++++
 2 files changed, 163 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 769c76d..2acf693 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -46,7 +46,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 
 	mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
 	if (!mt)
-		return -ENOMEM;
+		goto err_mem;
 
 	mt->num_slots = num_slots;
 	mt->flags = flags;
@@ -74,6 +74,12 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 	}
 	if (flags & INPUT_MT_DIRECT)
 		__set_bit(INPUT_PROP_DIRECT, dev->propbit);
+	if (flags & INPUT_MT_TRACK) {
+		unsigned int n2 = num_slots * num_slots;
+		mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
+		if (!mt->red)
+			goto err_mem;
+	}
 
 	/* Mark slots as 'unused' */
 	for (i = 0; i < num_slots; i++)
@@ -81,6 +87,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 
 	dev->mt = mt;
 	return 0;
+err_mem:
+	kfree(mt);
+	return -ENOMEM;
 }
 EXPORT_SYMBOL(input_mt_init_slots);
 
@@ -93,7 +102,10 @@ EXPORT_SYMBOL(input_mt_init_slots);
  */
 void input_mt_destroy_slots(struct input_dev *dev)
 {
-	kfree(dev->mt);
+	if (dev->mt) {
+		kfree(dev->mt->red);
+		kfree(dev->mt);
+	}
 	dev->mt = NULL;
 	dev->slot = 0;
 }
@@ -244,3 +256,131 @@ void input_mt_sync_frame(struct input_dev *dev)
 	mt->frame++;
 }
 EXPORT_SYMBOL(input_mt_sync_frame);
+
+static int adjust_dual(int *begin, int step, int *end, int eq)
+{
+	int f, *p, s, c;
+
+	if (begin == end)
+		return 0;
+
+	f = *begin;
+	p = begin + step;
+	s = p == end ? f + 1 : *p;
+
+	for (; p != end; p += step)
+		if (*p < f)
+			s = f, f = *p;
+		else if (*p < s)
+			s = *p;
+
+	c = (f + s + 1) / 2;
+	if (c == 0 || (c > 0 && !eq))
+		return 0;
+	if (s < 0)
+		c *= 2;
+
+	for (p = begin; p != end; p += step)
+		*p -= c;
+
+	return (c < s && s <= 0) || (f >= 0 && f < c);
+}
+
+static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
+{
+	int i, k, sum;
+
+	for (k = 0; k < nrc; k++) {
+		for (i = 0; i < nr; i++)
+			adjust_dual(w + i, nr, w + i + nrc, nr <= nc);
+		sum = 0;
+		for (i = 0; i < nrc; i += nr)
+			sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr);
+		if (!sum)
+			break;
+	}
+}
+
+static int input_mt_set_matrix(struct input_mt *mt,
+			       const struct input_mt_pos *pos, int num_pos)
+{
+	const struct input_mt_pos *p;
+	struct input_mt_slot *s;
+	int *w = mt->red;
+	int x, y;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (!input_mt_is_active(s))
+			continue;
+		x = input_mt_get_value(s, ABS_MT_POSITION_X);
+		y = input_mt_get_value(s, ABS_MT_POSITION_Y);
+		for (p = pos; p != pos + num_pos; p++) {
+			int dx = x - p->x, dy = y - p->y;
+			*w++ = dx * dx + dy * dy;
+		}
+	}
+
+	return w - mt->red;
+}
+
+static void input_mt_set_slots(struct input_mt *mt,
+			       int *slots, int num_pos)
+{
+	struct input_mt_slot *s;
+	int *w = mt->red, *p;
+
+	for (p = slots; p != slots + num_pos; p++)
+		*p = -1;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (!input_mt_is_active(s))
+			continue;
+		for (p = slots; p != slots + num_pos; p++)
+			if (*w++ < 0)
+				*p = s - mt->slots;
+	}
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (input_mt_is_active(s))
+			continue;
+		for (p = slots; p != slots + num_pos; p++)
+			if (*p < 0) {
+				*p = s - mt->slots;
+				break;
+			}
+	}
+}
+
+/**
+ * input_mt_assign_slots() - perform a best-match assignment
+ * @dev: input device with allocated MT slots
+ * @slots: the slot assignment to be filled
+ * @pos: the position array to match
+ * @num_pos: number of positions
+ *
+ * Performs a best match against the current contacts and returns
+ * the slot assignment list. New contacts are assigned to unused
+ * slots.
+ *
+ * Returns zero on success, or negative error in case of failure.
+ */
+int input_mt_assign_slots(struct input_dev *dev, int *slots,
+			  const struct input_mt_pos *pos, int num_pos)
+{
+	struct input_mt *mt = dev->mt;
+	int nrc;
+
+	if (!mt || !mt->red)
+		return -ENXIO;
+	if (num_pos > mt->num_slots)
+		return -EINVAL;
+	if (num_pos < 1)
+		return 0;
+
+	nrc = input_mt_set_matrix(mt, pos, num_pos);
+	find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc);
+	input_mt_set_slots(mt, slots, num_pos);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_mt_assign_slots);
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index a11d485..10bb77c 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -18,6 +18,8 @@
 #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 */
+#define INPUT_MT_TRACK		0x0008	/* use in-kernel tracking */
+
 /**
  * struct input_mt_slot - represents the state of an input MT slot
  * @abs: holds current values of ABS_MT axes for this slot
@@ -34,6 +36,7 @@ struct input_mt_slot {
  * @num_slots: number of MT slots the device uses
  * @flags: input_mt operation flags
  * @frame: increases every time input_mt_sync_frame() is called
+ * @red: reduced cost matrix for in-kernel tracking
  * @slots: array of slots holding current values of tracked contacts
  */
 struct input_mt {
@@ -41,6 +44,7 @@ struct input_mt {
 	int num_slots;
 	unsigned int flags;
 	unsigned int frame;
+	int *red;
 	struct input_mt_slot slots[];
 };
 
@@ -56,6 +60,11 @@ static inline int input_mt_get_value(const struct input_mt_slot *slot,
 	return slot->abs[code - ABS_MT_FIRST];
 }
 
+static inline bool input_mt_is_active(const struct input_mt_slot *slot)
+{
+	return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
+}
+
 int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
 			unsigned int flags);
 void input_mt_destroy_slots(struct input_dev *dev);
@@ -88,4 +97,16 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
 
 void input_mt_sync_frame(struct input_dev *dev);
 
+/**
+ * struct input_mt_pos - contact position
+ * @x: horizontal coordinate
+ * @y: vertical coordinate
+ */
+struct input_mt_pos {
+	s16 x, y;
+};
+
+int input_mt_assign_slots(struct input_dev *dev, int *slots,
+			  const struct input_mt_pos *pos, int num_pos);
+
 #endif
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 10/20] Input: MT - Get slot by key
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (8 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 09/20] Input: MT - Add in-kernel tracking Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 11/20] Input: bcm5974 - only setup button urb for TYPE1 devices Henrik Rydberg
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Some devices use an internal key for tracking which cannot be directly
mapped to slots. This patch provides a key-to-slot mapping, which can
be used by drivers of such devices.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/input-mt.c | 32 ++++++++++++++++++++++++++++++++
 include/linux/input/mt.h |  4 ++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 2acf693..4c0e531 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -384,3 +384,35 @@ int input_mt_assign_slots(struct input_dev *dev, int *slots,
 	return 0;
 }
 EXPORT_SYMBOL(input_mt_assign_slots);
+
+/**
+ * input_mt_get_slot_by_key() - return slot matching key
+ * @dev: input device with allocated MT slots
+ * @key: the key of the sought slot
+ *
+ * Returns the slot of the given key, if it exists, otherwise
+ * set the key on the first unused slot and return.
+ *
+ * If no available slot can be found, -1 is returned.
+ */
+int input_mt_get_slot_by_key(struct input_dev *dev, int key)
+{
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *s;
+
+	if (!mt)
+		return -1;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
+		if (input_mt_is_active(s) && s->key == key)
+			return s - mt->slots;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
+		if (!input_mt_is_active(s)) {
+			s->key = key;
+			return s - mt->slots;
+		}
+
+	return -1;
+}
+EXPORT_SYMBOL(input_mt_get_slot_by_key);
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index 10bb77c..bbdc694 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -24,10 +24,12 @@
  * 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
+ * @key: optional driver designation of this slot
  */
 struct input_mt_slot {
 	int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
 	unsigned int frame;
+	unsigned int key;
 };
 
 /**
@@ -109,4 +111,6 @@ struct input_mt_pos {
 int input_mt_assign_slots(struct input_dev *dev, int *slots,
 			  const struct input_mt_pos *pos, int num_pos);
 
+int input_mt_get_slot_by_key(struct input_dev *dev, int key);
+
 #endif
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 11/20] Input: bcm5974 - only setup button urb for TYPE1 devices
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (9 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 10/20] Input: MT - Get slot by key Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 12/20] Input: bcm5974 - Preparatory renames Henrik Rydberg
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

The early generations with this trackpad used the separate mouse
interface to produce button events. With the introduction of the
button pads, this information was moved to the trackpad interface,
leaving the mouse interface unused. The driver is still setting up
both interfaces, which has not caused any problems - until now.

It turns out that without the CONFIG_USB_EHCI_TT_NEWSCHED option, the
driver may return an ENOSPC upon bt_urb submission, resulting in a
failure to open the device. This happens everytime on the MacBookPro
Retina (and likely on other mid-2012 models), but earlier MacBook
models seem to work fine.

This patch skips the bt_urb setup for TYPE2 devices, which arguably
should have been done in the first place.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/mouse/bcm5974.c | 43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index d528c23..39ac9ff 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -742,9 +742,11 @@ static int bcm5974_start_traffic(struct bcm5974 *dev)
 		goto err_out;
 	}
 
-	error = usb_submit_urb(dev->bt_urb, GFP_KERNEL);
-	if (error)
-		goto err_reset_mode;
+	if (dev->bt_urb) {
+		error = usb_submit_urb(dev->bt_urb, GFP_KERNEL);
+		if (error)
+			goto err_reset_mode;
+	}
 
 	error = usb_submit_urb(dev->tp_urb, GFP_KERNEL);
 	if (error)
@@ -868,19 +870,23 @@ static int bcm5974_probe(struct usb_interface *iface,
 	mutex_init(&dev->pm_mutex);
 
 	/* setup urbs */
-	dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->bt_urb)
-		goto err_free_devs;
+	if (cfg->tp_type == TYPE1) {
+		dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!dev->bt_urb)
+			goto err_free_devs;
+	}
 
 	dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->tp_urb)
 		goto err_free_bt_urb;
 
-	dev->bt_data = usb_alloc_coherent(dev->udev,
+	if (dev->bt_urb) {
+		dev->bt_data = usb_alloc_coherent(dev->udev,
 					  dev->cfg.bt_datalen, GFP_KERNEL,
 					  &dev->bt_urb->transfer_dma);
-	if (!dev->bt_data)
-		goto err_free_urb;
+		if (!dev->bt_data)
+			goto err_free_urb;
+	}
 
 	dev->tp_data = usb_alloc_coherent(dev->udev,
 					  dev->cfg.tp_datalen, GFP_KERNEL,
@@ -888,10 +894,11 @@ static int bcm5974_probe(struct usb_interface *iface,
 	if (!dev->tp_data)
 		goto err_free_bt_buffer;
 
-	usb_fill_int_urb(dev->bt_urb, udev,
-			 usb_rcvintpipe(udev, cfg->bt_ep),
-			 dev->bt_data, dev->cfg.bt_datalen,
-			 bcm5974_irq_button, dev, 1);
+	if (dev->bt_urb)
+		usb_fill_int_urb(dev->bt_urb, udev,
+				 usb_rcvintpipe(udev, cfg->bt_ep),
+				 dev->bt_data, dev->cfg.bt_datalen,
+				 bcm5974_irq_button, dev, 1);
 
 	usb_fill_int_urb(dev->tp_urb, udev,
 			 usb_rcvintpipe(udev, cfg->tp_ep),
@@ -929,8 +936,9 @@ err_free_buffer:
 	usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
 		dev->tp_data, dev->tp_urb->transfer_dma);
 err_free_bt_buffer:
-	usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
-		dev->bt_data, dev->bt_urb->transfer_dma);
+	if (dev->bt_urb)
+		usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
+				  dev->bt_data, dev->bt_urb->transfer_dma);
 err_free_urb:
 	usb_free_urb(dev->tp_urb);
 err_free_bt_urb:
@@ -951,8 +959,9 @@ static void bcm5974_disconnect(struct usb_interface *iface)
 	input_unregister_device(dev->input);
 	usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
 			  dev->tp_data, dev->tp_urb->transfer_dma);
-	usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
-			  dev->bt_data, dev->bt_urb->transfer_dma);
+	if (dev->bt_urb)
+		usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
+				  dev->bt_data, dev->bt_urb->transfer_dma);
 	usb_free_urb(dev->tp_urb);
 	usb_free_urb(dev->bt_urb);
 	kfree(dev);
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 12/20] Input: bcm5974 - Preparatory renames
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (10 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 11/20] Input: bcm5974 - only setup button urb for TYPE1 devices Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation Henrik Rydberg
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Rename touch properties to match established nomenclature, and define
the maximum number of fingers.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/mouse/bcm5974.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 39ac9ff..2de974c 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -183,18 +183,19 @@ struct tp_finger {
 	__le16 abs_y;		/* absolute y coodinate */
 	__le16 rel_x;		/* relative x coodinate */
 	__le16 rel_y;		/* relative y coodinate */
-	__le16 size_major;	/* finger size, major axis? */
-	__le16 size_minor;	/* finger size, minor axis? */
+	__le16 tool_major;	/* tool area, major axis */
+	__le16 tool_minor;	/* tool area, minor axis */
 	__le16 orientation;	/* 16384 when point, else 15 bit angle */
-	__le16 force_major;	/* trackpad force, major axis? */
-	__le16 force_minor;	/* trackpad force, minor axis? */
+	__le16 touch_major;	/* touch area, major axis */
+	__le16 touch_minor;	/* touch area, minor axis */
 	__le16 unused[3];	/* zeros */
 	__le16 multi;		/* one finger: varies, more fingers: constant */
 } __attribute__((packed,aligned(2)));
 
 /* trackpad finger data size, empirically at least ten fingers */
+#define MAX_FINGERS		16
 #define SIZEOF_FINGER		sizeof(struct tp_finger)
-#define SIZEOF_ALL_FINGERS	(16 * SIZEOF_FINGER)
+#define SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
 #define MAX_FINGER_ORIENTATION	16384
 
 /* device-specific parameters */
@@ -482,13 +483,13 @@ static void report_finger_data(struct input_dev *input,
 			       const struct tp_finger *f)
 {
 	input_report_abs(input, ABS_MT_TOUCH_MAJOR,
-			 raw2int(f->force_major) << 1);
+			 raw2int(f->touch_major) << 1);
 	input_report_abs(input, ABS_MT_TOUCH_MINOR,
-			 raw2int(f->force_minor) << 1);
+			 raw2int(f->touch_minor) << 1);
 	input_report_abs(input, ABS_MT_WIDTH_MAJOR,
-			 raw2int(f->size_major) << 1);
+			 raw2int(f->tool_major) << 1);
 	input_report_abs(input, ABS_MT_WIDTH_MINOR,
-			 raw2int(f->size_minor) << 1);
+			 raw2int(f->tool_minor) << 1);
 	input_report_abs(input, ABS_MT_ORIENTATION,
 			 MAX_FINGER_ORIENTATION - raw2int(f->orientation));
 	input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
@@ -521,8 +522,8 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 		for (i = 0; i < raw_n; i++)
 			report_finger_data(input, c, &f[i]);
 
-		raw_p = raw2int(f->force_major);
-		raw_w = raw2int(f->size_major);
+		raw_p = raw2int(f->touch_major);
+		raw_w = raw2int(f->tool_major);
 		raw_x = raw2int(f->abs_x);
 		raw_y = raw2int(f->abs_y);
 
@@ -542,7 +543,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
 			while (raw_n--) {
 				ptest = int2bound(&c->p,
-						  raw2int(f->force_major));
+						  raw2int(f->touch_major));
 				if (ptest > PRESSURE_LOW)
 					nmax++;
 				if (ptest > PRESSURE_HIGH)
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (11 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 12/20] Input: bcm5974 - Preparatory renames Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-13  6:57   ` Dmitry Torokhov
  2012-09-01 19:47 ` [PATCH v3 14/20] Input: bcm5974 - Drop the logical dimensions Henrik Rydberg
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

The ABS_PRESSURE and ABS_WIDTH have special scales, and were initially
added solely for thumb and palm recognition in the synaptics driver.
This never really get used, however, and userspace quickly moved to
MT solutions instead. This patch drops the unused events.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/mouse/bcm5974.c | 26 +++++---------------------
 1 file changed, 5 insertions(+), 21 deletions(-)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 2de974c..e033d3a 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -417,10 +417,6 @@ static void setup_events_to_report(struct input_dev *input_dev,
 {
 	__set_bit(EV_ABS, input_dev->evbit);
 
-	input_set_abs_params(input_dev, ABS_PRESSURE,
-				0, cfg->p.dim, cfg->p.fuzz, 0);
-	input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
-				0, cfg->w.dim, cfg->w.fuzz, 0);
 	input_set_abs_params(input_dev, ABS_X,
 				0, cfg->x.dim, cfg->x.fuzz, 0);
 	input_set_abs_params(input_dev, ABS_Y,
@@ -504,9 +500,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	const struct bcm5974_config *c = &dev->cfg;
 	const struct tp_finger *f;
 	struct input_dev *input = dev->input;
-	int raw_p, raw_w, raw_x, raw_y, raw_n, i;
+	int raw_p, raw_x, raw_y, raw_n, i;
 	int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
-	int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
+	int abs_x = 0, abs_y = 0;
 
 	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
 		return -EIO;
@@ -523,22 +519,19 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 			report_finger_data(input, c, &f[i]);
 
 		raw_p = raw2int(f->touch_major);
-		raw_w = raw2int(f->tool_major);
 		raw_x = raw2int(f->abs_x);
 		raw_y = raw2int(f->abs_y);
 
 		dprintk(9,
 			"bcm5974: "
-			"raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
-			raw_p, raw_w, raw_x, raw_y, raw_n);
+			"raw: p: %+05d x: %+05d y: %+05d n: %d\n",
+			raw_p, raw_x, raw_y, raw_n);
 
 		ptest = int2bound(&c->p, raw_p);
 		origin = raw2int(f->origin);
 
 		/* while tracking finger still valid, count all fingers */
 		if (ptest > PRESSURE_LOW && origin) {
-			abs_p = ptest;
-			abs_w = int2bound(&c->w, raw_w);
 			abs_x = int2bound(&c->x, raw_x - c->x.devmin);
 			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
 			while (raw_n--) {
@@ -568,18 +561,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
 	input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
 
-	input_report_abs(input, ABS_PRESSURE, abs_p);
-	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
-
-	if (abs_p) {
+	if (dev->fingers > 0) {
 		input_report_abs(input, ABS_X, abs_x);
 		input_report_abs(input, ABS_Y, abs_y);
-
-		dprintk(8,
-			"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
-			"nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
-			abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
-
 	}
 
 	/* type 2 reports button events via ibt only */
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 14/20] Input: bcm5974 - Drop the logical dimensions
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (12 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 15/20] Input: bcm5974 - Convert to MT-B Henrik Rydberg
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

The logical scale was previously used to produce special width values
to userspace, and its only present use is to put "pressure" hysteresis
on a common scale. However, bcm5974 trackpads are very accurate and
work well without hysteresis.

This patch simplifies the driver and device data by removing the logical
scale altogether. While at it, the fake pressure range is replaced by the
orientation range, which will be used in a subsequent patch.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/mouse/bcm5974.c | 193 ++++++++++++++++--------------------------
 1 file changed, 75 insertions(+), 118 deletions(-)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index e033d3a..7f7ea62 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -200,10 +200,9 @@ struct tp_finger {
 
 /* device-specific parameters */
 struct bcm5974_param {
-	int dim;		/* logical dimension */
-	int fuzz;		/* logical noise value */
-	int devmin;		/* device minimum reading */
-	int devmax;		/* device maximum reading */
+	int snratio;		/* signal-to-noise ratio */
+	int min;		/* device minimum reading */
+	int max;		/* device maximum reading */
 };
 
 /* device-specific configuration */
@@ -216,7 +215,7 @@ struct bcm5974_config {
 	enum tp_type tp_type;	/* type of trackpad interface */
 	int tp_offset;		/* offset to trackpad finger data */
 	int tp_datalen;		/* data length of the trackpad interface */
-	struct bcm5974_param p;	/* finger pressure limits */
+	struct bcm5974_param o;	/* orientation limits */
 	struct bcm5974_param w;	/* finger width limits */
 	struct bcm5974_param x;	/* horizontal limits */
 	struct bcm5974_param y;	/* vertical limits */
@@ -235,24 +234,13 @@ struct bcm5974 {
 	struct bt_data *bt_data;	/* button transferred data */
 	struct urb *tp_urb;		/* trackpad usb request block */
 	u8 *tp_data;			/* trackpad transferred data */
-	int fingers;			/* number of fingers on trackpad */
 };
 
-/* logical dimensions */
-#define DIM_PRESSURE	256		/* maximum finger pressure */
-#define DIM_WIDTH	16		/* maximum finger width */
-#define DIM_X		1280		/* maximum trackpad x value */
-#define DIM_Y		800		/* maximum trackpad y value */
-
 /* logical signal quality */
-#define SN_PRESSURE	45		/* pressure signal-to-noise ratio */
+#define SN_ORIENT	10		/* orientation signal-to-noise ratio */
 #define SN_WIDTH	100		/* width signal-to-noise ratio */
 #define SN_COORD	250		/* coordinate signal-to-noise ratio */
 
-/* pressure thresholds */
-#define PRESSURE_LOW	(2 * DIM_PRESSURE / SN_PRESSURE)
-#define PRESSURE_HIGH	(3 * PRESSURE_LOW)
-
 /* device constants */
 static const struct bcm5974_config bcm5974_config_table[] = {
 	{
@@ -262,10 +250,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4824, 5342 },
-		{ DIM_Y, DIM_Y / SN_COORD, -172, 5820 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4824, 5342 },
+		{ SN_COORD, -172, 5820 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
@@ -274,10 +262,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
-		{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4824, 4824 },
+		{ SN_COORD, -172, 4290 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
@@ -286,10 +274,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
-		{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4460, 5166 },
+		{ SN_COORD, -75, 6700 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
@@ -298,10 +286,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
@@ -310,10 +298,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
-		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4616, 5112 },
+		{ SN_COORD, -142, 5234 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
@@ -322,10 +310,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
-		{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4415, 5050 },
+		{ SN_COORD, -55, 6680 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
@@ -334,10 +322,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
@@ -346,10 +334,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4750, 5280 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4750, 5280 },
+		{ SN_COORD, -150, 6730 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI,
@@ -358,10 +346,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
@@ -370,10 +358,10 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4750, 5280 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4750, 5280 },
+		{ SN_COORD, -150, 6730 }
 	},
 	{}
 };
@@ -397,18 +385,11 @@ static inline int raw2int(__le16 x)
 	return (signed short)le16_to_cpu(x);
 }
 
-/* scale device data to logical dimensions (asserts devmin < devmax) */
-static inline int int2scale(const struct bcm5974_param *p, int x)
-{
-	return x * p->dim / (p->devmax - p->devmin);
-}
-
-/* all logical value ranges are [0,dim). */
-static inline int int2bound(const struct bcm5974_param *p, int x)
+static void set_abs(struct input_dev *input, unsigned int code,
+		    const struct bcm5974_param *p)
 {
-	int s = int2scale(p, x);
-
-	return clamp_val(s, 0, p->dim - 1);
+	int fuzz = p->snratio ? (p->max - p->min) / p->snratio : 0;
+	input_set_abs_params(input, code, p->min, p->max, fuzz, 0);
 }
 
 /* setup which logical events to report */
@@ -417,30 +398,21 @@ static void setup_events_to_report(struct input_dev *input_dev,
 {
 	__set_bit(EV_ABS, input_dev->evbit);
 
-	input_set_abs_params(input_dev, ABS_X,
-				0, cfg->x.dim, cfg->x.fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-				0, cfg->y.dim, cfg->y.fuzz, 0);
+	/* pointer emulation */
+	set_abs(input_dev, ABS_X, &cfg->w);
+	set_abs(input_dev, ABS_Y, &cfg->w);
 
 	/* finger touch area */
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
+	set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
 	/* finger approach area */
-	input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w);
+	set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w);
 	/* finger orientation */
-	input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
-			     -MAX_FINGER_ORIENTATION,
-			     MAX_FINGER_ORIENTATION, 0, 0);
+	set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o);
 	/* finger position */
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     cfg->x.devmin, cfg->x.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     cfg->y.devmin, cfg->y.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_POSITION_X, &cfg->x);
+	set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y);
 
 	__set_bit(EV_KEY, input_dev->evbit);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
@@ -490,7 +462,7 @@ static void report_finger_data(struct input_dev *input,
 			 MAX_FINGER_ORIENTATION - raw2int(f->orientation));
 	input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
 	input_report_abs(input, ABS_MT_POSITION_Y,
-			 cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y));
+			 cfg->y.min + cfg->y.max - raw2int(f->abs_y));
 	input_mt_sync(input);
 }
 
@@ -501,8 +473,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	const struct tp_finger *f;
 	struct input_dev *input = dev->input;
 	int raw_p, raw_x, raw_y, raw_n, i;
-	int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
-	int abs_x = 0, abs_y = 0;
+	int abs_x = 0, abs_y = 0, n = 0;
 
 	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
 		return -EIO;
@@ -527,48 +498,34 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 			"raw: p: %+05d x: %+05d y: %+05d n: %d\n",
 			raw_p, raw_x, raw_y, raw_n);
 
-		ptest = int2bound(&c->p, raw_p);
-		origin = raw2int(f->origin);
-
 		/* while tracking finger still valid, count all fingers */
-		if (ptest > PRESSURE_LOW && origin) {
-			abs_x = int2bound(&c->x, raw_x - c->x.devmin);
-			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
+		if (raw_p > 0 && raw2int(f->origin)) {
+			abs_x = raw_x;
+			abs_y = c->y.min + c->y.max - raw_y;
 			while (raw_n--) {
-				ptest = int2bound(&c->p,
-						  raw2int(f->touch_major));
-				if (ptest > PRESSURE_LOW)
-					nmax++;
-				if (ptest > PRESSURE_HIGH)
-					nmin++;
+				if (raw2int(f->touch_major) > 0)
+					n++;
 				f++;
 			}
 		}
 	}
 
-	/* set the integrated button if applicable */
-	if (c->tp_type == TYPE2)
-		ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
-
-	if (dev->fingers < nmin)
-		dev->fingers = nmin;
-	if (dev->fingers > nmax)
-		dev->fingers = nmax;
+	input_report_key(input, BTN_TOUCH, n > 0);
+	input_report_key(input, BTN_TOOL_FINGER, n == 1);
+	input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
+	input_report_key(input, BTN_TOOL_TRIPLETAP, n == 3);
+	input_report_key(input, BTN_TOOL_QUADTAP, n > 3);
 
-	input_report_key(input, BTN_TOUCH, dev->fingers > 0);
-	input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
-	input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
-	input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
-	input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
-
-	if (dev->fingers > 0) {
+	if (n > 0) {
 		input_report_abs(input, ABS_X, abs_x);
 		input_report_abs(input, ABS_Y, abs_y);
 	}
 
 	/* type 2 reports button events via ibt only */
-	if (c->tp_type == TYPE2)
+	if (c->tp_type == TYPE2) {
+		int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
 		input_report_key(input, BTN_LEFT, ibt);
+	}
 
 	input_sync(input);
 
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 15/20] Input: bcm5974 - Convert to MT-B
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (13 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 14/20] Input: bcm5974 - Drop the logical dimensions Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 16/20] HID: Only dump input if someone is listening Henrik Rydberg
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Use of the in-kernel tracking code to convert the driver to MT-B.

With ten fingers on the pad, the in-kernel tracking adds approximately
25 us to the maximum irqsoff latency. Under normal workloads, however,
the tracking has no measurable effect.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/input/mouse/bcm5974.c | 80 ++++++++++++++-----------------------------
 1 file changed, 26 insertions(+), 54 deletions(-)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 7f7ea62..9555aa5 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -40,6 +40,7 @@
 #include <linux/usb/input.h>
 #include <linux/hid.h>
 #include <linux/mutex.h>
+#include <linux/input/mt.h>
 
 #define USB_VENDOR_ID_APPLE		0x05ac
 
@@ -234,6 +235,9 @@ struct bcm5974 {
 	struct bt_data *bt_data;	/* button transferred data */
 	struct urb *tp_urb;		/* trackpad usb request block */
 	u8 *tp_data;			/* trackpad transferred data */
+	const struct tp_finger *index[MAX_FINGERS];	/* finger index data */
+	struct input_mt_pos pos[MAX_FINGERS];		/* position array */
+	int slots[MAX_FINGERS];				/* slot assignments */
 };
 
 /* logical signal quality */
@@ -398,10 +402,6 @@ static void setup_events_to_report(struct input_dev *input_dev,
 {
 	__set_bit(EV_ABS, input_dev->evbit);
 
-	/* pointer emulation */
-	set_abs(input_dev, ABS_X, &cfg->w);
-	set_abs(input_dev, ABS_Y, &cfg->w);
-
 	/* finger touch area */
 	set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
 	set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
@@ -415,18 +415,13 @@ static void setup_events_to_report(struct input_dev *input_dev,
 	set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y);
 
 	__set_bit(EV_KEY, input_dev->evbit);
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-	__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-	__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-	__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
-	__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
 	__set_bit(BTN_LEFT, input_dev->keybit);
 
-	__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 	if (cfg->caps & HAS_INTEGRATED_BUTTON)
 		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
 
-	input_set_events_per_packet(input_dev, 60);
+	input_mt_init_slots(input_dev, MAX_FINGERS,
+		INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
 }
 
 /* report button data as logical button state */
@@ -446,10 +441,13 @@ static int report_bt_state(struct bcm5974 *dev, int size)
 	return 0;
 }
 
-static void report_finger_data(struct input_dev *input,
-			       const struct bcm5974_config *cfg,
+static void report_finger_data(struct input_dev *input, int slot,
+			       const struct input_mt_pos *pos,
 			       const struct tp_finger *f)
 {
+	input_mt_slot(input, slot);
+	input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+
 	input_report_abs(input, ABS_MT_TOUCH_MAJOR,
 			 raw2int(f->touch_major) << 1);
 	input_report_abs(input, ABS_MT_TOUCH_MINOR,
@@ -460,10 +458,8 @@ static void report_finger_data(struct input_dev *input,
 			 raw2int(f->tool_minor) << 1);
 	input_report_abs(input, ABS_MT_ORIENTATION,
 			 MAX_FINGER_ORIENTATION - raw2int(f->orientation));
-	input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
-	input_report_abs(input, ABS_MT_POSITION_Y,
-			 cfg->y.min + cfg->y.max - raw2int(f->abs_y));
-	input_mt_sync(input);
+	input_report_abs(input, ABS_MT_POSITION_X, pos->x);
+	input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
 }
 
 /* report trackpad data as logical trackpad state */
@@ -472,8 +468,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	const struct bcm5974_config *c = &dev->cfg;
 	const struct tp_finger *f;
 	struct input_dev *input = dev->input;
-	int raw_p, raw_x, raw_y, raw_n, i;
-	int abs_x = 0, abs_y = 0, n = 0;
+	int raw_n, i, n = 0;
 
 	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
 		return -EIO;
@@ -482,44 +477,21 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
 	raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
 
-	/* always track the first finger; when detached, start over */
-	if (raw_n) {
-
-		/* report raw trackpad data */
-		for (i = 0; i < raw_n; i++)
-			report_finger_data(input, c, &f[i]);
-
-		raw_p = raw2int(f->touch_major);
-		raw_x = raw2int(f->abs_x);
-		raw_y = raw2int(f->abs_y);
-
-		dprintk(9,
-			"bcm5974: "
-			"raw: p: %+05d x: %+05d y: %+05d n: %d\n",
-			raw_p, raw_x, raw_y, raw_n);
-
-		/* while tracking finger still valid, count all fingers */
-		if (raw_p > 0 && raw2int(f->origin)) {
-			abs_x = raw_x;
-			abs_y = c->y.min + c->y.max - raw_y;
-			while (raw_n--) {
-				if (raw2int(f->touch_major) > 0)
-					n++;
-				f++;
-			}
-		}
+	for (i = 0; i < raw_n; i++) {
+		if (raw2int(f[i].touch_major) == 0)
+			continue;
+		dev->pos[n].x = raw2int(f[i].abs_x);
+		dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
+		dev->index[n++] = &f[i];
 	}
 
-	input_report_key(input, BTN_TOUCH, n > 0);
-	input_report_key(input, BTN_TOOL_FINGER, n == 1);
-	input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
-	input_report_key(input, BTN_TOOL_TRIPLETAP, n == 3);
-	input_report_key(input, BTN_TOOL_QUADTAP, n > 3);
+	input_mt_assign_slots(input, dev->slots, dev->pos, n);
 
-	if (n > 0) {
-		input_report_abs(input, ABS_X, abs_x);
-		input_report_abs(input, ABS_Y, abs_y);
-	}
+	for (i = 0; i < n; i++)
+		report_finger_data(input, dev->slots[i],
+				   &dev->pos[i], dev->index[i]);
+
+	input_mt_sync_frame(input);
 
 	/* type 2 reports button events via ibt only */
 	if (c->tp_type == TYPE2) {
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (14 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 15/20] Input: bcm5974 - Convert to MT-B Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-02  7:28   ` Jiri Kosina
  2012-09-01 19:47 ` [PATCH v3 17/20] HID: Add an input configured notification callback Henrik Rydberg
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

Going through the motions of printing the debug message information
takes a long time; using the keyboard can lead to a 160 us irqsoff
latency. This patch skips hid_dump_input() when there are no open
handles, which brings latency down to 100 us.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 60ea284..5b74e78 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
 	struct hid_driver *hdrv = hid->driver;
 	int ret;
 
-	hid_dump_input(hid, usage, value);
+	if (!list_empty(&hid->debug_list))
+		hid_dump_input(hid, usage, value);
 
 	if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
 		ret = hdrv->event(hid, field, usage, value);
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 17/20] HID: Add an input configured notification callback
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (15 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 16/20] HID: Only dump input if someone is listening Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` Henrik Rydberg
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina; +Cc: linux-input, linux-kernel, Henrik Rydberg

A hid device may create several input devices, and a driver may need
to prepare or finalize the configuration per input device. Currently,
there is no sane way for a driver to know when a device has been
configured. This patch adds a callback providing that information.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-input.c | 11 +++++++++--
 include/linux/hid.h     |  3 +++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 811bfad..d917c0d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1154,6 +1154,7 @@ static void report_features(struct hid_device *hid)
 
 int hidinput_connect(struct hid_device *hid, unsigned int force)
 {
+	struct hid_driver *drv = hid->driver;
 	struct hid_report *report;
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
@@ -1228,6 +1229,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 				 * UGCI) cram a lot of unrelated inputs into the
 				 * same interface. */
 				hidinput->report = report;
+				if (drv->input_configured)
+					drv->input_configured(hid, hidinput);
 				if (input_register_device(hidinput->input))
 					goto out_cleanup;
 				hidinput = NULL;
@@ -1235,8 +1238,12 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 		}
 	}
 
-	if (hidinput && input_register_device(hidinput->input))
-		goto out_cleanup;
+	if (hidinput) {
+		if (drv->input_configured)
+			drv->input_configured(hid, hidinput);
+		if (input_register_device(hidinput->input))
+			goto out_cleanup;
+	}
 
 	return 0;
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 42970de..f37da28 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -626,6 +626,7 @@ struct hid_usage_id {
  * @report_fixup: called before report descriptor parsing (NULL means nop)
  * @input_mapping: invoked on input registering before mapping an usage
  * @input_mapped: invoked on input registering after mapping an usage
+ * @input_configured: invoked just before the device is registered
  * @feature_mapping: invoked on feature registering
  * @suspend: invoked on suspend (NULL means nop)
  * @resume: invoked on resume if device was not reset (NULL means nop)
@@ -670,6 +671,8 @@ struct hid_driver {
 	int (*input_mapped)(struct hid_device *hdev,
 			struct hid_input *hidinput, struct hid_field *field,
 			struct hid_usage *usage, unsigned long **bit, int *max);
+	void (*input_configured)(struct hid_device *hdev,
+				 struct hid_input *hidinput);
 	void (*feature_mapping)(struct hid_device *hdev,
 			struct hid_field *field,
 			struct hid_usage *usage);
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 17/20] HID: Add an input configured notification callback
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (16 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 17/20] HID: Add an input configured notification callback Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH v3 19/20] HID: hid-multitouch: Remove the redundant touch state Henrik Rydberg
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina
  Cc: linux-input, linux-kernel, Benjamin Tissoires, Henrik Rydberg

With the input_configured() callback in place, the setup and frame
synchronization can be simplified. The input device initialization is
moved to mt_input_configured(), to make sure the full HID report has been
seen.

Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-multitouch.c | 67 +++++++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 29 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index c400d90..1df86a7 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -92,8 +92,10 @@ struct mt_device {
 	__u8 touches_by_report;	/* how many touches are present in one report:
 				* 1 means we should use a serial protocol
 				* > 1 means hybrid (multitouch) protocol */
+	bool serial_maybe;	/* need to check for serial protocol */
 	bool curvalid;		/* is the current contact valid? */
 	struct mt_slot *slots;
+	unsigned mt_flags;	/* flags to pass to input-mt */
 };
 
 /* classes of device behavior */
@@ -319,24 +321,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	* We need to ignore fields that belong to other collections
 	* such as Mouse that might have the same GenericDesktop usages. */
 	if (field->application == HID_DG_TOUCHSCREEN)
-		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+		td->mt_flags |= INPUT_MT_DIRECT;
 	else if (field->application != HID_DG_TOUCHPAD)
 		return 0;
 
-	/* In case of an indirect device (touchpad), we need to add
-	 * specific BTN_TOOL_* to be handled by the synaptics xorg
-	 * driver.
-	 * We also consider that touchscreens providing buttons are touchpads.
+	/*
+	 * Model touchscreens providing buttons as touchpads.
 	 */
 	if (field->application == HID_DG_TOUCHPAD ||
-	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON ||
-	    cls->is_indirect) {
-		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
-		set_bit(BTN_TOOL_FINGER, hi->input->keybit);
-		set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit);
-		set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit);
-		set_bit(BTN_TOOL_QUADTAP, hi->input->keybit);
-	}
+	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
+		td->mt_flags |= INPUT_MT_POINTER;
 
 	/* eGalax devices provide a Digitizer.Stylus input which overrides
 	 * the correct Digitizers.Finger X/Y ranges.
@@ -353,8 +347,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_POSITION_X);
 			set_abs(hi->input, ABS_MT_POSITION_X, field,
 				cls->sn_move);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_X, field, cls->sn_move);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -363,8 +355,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_POSITION_Y);
 			set_abs(hi->input, ABS_MT_POSITION_Y, field,
 				cls->sn_move);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_Y, field, cls->sn_move);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -388,9 +378,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTID:
-			if (!td->maxcontacts)
-				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
-			input_mt_init_slots(hi->input, td->maxcontacts, 0);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			td->touches_by_report++;
@@ -418,9 +405,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_PRESSURE);
 			set_abs(hi->input, ABS_MT_PRESSURE, field,
 				cls->sn_pressure);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_PRESSURE, field,
-				cls->sn_pressure);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -536,7 +520,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 
 	}
 
-	input_mt_report_pointer_emulation(input, true);
+	input_mt_sync_frame(input);
 	input_sync(input);
 	td->num_received = 0;
 }
@@ -685,6 +669,32 @@ static void mt_post_parse(struct mt_device *td)
 	}
 }
 
+static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct mt_class *cls = &td->mtclass;
+	struct input_dev *input = hi->input;
+
+	/* Only initialize slots for MT input devices */
+	if (!test_bit(ABS_MT_POSITION_X, input->absbit))
+		return;
+
+	if (!td->maxcontacts)
+		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+
+	mt_post_parse(td);
+	if (td->serial_maybe)
+		mt_post_parse_default_settings(td);
+
+	if (cls->is_indirect)
+		td->mt_flags |= INPUT_MT_POINTER;
+
+	input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+
+	td->mt_flags = 0;
+}
+
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret, i;
@@ -722,6 +732,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto fail;
 	}
 
+	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
+		td->serial_maybe = true;
+
 	ret = hid_parse(hdev);
 	if (ret != 0)
 		goto fail;
@@ -730,11 +743,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (ret)
 		goto fail;
 
-	mt_post_parse(td);
-
-	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
-		mt_post_parse_default_settings(td);
-
 	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
 				GFP_KERNEL);
 	if (!td->slots) {
@@ -1087,6 +1095,7 @@ static struct hid_driver mt_driver = {
 	.remove = mt_remove,
 	.input_mapping = mt_input_mapping,
 	.input_mapped = mt_input_mapped,
+	.input_configured = mt_input_configured,
 	.feature_mapping = mt_feature_mapping,
 	.usage_table = mt_grabbed_usages,
 	.event = mt_event,
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v3 19/20] HID: hid-multitouch: Remove the redundant touch state
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (17 preceding siblings ...)
  2012-09-01 19:47 ` Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-01 19:47 ` [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection Henrik Rydberg
  2012-09-03 13:00 ` [PATCH v3 v3 00/20] Input and HID updates for 3.7 Benjamin Tissoires
  20 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina
  Cc: linux-input, linux-kernel, Henrik Rydberg, Benjamin Tissoires

With the input_mt_sync_frame() function in place, there is no longer
any need to keep the full touch state in the driver. This patch
removes the slot state and replaces the lookup code with the input-mt
equivalent.

Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
 drivers/hid/hid-multitouch.c | 88 ++++++++++++--------------------------------
 1 file changed, 23 insertions(+), 65 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 1df86a7..eee19c9 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -56,7 +56,6 @@ struct mt_slot {
 	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	bool touch_state;	/* is the touch valid? */
-	bool seen_in_this_frame;/* has this slot been updated */
 };
 
 struct mt_class {
@@ -94,7 +93,6 @@ struct mt_device {
 				* > 1 means hybrid (multitouch) protocol */
 	bool serial_maybe;	/* need to check for serial protocol */
 	bool curvalid;		/* is the current contact valid? */
-	struct mt_slot *slots;
 	unsigned mt_flags;	/* flags to pass to input-mt */
 };
 
@@ -136,25 +134,6 @@ static int cypress_compute_slot(struct mt_device *td)
 		return -1;
 }
 
-static int find_slot_from_contactid(struct mt_device *td)
-{
-	int i;
-	for (i = 0; i < td->maxcontacts; ++i) {
-		if (td->slots[i].contactid == td->curdata.contactid &&
-			td->slots[i].touch_state)
-			return i;
-	}
-	for (i = 0; i < td->maxcontacts; ++i) {
-		if (!td->slots[i].seen_in_this_frame &&
-			!td->slots[i].touch_state)
-			return i;
-	}
-	/* should not occurs. If this happens that means
-	 * that the device sent more touches that it says
-	 * in the report descriptor. It is ignored then. */
-	return -1;
-}
-
 static struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
@@ -448,7 +427,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 	return -1;
 }
 
-static int mt_compute_slot(struct mt_device *td)
+static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
 {
 	__s32 quirks = td->mtclass.quirks;
 
@@ -464,42 +443,23 @@ static int mt_compute_slot(struct mt_device *td)
 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
 		return td->curdata.contactid - 1;
 
-	return find_slot_from_contactid(td);
+	return input_mt_get_slot_by_key(input, td->curdata.contactid);
 }
 
 /*
  * this function is called when a whole contact has been processed,
  * so that it can assign it to a slot and store the data there
  */
-static void mt_complete_slot(struct mt_device *td)
+static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
-	td->curdata.seen_in_this_frame = true;
 	if (td->curvalid) {
-		int slotnum = mt_compute_slot(td);
-
-		if (slotnum >= 0 && slotnum < td->maxcontacts)
-			td->slots[slotnum] = td->curdata;
-	}
-	td->num_received++;
-}
-
-
-/*
- * this function is called when a whole packet has been received and processed,
- * so that it can decide what to send to the input layer.
- */
-static void mt_emit_event(struct mt_device *td, struct input_dev *input)
-{
-	int i;
+		int slotnum = mt_compute_slot(td, input);
+		struct mt_slot *s = &td->curdata;
 
-	for (i = 0; i < td->maxcontacts; ++i) {
-		struct mt_slot *s = &(td->slots[i]);
-		if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
-			!s->seen_in_this_frame) {
-			s->touch_state = false;
-		}
+		if (slotnum < 0 || slotnum >= td->maxcontacts)
+			return;
 
-		input_mt_slot(input, i);
+		input_mt_slot(input, slotnum);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER,
 			s->touch_state);
 		if (s->touch_state) {
@@ -516,24 +476,29 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
 		}
-		s->seen_in_this_frame = false;
-
 	}
 
+	td->num_received++;
+}
+
+/*
+ * this function is called when a whole packet has been received and processed,
+ * so that it can decide what to send to the input layer.
+ */
+static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+{
 	input_mt_sync_frame(input);
 	input_sync(input);
 	td->num_received = 0;
 }
 
-
-
 static int mt_event(struct hid_device *hid, struct hid_field *field,
 				struct hid_usage *usage, __s32 value)
 {
 	struct mt_device *td = hid_get_drvdata(hid);
 	__s32 quirks = td->mtclass.quirks;
 
-	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
+	if (hid->claimed & HID_CLAIMED_INPUT) {
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
 			if (quirks & MT_QUIRK_ALWAYS_VALID)
@@ -586,11 +551,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 		}
 
 		if (usage->hid == td->last_slot_field)
-			mt_complete_slot(td);
+			mt_complete_slot(td, field->hidinput->input);
 
 		if (field->index == td->last_field_index
 			&& td->num_received >= td->num_expected)
-			mt_emit_event(td, field->hidinput->input);
+			mt_sync_frame(td, field->hidinput->input);
 
 	}
 
@@ -690,6 +655,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
 	if (cls->is_indirect)
 		td->mt_flags |= INPUT_MT_POINTER;
 
+	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+		td->mt_flags |= INPUT_MT_DROP_UNUSED;
+
 	input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
 
 	td->mt_flags = 0;
@@ -743,15 +711,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (ret)
 		goto fail;
 
-	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
-				GFP_KERNEL);
-	if (!td->slots) {
-		dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
-		hid_hw_stop(hdev);
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
 
 	mt_set_maxcontacts(hdev);
@@ -782,7 +741,6 @@ static void mt_remove(struct hid_device *hdev)
 	struct mt_device *td = hid_get_drvdata(hdev);
 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
 	hid_hw_stop(hdev);
-	kfree(td->slots);
 	kfree(td);
 	hid_set_drvdata(hdev, NULL);
 }
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (18 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH v3 19/20] HID: hid-multitouch: Remove the redundant touch state Henrik Rydberg
@ 2012-09-01 19:47 ` Henrik Rydberg
  2012-09-03 12:59   ` Benjamin Tissoires
  2012-09-03 13:00 ` [PATCH v3 v3 00/20] Input and HID updates for 3.7 Benjamin Tissoires
  20 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-01 19:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Jiri Kosina
  Cc: linux-input, linux-kernel, Henrik Rydberg, Benjamin Tissoires

Some devices report the number of contacts via the CONTACTCOUNT usage,
rather than using the CONTACTMAX feature. Without this patch, such
devices will be capped to ten fingers, the default maximum. Fixes a
long-standing regression on 3M and similar panels.

Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
Since this patch looks like it could be backported as-is: In 3.6,
maxcontacts may be modified after the slots have been initialized,
leaving the patch harmless but ineffective.

 drivers/hid/hid-multitouch.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index eee19c9..2fc5335 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -388,6 +388,8 @@ 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:
+			if (td->maxcontacts < field->logical_maximum + 1)
+				td->maxcontacts = field->logical_maximum + 1;
 			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTMAX:
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-01 19:47 ` [PATCH v3 16/20] HID: Only dump input if someone is listening Henrik Rydberg
@ 2012-09-02  7:28   ` Jiri Kosina
  2012-09-02  8:52     ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Jiri Kosina @ 2012-09-02  7:28 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Sat, 1 Sep 2012, Henrik Rydberg wrote:

> Going through the motions of printing the debug message information
> takes a long time; using the keyboard can lead to a 160 us irqsoff
> latency. This patch skips hid_dump_input() when there are no open
> handles, which brings latency down to 100 us.
> 
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
> ---
>  drivers/hid/hid-core.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 60ea284..5b74e78 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
>  	struct hid_driver *hdrv = hid->driver;
>  	int ret;
>  
> -	hid_dump_input(hid, usage, value);
> +	if (!list_empty(&hid->debug_list))
> +		hid_dump_input(hid, usage, value);
>  
>  	if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
>  		ret = hdrv->event(hid, field, usage, value);

Henrik,

I have applied this one right away, so you can drop it from your series. 
The remaining ones I am still about to review (currently travelling).

There is no inter-dependency between the Input and HID ones, and so we can 
handle them with Dmitry as two independent Input and HID series, right?

Thanks a lot,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-02  7:28   ` Jiri Kosina
@ 2012-09-02  8:52     ` Henrik Rydberg
  2012-09-03 13:17       ` Jiri Kosina
  0 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-02  8:52 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, linux-kernel

Hi Jiri,

> I have applied this one right away, so you can drop it from your series. 
> The remaining ones I am still about to review (currently travelling).

Great, thanks. The notification callback can also be applied if you want.

> There is no inter-dependency between the Input and HID ones, and so we can 
> handle them with Dmitry as two independent Input and HID series, right?

Not quite, I am afraid. Some of the overlap has disappeared, true.
However, the hid-multitouch patches depend on new variables defined in
the input-mt patches, which in turn depend on the input core
changes. The hid-multitouch patches will apply (with a tiny merge
conflict), but they will not compile.

I can split the input-core and hid-core changes into separate sets,
and those could be applied separately. The input-mt and bcm5974 will
then build on input-core, and hid-multitouch will build on both
input-core and hid-core. I am not sure if this helps anyone, though.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection
  2012-09-01 19:47 ` [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection Henrik Rydberg
@ 2012-09-03 12:59   ` Benjamin Tissoires
  2012-09-03 17:07     ` Henrik Rydberg
  2012-09-05 15:09     ` [PATCH v2 20/20] HID: hid-multitouch: Fix contact count on 3M panels Henrik Rydberg
  0 siblings, 2 replies; 49+ messages in thread
From: Benjamin Tissoires @ 2012-09-03 12:59 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 1, 2012 at 9:47 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> Some devices report the number of contacts via the CONTACTCOUNT usage,
> rather than using the CONTACTMAX feature. Without this patch, such
> devices will be capped to ten fingers, the default maximum. Fixes a
> long-standing regression on 3M and similar panels.
>
> Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
> ---
> Since this patch looks like it could be backported as-is: In 3.6,
> maxcontacts may be modified after the slots have been initialized,
> leaving the patch harmless but ineffective.
>
>  drivers/hid/hid-multitouch.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index eee19c9..2fc5335 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -388,6 +388,8 @@ 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:
> +                       if (td->maxcontacts < field->logical_maximum + 1)
> +                               td->maxcontacts = field->logical_maximum + 1;

Hi Henrik,

Unfortunately, this is not working. We have bad devices that present either:
- a null logical_maximum (some Stantum do) -> the value 1 is assigned
to maxcontacts, and the device is turned into a mono touch....
- an obviously wrong value (with respect to the current state of the
devices) -> Quanta devices report 255 there.... and they support only
2 touches....

And of course, 3M decided to stop sending 60 touches on their recent
devices: we have here a 0x506 device that present a contact_count of
max 60, a maximum contact feature of max 60, but whatever I'm doing,
it does not want to send more than 10 touches....

Cheers,
Benjamin

>                         td->last_field_index = field->index;
>                         return 1;
>                 case HID_DG_CONTACTMAX:
> --
> 1.7.12
>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 v3 00/20] Input and HID updates for 3.7
  2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
                   ` (19 preceding siblings ...)
  2012-09-01 19:47 ` [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection Henrik Rydberg
@ 2012-09-03 13:00 ` Benjamin Tissoires
  2012-09-03 17:08   ` Henrik Rydberg
  20 siblings, 1 reply; 49+ messages in thread
From: Benjamin Tissoires @ 2012-09-03 13:00 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Henrik,

Indeed, we are getting close. I tested the whole patch set again.
So:
- patches 1 to 19 are not introducing any bugs (at least from what I've seen).
- patch 20 is not good (see the reply in the patch).

So far, devices tested are:
- Elan
- 3M
- Lumio
- Cypress
- Topseed
- Stantum

you can add my "reviewed by" on patches 1, 7, 8, 10, 17, 18 and 19
(those that are more MT related than generic input).
You can also add my 'tested-by' on the whole patch set except for the 20st.

Cheers,
Benjamin


On Sat, Sep 1, 2012 at 9:46 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
> Hi Dmitry, Jiri,
>
> Here is the third version of the patchset for 3.7. I think we are
> getting close. Changes in short:
>
> Patch 2: Folded the size estimate removal into this patch, since the
> other estimates are still needed for MT-A devices.
>
> Patch 5: Reworked to handle SYN_MT events the 'old' way.
> Patch 10: Reworked to allow for a proper device-to-slot mapping.
> Patch 15: Remove the old size estimate when converting to MT-B.
>
> Patch 18: New patch, carefully perform finalization per input device.
> Patch 19: Shortened version of touch state removal.
>
> Patch 20: New patch, fixing a long-standing bug for devices capable of
> more than ten touches.
>
> Several bugs removed, thanks to everyone involved in finding
> those. The set has been more thoroughly tested, but still needs
> further scrutiny from Benjamin.
>
> Thanks,
> Henrik
>
> Henrik Rydberg (20):
>   Input: Break out MT data
>   Input: Improve the events-per-packet estimate
>   Input: Make sure we follow all EV_KEY events
>   Input: Move autorepeat to the event-passing phase
>   Input: Send events one packet at a time
>   Input: evdev - Add the events() callback
>   Input: MT - Add flags to input_mt_init_slots()
>   Input: MT - Handle frame synchronization in core
>   Input: MT - Add in-kernel tracking
>   Input: MT - Get slot by key
>   Input: bcm5974 - only setup button urb for TYPE1 devices
>   Input: bcm5974 - Preparatory renames
>   Input: bcm5974 - Drop pressure and width emulation
>   Input: bcm5974 - Drop the logical dimensions
>   Input: bcm5974 - Convert to MT-B
>   HID: Only dump input if someone is listening
>   HID: Add an input configured notification callback
>   HID: hid-multitouch: Simplify setup and frame synchronization
>   HID: hid-multitouch: Remove the redundant touch state
>   HID: hid-multitouch: Add missing contact count detection
>
>  drivers/hid/hid-core.c                   |   3 +-
>  drivers/hid/hid-input.c                  |  11 +-
>  drivers/hid/hid-magicmouse.c             |   2 +-
>  drivers/hid/hid-multitouch.c             | 157 ++++++---------
>  drivers/input/evdev.c                    |  78 +++++---
>  drivers/input/input-mt.c                 | 294 +++++++++++++++++++++++++---
>  drivers/input/input.c                    | 245 ++++++++++++++++--------
>  drivers/input/misc/uinput.c              |   2 +-
>  drivers/input/mouse/alps.c               |   2 +-
>  drivers/input/mouse/bcm5974.c            | 317 ++++++++++++-------------------
>  drivers/input/mouse/elantech.c           |   4 +-
>  drivers/input/mouse/sentelic.c           |   2 +-
>  drivers/input/mouse/synaptics.c          |   4 +-
>  drivers/input/tablet/wacom_wac.c         |   6 +-
>  drivers/input/touchscreen/atmel_mxt_ts.c |   2 +-
>  drivers/input/touchscreen/cyttsp_core.c  |   2 +-
>  drivers/input/touchscreen/edt-ft5x06.c   |   2 +-
>  drivers/input/touchscreen/egalax_ts.c    |   2 +-
>  drivers/input/touchscreen/ili210x.c      |   2 +-
>  drivers/input/touchscreen/mms114.c       |   2 +-
>  drivers/input/touchscreen/penmount.c     |   2 +-
>  drivers/input/touchscreen/wacom_w8001.c  |   2 +-
>  include/linux/hid.h                      |   3 +
>  include/linux/input.h                    |  33 +++-
>  include/linux/input/mt.h                 |  55 +++++-
>  25 files changed, 778 insertions(+), 456 deletions(-)
>
> --
> 1.7.12
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-02  8:52     ` Henrik Rydberg
@ 2012-09-03 13:17       ` Jiri Kosina
  2012-09-06 20:57         ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Jiri Kosina @ 2012-09-03 13:17 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Sun, 2 Sep 2012, Henrik Rydberg wrote:

> > I have applied this one right away, so you can drop it from your series. 
> > The remaining ones I am still about to review (currently travelling).
> 
> Great, thanks. The notification callback can also be applied if you want.
> 
> > There is no inter-dependency between the Input and HID ones, and so we can 
> > handle them with Dmitry as two independent Input and HID series, right?
> 
> Not quite, I am afraid. Some of the overlap has disappeared, true.
> However, the hid-multitouch patches depend on new variables defined in
> the input-mt patches, which in turn depend on the input core
> changes. The hid-multitouch patches will apply (with a tiny merge
> conflict), but they will not compile.
> 
> I can split the input-core and hid-core changes into separate sets,
> and those could be applied separately. The input-mt and bcm5974 will
> then build on input-core, and hid-multitouch will build on both
> input-core and hid-core. I am not sure if this helps anyone, though.

I don't think so.

Let's wait once Dmitry is finished with the input changes, and I can 
either take the set through my tree with his Signed-off-by: on the Input 
patches, or vice-versa.

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection
  2012-09-03 12:59   ` Benjamin Tissoires
@ 2012-09-03 17:07     ` Henrik Rydberg
  2012-09-05 15:09     ` [PATCH v2 20/20] HID: hid-multitouch: Fix contact count on 3M panels Henrik Rydberg
  1 sibling, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-03 17:07 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Hi Benjamin,

> Unfortunately, this is not working. We have bad devices that present either:
> - a null logical_maximum (some Stantum do) -> the value 1 is assigned
> to maxcontacts, and the device is turned into a mono touch....
> - an obviously wrong value (with respect to the current state of the
> devices) -> Quanta devices report 255 there.... and they support only
> 2 touches....

This is really terrible :-) Ok, so let's set maxcontacts to 60 on the
3M class, that ought to work for all present devices, right?

> And of course, 3M decided to stop sending 60 touches on their recent
> devices: we have here a 0x506 device that present a contact_count of
> max 60, a maximum contact feature of max 60, but whatever I'm doing,
> it does not want to send more than 10 touches....

Odd indeed. Speaking of oddness, I have two patches for the Flatfrog
MT 3200, which 1) Uses more then 128 fields in the report descriptor
(ever seen that before?), and 2) Advertises axes that are not
used. But it does give 40 touches worth of awesomeness once quirked
properly. Will send shortly.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 v3 00/20] Input and HID updates for 3.7
  2012-09-03 13:00 ` [PATCH v3 v3 00/20] Input and HID updates for 3.7 Benjamin Tissoires
@ 2012-09-03 17:08   ` Henrik Rydberg
  0 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-03 17:08 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

> Indeed, we are getting close. I tested the whole patch set again.
> So:
> - patches 1 to 19 are not introducing any bugs (at least from what I've seen).
> - patch 20 is not good (see the reply in the patch).
> 
> So far, devices tested are:
> - Elan
> - 3M
> - Lumio
> - Cypress
> - Topseed
> - Stantum
> 
> you can add my "reviewed by" on patches 1, 7, 8, 10, 17, 18 and 19
> (those that are more MT related than generic input).
> You can also add my 'tested-by' on the whole patch set except for the 20st.

Excellent. Thank you for testing, Benjamin.

Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v2 20/20] HID: hid-multitouch: Fix contact count on 3M panels
  2012-09-03 12:59   ` Benjamin Tissoires
  2012-09-03 17:07     ` Henrik Rydberg
@ 2012-09-05 15:09     ` Henrik Rydberg
  1 sibling, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-05 15:09 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel

Some devices report the number of contacts via the unreliable
CONTACTCOUNT usage, rather than using the CONTACTMAX feature.
Without this patch, the 3M devices are constrained to the default
maximum of ten fingers.

Cc: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
Benjamin, are you ok with 0x506 being treated this way as well?

Thanks,
Henrik

 drivers/hid/hid-multitouch.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index eee19c9..63f120b 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -171,7 +171,9 @@ static struct mt_class mt_classes[] = {
 			MT_QUIRK_SLOT_IS_CONTACTID,
 		.sn_move = 2048,
 		.sn_width = 128,
-		.sn_height = 128 },
+		.sn_height = 128,
+		.maxcontacts = 60,
+	},
 	{ .name = MT_CLS_CYPRESS,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
 			MT_QUIRK_CYPRESS,
-- 
1.7.12


^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-03 13:17       ` Jiri Kosina
@ 2012-09-06 20:57         ` Henrik Rydberg
  2012-09-07  1:54           ` Ping Cheng
  2012-09-07 12:52           ` Jiri Kosina
  0 siblings, 2 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-06 20:57 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, linux-kernel

> Let's wait once Dmitry is finished with the input changes, and I can 
> either take the set through my tree with his Signed-off-by: on the Input 
> patches, or vice-versa.

Ok. Meanwhile, the current set is now in a temporary branch on github,
see below. Given there are no more change requests, I can add the
right SOBs and push it to my next tree for a while, before sending a
proper pull request to either of you.

Thanks,
Henrik

The following changes since commit 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d:

  Linux 3.6-rc4 (2012-09-01 10:39:58 -0700)

are available in the git repository at:

  git://github.com/rydberg/linux.git maybe

for you to fetch changes up to 631ea780695fdc0d1efa91b6714bd85369daab06:

  HID: hid-multitouch: Add Flatfrog support (2012-09-06 22:21:02 +0200)

----------------------------------------------------------------
Henrik Rydberg (21):
      Input: Break out MT data
      Input: Improve the events-per-packet estimate
      Input: Make sure we follow all EV_KEY events
      Input: Move autorepeat to the event-passing phase
      Input: Send events one packet at a time
      Input: evdev - Add the events() callback
      Input: MT - Add flags to input_mt_init_slots()
      Input: MT - Handle frame synchronization in core
      Input: MT - Add in-kernel tracking
      Input: MT - Get slot by key
      Input: bcm5974 - only setup button urb for TYPE1 devices
      Input: bcm5974 - Preparatory renames
      Input: bcm5974 - Drop pressure and width emulation
      Input: bcm5974 - Drop the logical dimensions
      Input: bcm5974 - Convert to MT-B
      HID: Add an input configured notification callback
      HID: hid-multitouch: Simplify setup and frame synchronization
      HID: hid-multitouch: Remove the redundant touch state
      HID: hid-multitouch: Fix contact count on 3M panels
      HID: Allow more fields in the hid report
      HID: hid-multitouch: Add Flatfrog support

 drivers/hid/hid-ids.h                    |   3 +
 drivers/hid/hid-input.c                  |  11 +-
 drivers/hid/hid-magicmouse.c             |   2 +-
 drivers/hid/hid-multitouch.c             | 192 +++++++++++++++-----------------
 drivers/input/evdev.c                    |  78 ++++++++-----
 drivers/input/input-mt.c                 | 294 +++++++++++++++++++++++++++++++++++++++++++++----
 drivers/input/input.c                    | 245 +++++++++++++++++++++++++++--------------
 drivers/input/misc/uinput.c              |   2 +-
 drivers/input/mouse/alps.c               |   2 +-
 drivers/input/mouse/bcm5974.c            | 317 ++++++++++++++++++++---------------------------------
 drivers/input/mouse/elantech.c           |   4 +-
 drivers/input/mouse/sentelic.c           |   2 +-
 drivers/input/mouse/synaptics.c          |   4 +-
 drivers/input/tablet/wacom_wac.c         |   6 +-
 drivers/input/touchscreen/atmel_mxt_ts.c |   2 +-
 drivers/input/touchscreen/cyttsp_core.c  |   2 +-
 drivers/input/touchscreen/edt-ft5x06.c   |   2 +-
 drivers/input/touchscreen/egalax_ts.c    |   2 +-
 drivers/input/touchscreen/ili210x.c      |   2 +-
 drivers/input/touchscreen/mms114.c       |   2 +-
 drivers/input/touchscreen/penmount.c     |   2 +-
 drivers/input/touchscreen/wacom_w8001.c  |   2 +-
 include/linux/hid.h                      |   5 +-
 include/linux/input.h                    |  33 ++++--
 include/linux/input/mt.h                 |  55 +++++++++-
 25 files changed, 807 insertions(+), 464 deletions(-)

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-06 20:57         ` Henrik Rydberg
@ 2012-09-07  1:54           ` Ping Cheng
  2012-09-07 12:52           ` Jiri Kosina
  1 sibling, 0 replies; 49+ messages in thread
From: Ping Cheng @ 2012-09-07  1:54 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, Dmitry Torokhov, linux-input, linux-kernel

On Thu, Sep 6, 2012 at 1:57 PM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> Let's wait once Dmitry is finished with the input changes, and I can
>> either take the set through my tree with his Signed-off-by: on the Input
>> patches, or vice-versa.
>
> Ok. Meanwhile, the current set is now in a temporary branch on github,
> see below. Given there are no more change requests, I can add the
> right SOBs and push it to my next tree for a while, before sending a
> proper pull request to either of you.
>
> Thanks,
> Henrik
>
> The following changes since commit 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d:
>
>   Linux 3.6-rc4 (2012-09-01 10:39:58 -0700)
>
> are available in the git repository at:
>
>   git://github.com/rydberg/linux.git maybe

This branch is tested with a Wacom Bamboo3 and an Intuos 5 M.

Tested-by: Ping Cheng <pingc@wacom.com>

Ping

> for you to fetch changes up to 631ea780695fdc0d1efa91b6714bd85369daab06:
>
>   HID: hid-multitouch: Add Flatfrog support (2012-09-06 22:21:02 +0200)
>
> ----------------------------------------------------------------
> Henrik Rydberg (21):
>       Input: Break out MT data
>       Input: Improve the events-per-packet estimate
>       Input: Make sure we follow all EV_KEY events
>       Input: Move autorepeat to the event-passing phase
>       Input: Send events one packet at a time
>       Input: evdev - Add the events() callback
>       Input: MT - Add flags to input_mt_init_slots()
>       Input: MT - Handle frame synchronization in core
>       Input: MT - Add in-kernel tracking
>       Input: MT - Get slot by key
>       Input: bcm5974 - only setup button urb for TYPE1 devices
>       Input: bcm5974 - Preparatory renames
>       Input: bcm5974 - Drop pressure and width emulation
>       Input: bcm5974 - Drop the logical dimensions
>       Input: bcm5974 - Convert to MT-B
>       HID: Add an input configured notification callback
>       HID: hid-multitouch: Simplify setup and frame synchronization
>       HID: hid-multitouch: Remove the redundant touch state
>       HID: hid-multitouch: Fix contact count on 3M panels
>       HID: Allow more fields in the hid report
>       HID: hid-multitouch: Add Flatfrog support
>
>  drivers/hid/hid-ids.h                    |   3 +
>  drivers/hid/hid-input.c                  |  11 +-
>  drivers/hid/hid-magicmouse.c             |   2 +-
>  drivers/hid/hid-multitouch.c             | 192 +++++++++++++++-----------------
>  drivers/input/evdev.c                    |  78 ++++++++-----
>  drivers/input/input-mt.c                 | 294 +++++++++++++++++++++++++++++++++++++++++++++----
>  drivers/input/input.c                    | 245 +++++++++++++++++++++++++++--------------
>  drivers/input/misc/uinput.c              |   2 +-
>  drivers/input/mouse/alps.c               |   2 +-
>  drivers/input/mouse/bcm5974.c            | 317 ++++++++++++++++++++---------------------------------
>  drivers/input/mouse/elantech.c           |   4 +-
>  drivers/input/mouse/sentelic.c           |   2 +-
>  drivers/input/mouse/synaptics.c          |   4 +-
>  drivers/input/tablet/wacom_wac.c         |   6 +-
>  drivers/input/touchscreen/atmel_mxt_ts.c |   2 +-
>  drivers/input/touchscreen/cyttsp_core.c  |   2 +-
>  drivers/input/touchscreen/edt-ft5x06.c   |   2 +-
>  drivers/input/touchscreen/egalax_ts.c    |   2 +-
>  drivers/input/touchscreen/ili210x.c      |   2 +-
>  drivers/input/touchscreen/mms114.c       |   2 +-
>  drivers/input/touchscreen/penmount.c     |   2 +-
>  drivers/input/touchscreen/wacom_w8001.c  |   2 +-
>  include/linux/hid.h                      |   5 +-
>  include/linux/input.h                    |  33 ++++--
>  include/linux/input/mt.h                 |  55 +++++++++-
>  25 files changed, 807 insertions(+), 464 deletions(-)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-06 20:57         ` Henrik Rydberg
  2012-09-07  1:54           ` Ping Cheng
@ 2012-09-07 12:52           ` Jiri Kosina
  2012-09-10 19:02             ` Henrik Rydberg
  1 sibling, 1 reply; 49+ messages in thread
From: Jiri Kosina @ 2012-09-07 12:52 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Thu, 6 Sep 2012, Henrik Rydberg wrote:

> > Let's wait once Dmitry is finished with the input changes, and I can 
> > either take the set through my tree with his Signed-off-by: on the Input 
> > patches, or vice-versa.
> 
> Ok. Meanwhile, the current set is now in a temporary branch on github,
> see below. Given there are no more change requests, I can add the
> right SOBs and push it to my next tree for a while, before sending a
> proper pull request to either of you.
> 
> Thanks,
> Henrik
> 
> The following changes since commit 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d:
> 
>   Linux 3.6-rc4 (2012-09-01 10:39:58 -0700)
> 
> are available in the git repository at:
> 
>   git://github.com/rydberg/linux.git maybe
> 
> for you to fetch changes up to 631ea780695fdc0d1efa91b6714bd85369daab06:
> 
>   HID: hid-multitouch: Add Flatfrog support (2012-09-06 22:21:02 +0200)
> 

Dmitry,

how do you want to handle this? I am fine with all the HID changes. So 
either I can take it through my tree and add your Sigoff to the Input 
patches (if you are fine with those), or vice versa (or take this through 
git branches, i.e. you apply the Input bits, I fetch that branch, and 
apply the rest on top of it).

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-07 12:52           ` Jiri Kosina
@ 2012-09-10 19:02             ` Henrik Rydberg
  2012-09-10 20:49               ` Jiri Kosina
  0 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-10 19:02 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, linux-kernel

> Dmitry,
> 
> how do you want to handle this? I am fine with all the HID changes. So 
> either I can take it through my tree and add your Sigoff to the Input 
> patches (if you are fine with those), or vice versa (or take this through 
> git branches, i.e. you apply the Input bits, I fetch that branch, and 
> apply the rest on top of it).

I went ahead and pushed the (updated) branch to my for-next, to get
some integration coverage. It is that time. Jiri, I added your
Acked-by on the hid patches for now, hope that is alright.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-10 19:02             ` Henrik Rydberg
@ 2012-09-10 20:49               ` Jiri Kosina
  2012-09-10 21:12                 ` Dmitry Torokhov
  0 siblings, 1 reply; 49+ messages in thread
From: Jiri Kosina @ 2012-09-10 20:49 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Mon, 10 Sep 2012, Henrik Rydberg wrote:

> > how do you want to handle this? I am fine with all the HID changes. So 
> > either I can take it through my tree and add your Sigoff to the Input 
> > patches (if you are fine with those), or vice versa (or take this through 
> > git branches, i.e. you apply the Input bits, I fetch that branch, and 
> > apply the rest on top of it).
> 
> I went ahead and pushed the (updated) branch to my for-next, to get
> some integration coverage. It is that time. Jiri, I added your
> Acked-by on the hid patches for now, hope that is alright.

Yes, it is, thanks Henrik.

Dmitry, I can pull the whole lot into my tree once you Ack/Signoff the 
input patches, if you wish.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-10 20:49               ` Jiri Kosina
@ 2012-09-10 21:12                 ` Dmitry Torokhov
  2012-09-14 19:25                   ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-10 21:12 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Henrik Rydberg, linux-input, linux-kernel

On Monday, September 10, 2012 10:49:13 PM Jiri Kosina wrote:
> On Mon, 10 Sep 2012, Henrik Rydberg wrote:
> > > how do you want to handle this? I am fine with all the HID changes. So
> > > either I can take it through my tree and add your Sigoff to the Input
> > > patches (if you are fine with those), or vice versa (or take this
> > > through
> > > git branches, i.e. you apply the Input bits, I fetch that branch, and
> > > apply the rest on top of it).
> > 
> > I went ahead and pushed the (updated) branch to my for-next, to get
> > some integration coverage. It is that time. Jiri, I added your
> > Acked-by on the hid patches for now, hope that is alright.
> 
> Yes, it is, thanks Henrik.
> 
> Dmitry, I can pull the whole lot into my tree once you Ack/Signoff the
> input patches, if you wish.

Yes, let me try to go through the patches tonight and I'll let yo know...

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 01/20] Input: Break out MT data
  2012-09-01 19:46 ` [PATCH v3 01/20] Input: Break out MT data Henrik Rydberg
@ 2012-09-13  5:15   ` Dmitry Torokhov
  2012-09-13 17:58     ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-13  5:15 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 01, 2012 at 09:46:56PM +0200, Henrik Rydberg wrote:
> Move all MT-related things to a separate place. This saves some
> bytes for non-mt input devices, and prepares for new MT features.
> 
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
...
> @@ -1287,10 +1284,8 @@ struct input_dev {
>  
>  	int rep[REP_CNT];
>  
> -	struct input_mt_slot *mt;
> -	int mtsize;
> +	struct input_mt *mt;
>  	int slot;
> -	int trkid;
>  
>  	struct input_absinfo *absinfo;

Shouldn't 'slot' go into struct input_mt as well?

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 02/20] Input: Improve the events-per-packet estimate
  2012-09-01 19:46 ` [PATCH v3 02/20] Input: Improve the events-per-packet estimate Henrik Rydberg
@ 2012-09-13  5:16   ` Dmitry Torokhov
  0 siblings, 0 replies; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-13  5:16 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 01, 2012 at 09:46:57PM +0200, Henrik Rydberg wrote:
> The events-per-packet estimate has so far been used by MT devices
> only. This patch adjusts the packet buffer size to also accomodate the
> KEY and MSC events.  Keyboards normally send one or two keys at a
> time. MT devices normally send a number of button keys along with the
> MT information.  The buffer size chosen here covers those cases, and
> matches the default buffer size in evdev. Since the input estimate is
> now preferred, remove the special input-mt estimate.
> 
> Reviewed-by: Ping Cheng <pingc@wacom.com>
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>

Makes sense.

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

> ---
>  drivers/input/input-mt.c |  1 -
>  drivers/input/input.c    | 10 +++++++---
>  2 files changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
> index c6df704..58bde77 100644
> --- a/drivers/input/input-mt.c
> +++ b/drivers/input/input-mt.c
> @@ -42,7 +42,6 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
>  	mt->num_slots = 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);
> -	input_set_events_per_packet(dev, 6 * num_slots);
>  
>  	/* Mark slots as 'unused' */
>  	for (i = 0; i < num_slots; i++)
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 6e90705..8ebf116 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -1777,6 +1777,9 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
>  		if (test_bit(i, dev->relbit))
>  			events++;
>  
> +	/* Make room for KEY and MSC events */
> +	events += 7;
> +
>  	return events;
>  }
>  
> @@ -1815,6 +1818,7 @@ int input_register_device(struct input_dev *dev)
>  {
>  	static atomic_t input_no = ATOMIC_INIT(0);
>  	struct input_handler *handler;
> +	unsigned int packet_size;
>  	const char *path;
>  	int error;
>  
> @@ -1827,9 +1831,9 @@ int input_register_device(struct input_dev *dev)
>  	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
>  	input_cleanse_bitmasks(dev);
>  
> -	if (!dev->hint_events_per_packet)
> -		dev->hint_events_per_packet =
> -				input_estimate_events_per_packet(dev);
> +	packet_size = input_estimate_events_per_packet(dev);
> +	if (dev->hint_events_per_packet < packet_size)
> +		dev->hint_events_per_packet = packet_size;
>  
>  	/*
>  	 * If delay and period are pre-set by the driver, then autorepeating
> -- 
> 1.7.12
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events
  2012-09-01 19:46 ` [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events Henrik Rydberg
@ 2012-09-13  5:19   ` Dmitry Torokhov
  0 siblings, 0 replies; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-13  5:19 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 01, 2012 at 09:46:58PM +0200, Henrik Rydberg wrote:
> For some EV_KEY types, sending a larger-than-one value causes the
> input state to oscillate. This patch makes sure this cannot happen,
> clearing up the autorepeat bypass logic in the process.
> 
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

> ---
>  drivers/input/input.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 8ebf116..4d64500 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -239,24 +239,30 @@ static void input_handle_event(struct input_dev *dev,
>  		break;
>  
>  	case EV_KEY:
> -		if (is_event_supported(code, dev->keybit, KEY_MAX) &&
> -		    !!test_bit(code, dev->key) != value) {
> +		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
> +
> +			/* auto-repeat bypasses state updates */
> +			if (value == 2) {
> +				disposition = INPUT_PASS_TO_HANDLERS;
> +				break;
> +			}
> +
> +			if (!!test_bit(code, dev->key) != !!value) {
>  
> -			if (value != 2) {
>  				__change_bit(code, dev->key);
> +				disposition = INPUT_PASS_TO_HANDLERS;
> +
>  				if (value)
>  					input_start_autorepeat(dev, code);
>  				else
>  					input_stop_autorepeat(dev);
>  			}
> -
> -			disposition = INPUT_PASS_TO_HANDLERS;
>  		}
>  		break;
>  
>  	case EV_SW:
>  		if (is_event_supported(code, dev->swbit, SW_MAX) &&
> -		    !!test_bit(code, dev->sw) != value) {
> +		    !!test_bit(code, dev->sw) != !!value) {
>  
>  			__change_bit(code, dev->sw);
>  			disposition = INPUT_PASS_TO_HANDLERS;
> @@ -283,7 +289,7 @@ static void input_handle_event(struct input_dev *dev,
>  
>  	case EV_LED:
>  		if (is_event_supported(code, dev->ledbit, LED_MAX) &&
> -		    !!test_bit(code, dev->led) != value) {
> +		    !!test_bit(code, dev->led) != !!value) {
>  
>  			__change_bit(code, dev->led);
>  			disposition = INPUT_PASS_TO_ALL;
> -- 
> 1.7.12
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 05/20] Input: Send events one packet at a time
  2012-09-01 19:47 ` [PATCH v3 05/20] Input: Send events one packet at a time Henrik Rydberg
@ 2012-09-13  6:56   ` Dmitry Torokhov
  2012-09-13 17:59     ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-13  6:56 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 01, 2012 at 09:47:00PM +0200, Henrik Rydberg wrote:
> On heavy event loads, such as a multitouch driver, the irqsoff latency
> can be as high as 250 us.  By accumulating a frame worth of data
> before passing it on, the latency can be dramatically reduced.  As a
> side effect, the special EV_SYN handling can be removed, since the
> frame is now atomic.
> 
> This patch adds the events() handler callback and uses it if it
> exists. The latency is improved by 50 us even without the callback.
> 
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
> ---
>  drivers/input/input.c | 176 +++++++++++++++++++++++++++++++++++---------------
>  include/linux/input.h |  24 ++++++-
>  2 files changed, 144 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index a57c4a5..5b66b2f 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex);
>  
>  static struct input_handler *input_table[8];
>  
> +static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
> +
>  static inline int is_event_supported(unsigned int code,
>  				     unsigned long *bm, unsigned int max)
>  {
> @@ -90,46 +92,81 @@ static void input_stop_autorepeat(struct input_dev *dev)
>   * filtered out, through all open handles. This function is called with
>   * dev->event_lock held and interrupts disabled.
>   */
> -static void input_pass_event(struct input_dev *dev,
> -			     unsigned int type, unsigned int code, int value)
> +static unsigned int input_to_handler(struct input_handle *handle,
> +			struct input_value *vals, unsigned int count)
>  {
> -	struct input_handler *handler;
> -	struct input_handle *handle;
> +	struct input_handler *handler = handle->handler;
> +	struct input_value *end = vals;
> +	struct input_value *v;
>  
> -	rcu_read_lock();
> +	for (v = vals; v != vals + count; v++) {
> +		if (handler->filter &&
> +		    handler->filter(handle, v->type, v->code, v->value))
> +			continue;
> +		if (end != v)
> +			*end = *v;
> +		end++;
> +	}
>  
> -	handle = rcu_dereference(dev->grab);
> -	if (handle)
> -		handle->handler->event(handle, type, code, value);
> -	else {
> -		bool filtered = false;
> +	count = end - vals;
> +	if (!count)
> +		return 0;
>  
> -		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
> -			if (!handle->open)
> -				continue;
> +	if (handler->events)
> +		handler->events(handle, vals, count);
> +	else
> +		for (v = vals; v != end; v++)
> +			handler->event(handle, v->type, v->code, v->value);

Filter handlers do not typically have ->event() methods, that's the
reason for reported panic.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation
  2012-09-01 19:47 ` [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation Henrik Rydberg
@ 2012-09-13  6:57   ` Dmitry Torokhov
  2012-09-13 18:41     ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-13  6:57 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Sat, Sep 01, 2012 at 09:47:08PM +0200, Henrik Rydberg wrote:
> The ABS_PRESSURE and ABS_WIDTH have special scales, and were initially
> added solely for thumb and palm recognition in the synaptics driver.
> This never really get used, however, and userspace quickly moved to
> MT solutions instead. This patch drops the unused events.

How can you know that? There could still be people using ST emulation
with this device. I think we should keep it.

Thanks.

> 
> Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
> ---
>  drivers/input/mouse/bcm5974.c | 26 +++++---------------------
>  1 file changed, 5 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
> index 2de974c..e033d3a 100644
> --- a/drivers/input/mouse/bcm5974.c
> +++ b/drivers/input/mouse/bcm5974.c
> @@ -417,10 +417,6 @@ static void setup_events_to_report(struct input_dev *input_dev,
>  {
>  	__set_bit(EV_ABS, input_dev->evbit);
>  
> -	input_set_abs_params(input_dev, ABS_PRESSURE,
> -				0, cfg->p.dim, cfg->p.fuzz, 0);
> -	input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
> -				0, cfg->w.dim, cfg->w.fuzz, 0);
>  	input_set_abs_params(input_dev, ABS_X,
>  				0, cfg->x.dim, cfg->x.fuzz, 0);
>  	input_set_abs_params(input_dev, ABS_Y,
> @@ -504,9 +500,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
>  	const struct bcm5974_config *c = &dev->cfg;
>  	const struct tp_finger *f;
>  	struct input_dev *input = dev->input;
> -	int raw_p, raw_w, raw_x, raw_y, raw_n, i;
> +	int raw_p, raw_x, raw_y, raw_n, i;
>  	int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
> -	int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
> +	int abs_x = 0, abs_y = 0;
>  
>  	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
>  		return -EIO;
> @@ -523,22 +519,19 @@ static int report_tp_state(struct bcm5974 *dev, int size)
>  			report_finger_data(input, c, &f[i]);
>  
>  		raw_p = raw2int(f->touch_major);
> -		raw_w = raw2int(f->tool_major);
>  		raw_x = raw2int(f->abs_x);
>  		raw_y = raw2int(f->abs_y);
>  
>  		dprintk(9,
>  			"bcm5974: "
> -			"raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
> -			raw_p, raw_w, raw_x, raw_y, raw_n);
> +			"raw: p: %+05d x: %+05d y: %+05d n: %d\n",
> +			raw_p, raw_x, raw_y, raw_n);
>  
>  		ptest = int2bound(&c->p, raw_p);
>  		origin = raw2int(f->origin);
>  
>  		/* while tracking finger still valid, count all fingers */
>  		if (ptest > PRESSURE_LOW && origin) {
> -			abs_p = ptest;
> -			abs_w = int2bound(&c->w, raw_w);
>  			abs_x = int2bound(&c->x, raw_x - c->x.devmin);
>  			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
>  			while (raw_n--) {
> @@ -568,18 +561,9 @@ static int report_tp_state(struct bcm5974 *dev, int size)
>  	input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
>  	input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
>  
> -	input_report_abs(input, ABS_PRESSURE, abs_p);
> -	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
> -
> -	if (abs_p) {
> +	if (dev->fingers > 0) {
>  		input_report_abs(input, ABS_X, abs_x);
>  		input_report_abs(input, ABS_Y, abs_y);
> -
> -		dprintk(8,
> -			"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
> -			"nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
> -			abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
> -
>  	}
>  
>  	/* type 2 reports button events via ibt only */
> -- 
> 1.7.12
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 01/20] Input: Break out MT data
  2012-09-13  5:15   ` Dmitry Torokhov
@ 2012-09-13 17:58     ` Henrik Rydberg
  0 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-13 17:58 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

On Wed, Sep 12, 2012 at 10:15:28PM -0700, Dmitry Torokhov wrote:
> On Sat, Sep 01, 2012 at 09:46:56PM +0200, Henrik Rydberg wrote:
> > Move all MT-related things to a separate place. This saves some
> > bytes for non-mt input devices, and prepares for new MT features.
> > 
> > Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
> ...
> > @@ -1287,10 +1284,8 @@ struct input_dev {
> >  
> >  	int rep[REP_CNT];
> >  
> > -	struct input_mt_slot *mt;
> > -	int mtsize;
> > +	struct input_mt *mt;
> >  	int slot;
> > -	int trkid;
> >  
> >  	struct input_absinfo *absinfo;
> 
> Shouldn't 'slot' go into struct input_mt as well?

I wanted to remove it all together, but it turned out hairier than I
envisioned, so I left it for now. Once/if MT drivers are converted to
pass input_value arrays instead, 'slot' will disappear cleanly.

Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 05/20] Input: Send events one packet at a time
  2012-09-13  6:56   ` Dmitry Torokhov
@ 2012-09-13 17:59     ` Henrik Rydberg
  0 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-13 17:59 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

> Filter handlers do not typically have ->event() methods, that's the
> reason for reported panic.

If we decide to rewind the tree, I will amend the fix here.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation
  2012-09-13  6:57   ` Dmitry Torokhov
@ 2012-09-13 18:41     ` Henrik Rydberg
  0 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-13 18:41 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

On Wed, Sep 12, 2012 at 11:57:24PM -0700, Dmitry Torokhov wrote:
> On Sat, Sep 01, 2012 at 09:47:08PM +0200, Henrik Rydberg wrote:
> > The ABS_PRESSURE and ABS_WIDTH have special scales, and were initially
> > added solely for thumb and palm recognition in the synaptics driver.
> > This never really get used, however, and userspace quickly moved to
> > MT solutions instead. This patch drops the unused events.
> 
> How can you know that? There could still be people using ST emulation
> with this device. I think we should keep it.

Alright, maybe we need to carry this still. Probability = macbook *
old_userland * new_kernel * working_synaptics * tuned_palm_parameters,
must be a pretty large number. ;-)

Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v3 16/20] HID: Only dump input if someone is listening
  2012-09-10 21:12                 ` Dmitry Torokhov
@ 2012-09-14 19:25                   ` Henrik Rydberg
  2012-09-15 15:33                     ` Input and HID updates for 3.7, version 4 Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-14 19:25 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

> > > I went ahead and pushed the (updated) branch to my for-next, to get
> > > some integration coverage. It is that time. Jiri, I added your
> > > Acked-by on the hid patches for now, hope that is alright.
> > 
> > Yes, it is, thanks Henrik.
> > 
> > Dmitry, I can pull the whole lot into my tree once you Ack/Signoff the
> > input patches, if you wish.
> 
> Yes, let me try to go through the patches tonight and I'll let yo know...

Dmitry, given the oops-fix amended, are you ok with the input core
changes at this point? If so, I can add your ACK on those, and refresh
the input, input-mt and hid changes to next. I will be back with the
reworked bcm5974 set, but the rest should be ready for a pull from
Jiri.

Thanks,
Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Input and HID updates for 3.7, version 4
  2012-09-14 19:25                   ` Henrik Rydberg
@ 2012-09-15 15:33                     ` Henrik Rydberg
  2012-09-18 11:29                       ` Jiri Kosina
  0 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-15 15:33 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

Ok, here is version 4 of the patchset. Rather than sending out all the
patches again, the diff to linux-next is given below, and the
refreshed tree can be pulled from

  git://github.com/rydberg/linux.git maybe

All Dmitry's comments are addressed. Changes in short:

* Also move 'slot' to input_mt
* Oops fix amended
* New patch to allow driver pressure handling
* Keep the synaptics specials in bcm5974

Needless to say, I want to move this tree to linux-next soonish, so if
there are more comments coming, I would appreciate a heads-up.

Thanks,
Henrik

diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 4c0e531..c0ec7d4 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -107,7 +107,6 @@ void input_mt_destroy_slots(struct input_dev *dev)
 		kfree(dev->mt);
 	}
 	dev->mt = NULL;
-	dev->slot = 0;
 }
 EXPORT_SYMBOL(input_mt_destroy_slots);
 
@@ -133,7 +132,7 @@ void input_mt_report_slot_state(struct input_dev *dev,
 	if (!mt)
 		return;
 
-	slot = &mt->slots[dev->slot];
+	slot = &mt->slots[mt->slot];
 	slot->frame = mt->frame;
 
 	if (!active) {
@@ -215,13 +214,17 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 	if (oldest) {
 		int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
 		int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
-		int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
 
 		input_event(dev, EV_ABS, ABS_X, x);
 		input_event(dev, EV_ABS, ABS_Y, y);
-		input_event(dev, EV_ABS, ABS_PRESSURE, p);
+
+		if (test_bit(ABS_MT_PRESSURE, dev->absbit)) {
+			int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
+			input_event(dev, EV_ABS, ABS_PRESSURE, p);
+		}
 	} else {
-		input_event(dev, EV_ABS, ABS_PRESSURE, 0);
+		if (test_bit(ABS_MT_PRESSURE, dev->absbit))
+			input_event(dev, EV_ABS, ABS_PRESSURE, 0);
 	}
 }
 EXPORT_SYMBOL(input_mt_report_pointer_emulation);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 2dff71b..5244f3d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -208,6 +208,7 @@ static void input_repeat_key(unsigned long data)
 static int input_handle_abs_event(struct input_dev *dev,
 				  unsigned int code, int *pval)
 {
+	struct input_mt *mt = dev->mt;
 	bool is_mt_event;
 	int *pold;
 
@@ -216,8 +217,8 @@ static int input_handle_abs_event(struct input_dev *dev,
 		 * "Stage" the event; we'll flush it later, when we
 		 * get actual touch data.
 		 */
-		if (dev->mt && *pval >= 0 && *pval < dev->mt->num_slots)
-			dev->slot = *pval;
+		if (mt && *pval >= 0 && *pval < mt->num_slots)
+			mt->slot = *pval;
 
 		return INPUT_IGNORE_EVENT;
 	}
@@ -226,8 +227,8 @@ static int input_handle_abs_event(struct input_dev *dev,
 
 	if (!is_mt_event) {
 		pold = &dev->absinfo[code].value;
-	} else if (dev->mt) {
-		pold = &dev->mt->slots[dev->slot].abs[code - ABS_MT_FIRST];
+	} else if (mt) {
+		pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST];
 	} else {
 		/*
 		 * Bypass filtering for multi-touch events when
@@ -246,8 +247,8 @@ static int input_handle_abs_event(struct input_dev *dev,
 	}
 
 	/* Flush pending "slot" event */
-	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
-		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
+	if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
+		input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
 		return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
 	}
 
@@ -378,7 +379,7 @@ static void input_handle_event(struct input_dev *dev,
 			v = &dev->vals[dev->num_vals++];
 			v->type = EV_ABS;
 			v->code = ABS_MT_SLOT;
-			v->value = dev->slot;
+			v->value = dev->mt->slot;
 		}
 
 		v = &dev->vals[dev->num_vals++];
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 9555aa5..3a78f23 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -216,10 +216,11 @@ struct bcm5974_config {
 	enum tp_type tp_type;	/* type of trackpad interface */
 	int tp_offset;		/* offset to trackpad finger data */
 	int tp_datalen;		/* data length of the trackpad interface */
-	struct bcm5974_param o;	/* orientation limits */
+	struct bcm5974_param p;	/* finger pressure limits */
 	struct bcm5974_param w;	/* finger width limits */
 	struct bcm5974_param x;	/* horizontal limits */
 	struct bcm5974_param y;	/* vertical limits */
+	struct bcm5974_param o;	/* orientation limits */
 };
 
 /* logical device structure */
@@ -241,9 +242,10 @@ struct bcm5974 {
 };
 
 /* logical signal quality */
-#define SN_ORIENT	10		/* orientation signal-to-noise ratio */
-#define SN_WIDTH	100		/* width signal-to-noise ratio */
+#define SN_PRESSURE	45		/* pressure signal-to-noise ratio */
+#define SN_WIDTH	25		/* width signal-to-noise ratio */
 #define SN_COORD	250		/* coordinate signal-to-noise ratio */
+#define SN_ORIENT	10		/* orientation signal-to-noise ratio */
 
 /* device constants */
 static const struct bcm5974_config bcm5974_config_table[] = {
@@ -254,10 +256,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 256 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4824, 5342 },
-		{ SN_COORD, -172, 5820 }
+		{ SN_COORD, -172, 5820 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
@@ -266,10 +269,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 256 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4824, 4824 },
-		{ SN_COORD, -172, 4290 }
+		{ SN_COORD, -172, 4290 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
@@ -278,10 +282,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4460, 5166 },
-		{ SN_COORD, -75, 6700 }
+		{ SN_COORD, -75, 6700 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
@@ -290,10 +295,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4620, 5140 },
-		{ SN_COORD, -150, 6600 }
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
@@ -302,10 +308,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4616, 5112 },
-		{ SN_COORD, -142, 5234 }
+		{ SN_COORD, -142, 5234 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
@@ -314,10 +321,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4415, 5050 },
-		{ SN_COORD, -55, 6680 }
+		{ SN_COORD, -55, 6680 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
@@ -326,10 +334,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4620, 5140 },
-		{ SN_COORD, -150, 6600 }
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
@@ -338,10 +347,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4750, 5280 },
-		{ SN_COORD, -150, 6730 }
+		{ SN_COORD, -150, 6730 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI,
@@ -350,10 +360,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4620, 5140 },
-		{ SN_COORD, -150, 6600 }
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
@@ -362,10 +373,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
+		{ SN_PRESSURE, 0, 300 },
 		{ SN_WIDTH, 0, 2048 },
 		{ SN_COORD, -4750, 5280 },
-		{ SN_COORD, -150, 6730 }
+		{ SN_COORD, -150, 6730 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{}
 };
@@ -402,6 +414,10 @@ static void setup_events_to_report(struct input_dev *input_dev,
 {
 	__set_bit(EV_ABS, input_dev->evbit);
 
+	/* for synaptics only */
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0);
+	input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0);
+
 	/* finger touch area */
 	set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
 	set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
@@ -462,6 +478,25 @@ static void report_finger_data(struct input_dev *input, int slot,
 	input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
 }
 
+static void report_synaptics_data(struct input_dev *input,
+				  const struct bcm5974_config *cfg,
+				  const struct tp_finger *f, int raw_n)
+{
+	int abs_p = 0, abs_w = 0;
+
+	if (raw_n) {
+		int p = raw2int(f->touch_major);
+		int w = raw2int(f->tool_major);
+		if (p > 0 && raw2int(f->origin)) {
+			abs_p = clamp_val(256 * p / cfg->p.max, 0, 255);
+			abs_w = clamp_val(16 * w / cfg->w.max, 0, 15);
+		}
+	}
+
+	input_report_abs(input, ABS_PRESSURE, abs_p);
+	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
+}
+
 /* report trackpad data as logical trackpad state */
 static int report_tp_state(struct bcm5974 *dev, int size)
 {
@@ -493,6 +528,8 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 
 	input_mt_sync_frame(input);
 
+	report_synaptics_data(input, c, f, raw_n);
+
 	/* type 2 reports button events via ibt only */
 	if (c->tp_type == TYPE2) {
 		int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
diff --git a/include/linux/input.h b/include/linux/input.h
index 797f335..ba48743 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1216,7 +1216,6 @@ struct input_value {
  * @timer: timer for software autorepeat
  * @rep: current values for autorepeat parameters (delay, rate)
  * @mt: pointer to multitouch state
- * @slot: MT slot currently being transmitted
  * @absinfo: array of &struct input_absinfo elements holding information
  *	about absolute axes (current value, min, max, flat, fuzz,
  *	resolution)
@@ -1296,7 +1295,6 @@ struct input_dev {
 	int rep[REP_CNT];
 
 	struct input_mt *mt;
-	int slot;
 
 	struct input_absinfo *absinfo;
 
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index bbdc694..cc5cca7 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -36,6 +36,7 @@ struct input_mt_slot {
  * struct input_mt - state of tracked contacts
  * @trkid: stores MT tracking ID for the next contact
  * @num_slots: number of MT slots the device uses
+ * @slot: MT slot currently being transmitted
  * @flags: input_mt operation flags
  * @frame: increases every time input_mt_sync_frame() is called
  * @red: reduced cost matrix for in-kernel tracking
@@ -44,6 +45,7 @@ struct input_mt_slot {
 struct input_mt {
 	int trkid;
 	int num_slots;
+	int slot;
 	unsigned int flags;
 	unsigned int frame;
 	int *red;

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: Input and HID updates for 3.7, version 4
  2012-09-15 15:33                     ` Input and HID updates for 3.7, version 4 Henrik Rydberg
@ 2012-09-18 11:29                       ` Jiri Kosina
  2012-09-18 16:19                         ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Jiri Kosina @ 2012-09-18 11:29 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Sat, 15 Sep 2012, Henrik Rydberg wrote:

> Ok, here is version 4 of the patchset. Rather than sending out all the
> patches again, the diff to linux-next is given below, and the
> refreshed tree can be pulled from
> 
>   git://github.com/rydberg/linux.git maybe
> 
> All Dmitry's comments are addressed. Changes in short:
> 
> * Also move 'slot' to input_mt
> * Oops fix amended
> * New patch to allow driver pressure handling
> * Keep the synaptics specials in bcm5974
> 
> Needless to say, I want to move this tree to linux-next soonish, so if
> there are more comments coming, I would appreciate a heads-up.

So if Dmitry has Acked all the input patches and I am going to take it, 
could you please send me either a proper pull request, or the patch series 
via e-mail, so that I could apply it?

Thanks Henrik,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: Input and HID updates for 3.7, version 4
  2012-09-18 11:29                       ` Jiri Kosina
@ 2012-09-18 16:19                         ` Henrik Rydberg
  2012-09-19 16:57                           ` Dmitry Torokhov
  0 siblings, 1 reply; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-18 16:19 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Dmitry Torokhov, linux-input, linux-kernel

On Tue, Sep 18, 2012 at 01:29:29PM +0200, Jiri Kosina wrote:
> On Sat, 15 Sep 2012, Henrik Rydberg wrote:
> 
> > Ok, here is version 4 of the patchset. Rather than sending out all the
> > patches again, the diff to linux-next is given below, and the
> > refreshed tree can be pulled from
> > 
> >   git://github.com/rydberg/linux.git maybe
> > 
> > All Dmitry's comments are addressed. Changes in short:
> > 
> > * Also move 'slot' to input_mt
> > * Oops fix amended
> > * New patch to allow driver pressure handling
> > * Keep the synaptics specials in bcm5974
> > 
> > Needless to say, I want to move this tree to linux-next soonish, so if
> > there are more comments coming, I would appreciate a heads-up.
> 
> So if Dmitry has Acked all the input patches and I am going to take it, 
> could you please send me either a proper pull request, or the patch series 
> via e-mail, so that I could apply it?

Absolutely, a pull request is the plan, but I have not heard anything
from Dmitry yet. Dmitry, no news is good news?

Thanks,
Henrik

ps. Two people got this mail twice, sorry about that.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: Input and HID updates for 3.7, version 4
  2012-09-18 16:19                         ` Henrik Rydberg
@ 2012-09-19 16:57                           ` Dmitry Torokhov
  2012-09-19 18:34                             ` Henrik Rydberg
  0 siblings, 1 reply; 49+ messages in thread
From: Dmitry Torokhov @ 2012-09-19 16:57 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: Jiri Kosina, linux-input, linux-kernel

On Tue, Sep 18, 2012 at 06:19:56PM +0200, Henrik Rydberg wrote:
> On Tue, Sep 18, 2012 at 01:29:29PM +0200, Jiri Kosina wrote:
> > On Sat, 15 Sep 2012, Henrik Rydberg wrote:
> > 
> > > Ok, here is version 4 of the patchset. Rather than sending out all the
> > > patches again, the diff to linux-next is given below, and the
> > > refreshed tree can be pulled from
> > > 
> > >   git://github.com/rydberg/linux.git maybe
> > > 
> > > All Dmitry's comments are addressed. Changes in short:
> > > 
> > > * Also move 'slot' to input_mt
> > > * Oops fix amended
> > > * New patch to allow driver pressure handling
> > > * Keep the synaptics specials in bcm5974
> > > 
> > > Needless to say, I want to move this tree to linux-next soonish, so if
> > > there are more comments coming, I would appreciate a heads-up.
> > 
> > So if Dmitry has Acked all the input patches and I am going to take it, 
> > could you please send me either a proper pull request, or the patch series 
> > via e-mail, so that I could apply it?
> 
> Absolutely, a pull request is the plan, but I have not heard anything
> from Dmitry yet. Dmitry, no news is good news?

Yep, and sorry for the delay.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: Input and HID updates for 3.7, version 4
  2012-09-19 16:57                           ` Dmitry Torokhov
@ 2012-09-19 18:34                             ` Henrik Rydberg
  0 siblings, 0 replies; 49+ messages in thread
From: Henrik Rydberg @ 2012-09-19 18:34 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Jiri Kosina, linux-input, linux-kernel

On Wed, Sep 19, 2012 at 09:57:07AM -0700, Dmitry Torokhov wrote:
> On Tue, Sep 18, 2012 at 06:19:56PM +0200, Henrik Rydberg wrote:
> > On Tue, Sep 18, 2012 at 01:29:29PM +0200, Jiri Kosina wrote:
> > > On Sat, 15 Sep 2012, Henrik Rydberg wrote:
> > > 
> > > > Ok, here is version 4 of the patchset. Rather than sending out all the
> > > > patches again, the diff to linux-next is given below, and the
> > > > refreshed tree can be pulled from
> > > > 
> > > >   git://github.com/rydberg/linux.git maybe
> > > > 
> > > > All Dmitry's comments are addressed. Changes in short:
> > > > 
> > > > * Also move 'slot' to input_mt
> > > > * Oops fix amended
> > > > * New patch to allow driver pressure handling
> > > > * Keep the synaptics specials in bcm5974
> > > > 
> > > > Needless to say, I want to move this tree to linux-next soonish, so if
> > > > there are more comments coming, I would appreciate a heads-up.
> > > 
> > > So if Dmitry has Acked all the input patches and I am going to take it, 
> > > could you please send me either a proper pull request, or the patch series 
> > > via e-mail, so that I could apply it?
> > 
> > Absolutely, a pull request is the plan, but I have not heard anything
> > from Dmitry yet. Dmitry, no news is good news?
> 
> Yep, and sorry for the delay.

Thanks, Dmitry. I will send out a pull request shortly.

Henrik

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2012-09-19 18:34 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-01 19:46 [PATCH v3 v3 00/20] Input and HID updates for 3.7 Henrik Rydberg
2012-09-01 19:46 ` [PATCH v3 01/20] Input: Break out MT data Henrik Rydberg
2012-09-13  5:15   ` Dmitry Torokhov
2012-09-13 17:58     ` Henrik Rydberg
2012-09-01 19:46 ` [PATCH v3 02/20] Input: Improve the events-per-packet estimate Henrik Rydberg
2012-09-13  5:16   ` Dmitry Torokhov
2012-09-01 19:46 ` [PATCH v3 03/20] Input: Make sure we follow all EV_KEY events Henrik Rydberg
2012-09-13  5:19   ` Dmitry Torokhov
2012-09-01 19:46 ` [PATCH v3 04/20] Input: Move autorepeat to the event-passing phase Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 05/20] Input: Send events one packet at a time Henrik Rydberg
2012-09-13  6:56   ` Dmitry Torokhov
2012-09-13 17:59     ` Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 06/20] Input: evdev - Add the events() callback Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 07/20] Input: MT - Add flags to input_mt_init_slots() Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 08/20] Input: MT - Handle frame synchronization in core Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 09/20] Input: MT - Add in-kernel tracking Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 10/20] Input: MT - Get slot by key Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 11/20] Input: bcm5974 - only setup button urb for TYPE1 devices Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 12/20] Input: bcm5974 - Preparatory renames Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 13/20] Input: bcm5974 - Drop pressure and width emulation Henrik Rydberg
2012-09-13  6:57   ` Dmitry Torokhov
2012-09-13 18:41     ` Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 14/20] Input: bcm5974 - Drop the logical dimensions Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 15/20] Input: bcm5974 - Convert to MT-B Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 16/20] HID: Only dump input if someone is listening Henrik Rydberg
2012-09-02  7:28   ` Jiri Kosina
2012-09-02  8:52     ` Henrik Rydberg
2012-09-03 13:17       ` Jiri Kosina
2012-09-06 20:57         ` Henrik Rydberg
2012-09-07  1:54           ` Ping Cheng
2012-09-07 12:52           ` Jiri Kosina
2012-09-10 19:02             ` Henrik Rydberg
2012-09-10 20:49               ` Jiri Kosina
2012-09-10 21:12                 ` Dmitry Torokhov
2012-09-14 19:25                   ` Henrik Rydberg
2012-09-15 15:33                     ` Input and HID updates for 3.7, version 4 Henrik Rydberg
2012-09-18 11:29                       ` Jiri Kosina
2012-09-18 16:19                         ` Henrik Rydberg
2012-09-19 16:57                           ` Dmitry Torokhov
2012-09-19 18:34                             ` Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 17/20] HID: Add an input configured notification callback Henrik Rydberg
2012-09-01 19:47 ` Henrik Rydberg
2012-09-01 19:47 ` [PATCH v3 19/20] HID: hid-multitouch: Remove the redundant touch state Henrik Rydberg
2012-09-01 19:47 ` [PATCH 20/20] HID: hid-multitouch: Add missing contact count detection Henrik Rydberg
2012-09-03 12:59   ` Benjamin Tissoires
2012-09-03 17:07     ` Henrik Rydberg
2012-09-05 15:09     ` [PATCH v2 20/20] HID: hid-multitouch: Fix contact count on 3M panels Henrik Rydberg
2012-09-03 13:00 ` [PATCH v3 v3 00/20] Input and HID updates for 3.7 Benjamin Tissoires
2012-09-03 17:08   ` Henrik Rydberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).