diff mbox

[2/4] Input: Report defuzzed event once before filtering for devices with the INCONSISTENT_RATE property

Message ID 1307735704-30673-3-git-send-email-derek.foreman@collabora.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Derek Foreman June 10, 2011, 7:55 p.m. UTC
Some input devices have a non-uniform report rate, which can make it difficult for a userspace driver to distinguish between a lack of motion or a lack of new input.

With this patch, if multiple duplicate events (after defuzz) are received in a row, the first duplicate is posted to userspace.

Signed-off-by: Derek Foreman <derek.foreman@collabora.co.uk>
---
 drivers/input/input.c |   22 +++++++++++++++++++---
 include/linux/input.h |    4 ++++
 2 files changed, 23 insertions(+), 3 deletions(-)

Comments

Henrik Rydberg June 10, 2011, 8:56 p.m. UTC | #1
On Fri, Jun 10, 2011 at 03:55:02PM -0400, Derek Foreman wrote:
> Some input devices have a non-uniform report rate, which can make it difficult for a userspace driver to distinguish between a lack of motion or a lack of new input.
> 
> With this patch, if multiple duplicate events (after defuzz) are received in a row, the first duplicate is posted to userspace.

Every change is already propagated exactly once, which seems to amount
to the same thing your patch is aiming at. The evdev event signifies
the change itself (and when it occurs), so there is actually no
difference between the lack of motion and the lack of input.

Thanks, Henrik
--
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
Derek Foreman June 13, 2011, 2:19 p.m. UTC | #2
On 06/10/11 16:56, Henrik Rydberg wrote:
> On Fri, Jun 10, 2011 at 03:55:02PM -0400, Derek Foreman wrote:
>> Some input devices have a non-uniform report rate, which can make it difficult for a userspace driver to distinguish between a lack of motion or a lack of new input.
>>
>> With this patch, if multiple duplicate events (after defuzz) are received in a row, the first duplicate is posted to userspace.
>
> Every change is already propagated exactly once, which seems to amount
> to the same thing your patch is aiming at. The evdev event signifies
> the change itself (and when it occurs), so there is actually no
> difference between the lack of motion and the lack of input.

Hi Henrik,

Thank you for all your input.

The specific problem that this patch aims to solve is that a certain 
family of synaptics devices drops from 80Hz to 40Hz reporting when 2 or 
more fingers are on the pad.  As the screen refresh rate for a modern PC 
is generally 60Hz, input feels subjectively much less interactive.

It is possible - by maintaining a short history of past events and 
predicting where the cursor would be in the future - to do a reasonable 
job of creating 60Hz motion from this lower input rate.  This is where 
the difference between lack of motion and lack of input is key.

If I receive an event, then 1/80th of a second later I do NOT receive 
another one, I don't know whether the device has dropped to a lower 
reporting rate (lack of input), or whether the device reported the same 
event 2 times in a row, and the kernel "defuzz" code filtered it (lack 
of motion).

In the "lack of input" case, I want to fabricate a synthetic event to 
keep the pointer motion fluid.  In the "lack of motion" case, I want 
pointer motion to stop.

Currently, the kernel knows it has started to filter unchanging input, 
but userspace has no mechanism to detect that this filtering has begun. 
  As two identical events in a row is an impossibility in the face of 
the defuzz code, I had thought this would be a good way to expose this 
information without confusing any existing applications...

Thanks,
Derek
--
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
diff mbox

Patch

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 75e11c7..5c7af82 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -198,8 +198,15 @@  static int input_handle_abs_event(struct input_dev *dev,
 	if (pold) {
 		*pval = input_defuzz_abs_event(*pval, *pold,
 						dev->absinfo[code].fuzz);
-		if (*pold == *pval)
-			return INPUT_IGNORE_EVENT;
+		if (*pold == *pval) {
+			if (!test_bit(INPUT_PROP_INCONSISTENT_RATE,
+				      dev->propbit)
+			    || dev->reposted[code])
+				return INPUT_IGNORE_EVENT;
+			else
+				dev->reposted[code] = 1;
+		} else
+			dev->reposted[code] = 0;
 
 		*pold = *pval;
 	}
@@ -405,6 +412,14 @@  void input_alloc_absinfo(struct input_dev *dev)
 					GFP_KERNEL);
 
 	WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
+
+	if (!dev->absinfo)
+		return;
+
+	if (!dev->reposted)
+		dev->reposted = kcalloc(ABS_CNT, sizeof(bool), GFP_KERNEL);
+
+	WARN(!dev->reposted, "%s(): kcalloc() failed?\n", __func__);
 }
 EXPORT_SYMBOL(input_alloc_absinfo);
 
@@ -414,7 +429,7 @@  void input_set_abs_params(struct input_dev *dev, unsigned int axis,
 	struct input_absinfo *absinfo;
 
 	input_alloc_absinfo(dev);
-	if (!dev->absinfo)
+	if (!dev->absinfo || !dev->reposted)
 		return;
 
 	absinfo = &dev->absinfo[axis];
@@ -1416,6 +1431,7 @@  static void input_dev_release(struct device *device)
 	input_ff_destroy(dev);
 	input_mt_destroy_slots(dev);
 	kfree(dev->absinfo);
+	kfree(dev->reposted);
 	kfree(dev);
 
 	module_put(THIS_MODULE);
diff --git a/include/linux/input.h b/include/linux/input.h
index f8a0c2d..388cdef 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1178,6 +1178,9 @@  struct ff_effect {
  * @absinfo: array of &struct input_absinfo elements holding information
  *	about absolute axes (current value, min, max, flat, fuzz,
  *	resolution)
+ * @reposted: boolean for each absinfo indicating whether the current
+ *	value has been posted a second time and the defuzz algorithm
+ *	can remove subsequent identical values
  * @key: reflects current state of device's keys/buttons
  * @led: reflects current state of device's LEDs
  * @snd: reflects current state of sound effects
@@ -1260,6 +1263,7 @@  struct input_dev {
 	int trkid;
 
 	struct input_absinfo *absinfo;
+	bool *reposted;
 
 	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
 	unsigned long led[BITS_TO_LONGS(LED_CNT)];