diff mbox

[09/12] Input: synaptics - add image sensor support

Message ID 1309324042-22943-10-git-send-email-djkurtz@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Kurtz June 29, 2011, 5:07 a.m. UTC
From: Daniel Kurtz <djkurtz@chromium.org>

Synaptics makes (at least) two kinds of touchpad sensors:
 * Older pads use a profile sensor that could only infer the location
   of individual fingers based on the projection of their profiles
   onto row and column sensors.
 * Newer pads use an image sensor that can track true finger position
   using a two-dimensional sensor grid.

Both sensor types support an "Advanced Gesture Mode":
 When multiple fingers are detected, the touchpad sends alternating
 "Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
 packets.
 The AGM packets have w=2, and contain reduced resolution finger data
 The SGM packets have w={0,1} and contain full resolution finger data

Profile sensors try to report the "upper" (larger y value) finger in
 the SGM packet, and the lower (smaller y value) in the AGM packet.
 However, due to the nature of the profile sensor, they easily get
 confused when fingers cross, and can start reporting the x-coordinate
 of one with the y-coordinate of the other.  Thus, for profile
 sensors, "semi-mt" was created, which reports a "bounding box"
 created by pairing min and max coordinates of the two pairs of
 reported fingers.

Image sensors can report the actual coordinates of two of the fingers
 present.  This patch detects if the touchpad is an image sensor and
 reports finger data using the MT-B protocol.

NOTE: This patch only adds partial support for 2-finger gestures.
      The proper interpretation of the slot contents when more than
      two fingers are present is left to later patches.  Also,
      handling of 'number of fingers' transitions is incomplete.

Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
---
 drivers/input/mouse/synaptics.c |  116 ++++++++++++++++++++++++++++++++++++++-
 drivers/input/mouse/synaptics.h |   13 ++++
 2 files changed, 126 insertions(+), 3 deletions(-)

Comments

Henrik Rydberg July 4, 2011, 9:42 p.m. UTC | #1
Hi Daniel,

> Synaptics makes (at least) two kinds of touchpad sensors:
>  * Older pads use a profile sensor that could only infer the location
>    of individual fingers based on the projection of their profiles
>    onto row and column sensors.
>  * Newer pads use an image sensor that can track true finger position
>    using a two-dimensional sensor grid.
> 
> Both sensor types support an "Advanced Gesture Mode":
>  When multiple fingers are detected, the touchpad sends alternating
>  "Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
>  packets.
>  The AGM packets have w=2, and contain reduced resolution finger data
>  The SGM packets have w={0,1} and contain full resolution finger data
> 
> Profile sensors try to report the "upper" (larger y value) finger in
>  the SGM packet, and the lower (smaller y value) in the AGM packet.
>  However, due to the nature of the profile sensor, they easily get
>  confused when fingers cross, and can start reporting the x-coordinate
>  of one with the y-coordinate of the other.  Thus, for profile
>  sensors, "semi-mt" was created, which reports a "bounding box"
>  created by pairing min and max coordinates of the two pairs of
>  reported fingers.
> 
> Image sensors can report the actual coordinates of two of the fingers
>  present.  This patch detects if the touchpad is an image sensor and
>  reports finger data using the MT-B protocol.
> 
> NOTE: This patch only adds partial support for 2-finger gestures.
>       The proper interpretation of the slot contents when more than
>       two fingers are present is left to later patches.  Also,
>       handling of 'number of fingers' transitions is incomplete.
> 
> Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>

I guess the real question here is: do the following patches really
help? Creating additional logic to band-aid yet another special case,
which still does not give full MT support, seems to create more
problems than it solves. If the code was needed to ensure proper five
finger support to userspace, then maybe one could live with
it. However, as it stands, keeping the semi-mt behavior also for the
slightly better devices may not be such a bad idea, after all.

_Iff_ the whole series can be formulated as true protocol B support
(no special flags, please), and _iff_ it helps to use software finger
tracking for less than four fingers, then please do tell, and we can
add that part to the input core to simplify the synaptics
implementation a bit.

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
Daniel Kurtz July 5, 2011, 5:08 a.m. UTC | #2
Hi Henrik,

On Tue, Jul 5, 2011 at 5:42 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
> Hi Daniel,
>
>> Synaptics makes (at least) two kinds of touchpad sensors:
>>  * Older pads use a profile sensor that could only infer the location
>>    of individual fingers based on the projection of their profiles
>>    onto row and column sensors.
>>  * Newer pads use an image sensor that can track true finger position
>>    using a two-dimensional sensor grid.
>>
>> Both sensor types support an "Advanced Gesture Mode":
>>  When multiple fingers are detected, the touchpad sends alternating
>>  "Advanced Gesture Mode" (AGM) and "Simple Gesture Mode" (SGM)
>>  packets.
>>  The AGM packets have w=2, and contain reduced resolution finger data
>>  The SGM packets have w={0,1} and contain full resolution finger data
>>
>> Profile sensors try to report the "upper" (larger y value) finger in
>>  the SGM packet, and the lower (smaller y value) in the AGM packet.
>>  However, due to the nature of the profile sensor, they easily get
>>  confused when fingers cross, and can start reporting the x-coordinate
>>  of one with the y-coordinate of the other.  Thus, for profile
>>  sensors, "semi-mt" was created, which reports a "bounding box"
>>  created by pairing min and max coordinates of the two pairs of
>>  reported fingers.
>>
>> Image sensors can report the actual coordinates of two of the fingers
>>  present.  This patch detects if the touchpad is an image sensor and
>>  reports finger data using the MT-B protocol.
>>
>> NOTE: This patch only adds partial support for 2-finger gestures.
>>       The proper interpretation of the slot contents when more than
>>       two fingers are present is left to later patches.  Also,
>>       handling of 'number of fingers' transitions is incomplete.
>>
>> Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
>
> I guess the real question here is: do the following patches really
> help? Creating additional logic to band-aid yet another special case,
> which still does not give full MT support, seems to create more
> problems than it solves. If the code was needed to ensure proper five
> finger support to userspace, then maybe one could live with
> it. However, as it stands, keeping the semi-mt behavior also for the
> slightly better devices may not be such a bad idea, after all.
>
> _Iff_ the whole series can be formulated as true protocol B support
> (no special flags, please), and _iff_ it helps to use software finger
> tracking for less than four fingers, then please do tell, and we can
> add that part to the input core to simplify the synaptics
> implementation a bit.

Image sensors and profile sensors behave differently.  However, even
the image sensors do not allow true MT-B, since they only report 2
fingers.  Hence, it makes sense to add a property to distinguish the 3
cases.

This implementation addresses the following issues:

  (1) Improves handling of the 2-finger case.  Image sensors due allow
true MT-B for two finger case.  This, for example, allows detecting
whether the click in a click+drag is happening in bottom right or
bottom left quadrant of the pad.

  (2) Helps improve handling of number-of-fingers transitions.  Most
of the complexity of the synaptics driver comes with dealing with the
complicated way that the protocol handles number-of-fingers
transitions.  Just ignoring them with semi-mt could cause lots of
jumpy behavior as the transitions are mapped to bounding boxes whose
coordinates jump around.  Thus, this implementation tries to notify
userspace of finger transition by 'rolling slots' when necessary.
What I mean is, if the driver deduces that a given slot may not
contain the same finger as a previous report, it releases it (sets its
tracking_id = -1), and reestablishes the slot with a new tracking_id
when it is more confident that it is now tracking a new finger.

  (3) Properly decode the "AGM_CONTACT" packet type.  4- and 5- finger
gestures may never be supported, however, I think it is still a good
idea to detect and parse these packets properly in the kernel driver,
and leave policy to userspace.  I'm open to alternative suggestions
for ways to represent this to userspace.  The idea in this patch set
is to reuse the MT-B plumbing as much as possible, but use the device
property to mark the fact that the interpretation of the resulting
slots is somewhat different.

A bare minimum patchset might do:
   (1) Do true MT-B for two fingers
   (2) Improved number-of-finger tracking for just the 2-finger case.
(Keep tracking finger 1 when finger 2 is removed, and vice versa)
   (3) Properly parse, but don't use, AGM_CONTACT packets

We can then argue about what to do with 3+ fingers :).

Thanks,
Daniel

>
> 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
Henrik Rydberg July 5, 2011, 7:27 p.m. UTC | #3
> > I guess the real question here is: do the following patches really
> > help? Creating additional logic to band-aid yet another special case,
> > which still does not give full MT support, seems to create more
> > problems than it solves. If the code was needed to ensure proper five
> > finger support to userspace, then maybe one could live with
> > it. However, as it stands, keeping the semi-mt behavior also for the
> > slightly better devices may not be such a bad idea, after all.
> >
> > _Iff_ the whole series can be formulated as true protocol B support
> > (no special flags, please), and _iff_ it helps to use software finger
> > tracking for less than four fingers, then please do tell, and we can
> > add that part to the input core to simplify the synaptics
> > implementation a bit.
> 
> Image sensors and profile sensors behave differently.  However, even
> the image sensors do not allow true MT-B, since they only report 2
> fingers.  Hence, it makes sense to add a property to distinguish the 3
> cases.

The lifetime of such a solution should also be considered.

> This implementation addresses the following issues:
> 
>   (1) Improves handling of the 2-finger case.  Image sensors due allow
> true MT-B for two finger case.  This, for example, allows detecting
> whether the click in a click+drag is happening in bottom right or
> bottom left quadrant of the pad.

In principle, this could be done within the semi-mt realm by adding a
binary value to the protocol, distinguishing the diagonals of the
bounding box. It would be ugly too, but at least it would be
compatible with the current semi-mt effort in userspace.

>   (2) Helps improve handling of number-of-fingers transitions.  Most
> of the complexity of the synaptics driver comes with dealing with the
> complicated way that the protocol handles number-of-fingers
> transitions.  Just ignoring them with semi-mt could cause lots of
> jumpy behavior as the transitions are mapped to bounding boxes whose
> coordinates jump around.  Thus, this implementation tries to notify
> userspace of finger transition by 'rolling slots' when necessary.

If the kernel driver cannot create a smooth bounding box, which by all
means is simpler than providing proper finger tracking, then there is
no way this can be done in userspace either.

> What I mean is, if the driver deduces that a given slot may not
> contain the same finger as a previous report, it releases it (sets its
> tracking_id = -1), and reestablishes the slot with a new tracking_id
> when it is more confident that it is now tracking a new finger.

As a general question, one might ask oneself: If the new device
_really_ can track five fingers, then why does it not send enough
information to recover that information? A proper tracking id would
suffice.

>   (3) Properly decode the "AGM_CONTACT" packet type.  4- and 5- finger
> gestures may never be supported, however, I think it is still a good
> idea to detect and parse these packets properly in the kernel driver,
> and leave policy to userspace.  I'm open to alternative suggestions
> for ways to represent this to userspace.  The idea in this patch set
> is to reuse the MT-B plumbing as much as possible, but use the device
> property to mark the fact that the interpretation of the resulting
> slots is somewhat different.

If the data cannot be reliably utilized, I doubt anyone cares.  There
is a lot of hardware out there capable of tracking ten and more
fingers, without the agonizing pain.

> A bare minimum patchset might do:
>    (1) Do true MT-B for two fingers
>    (2) Improved number-of-finger tracking for just the 2-finger case.
> (Keep tracking finger 1 when finger 2 is removed, and vice versa)

In what way is this different from 1)?

>    (3) Properly parse, but don't use, AGM_CONTACT packets

I am tempted to write something about Schrödinger's cat here... ;-)

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
Daniel Kurtz July 6, 2011, 4:41 p.m. UTC | #4
On Wed, Jul 6, 2011 at 3:27 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
>> ...
>> This implementation addresses the following issues:
>>
>>   (1) Improves handling of the 2-finger case.  Image sensors due allow
>> true MT-B for two finger case.  This, for example, allows detecting
>> whether the click in a click+drag is happening in bottom right or
>> bottom left quadrant of the pad.
>
> In principle, this could be done within the semi-mt realm by adding a
> binary value to the protocol, distinguishing the diagonals of the
> bounding box. It would be ugly too, but at least it would be
> compatible with the current semi-mt effort in userspace.

(A) I think the "semi-mt" protocol works like this:
  (1) When two or more fingers are on the pad, report two MT-B slots, where:
    (a) slot[0] contains (x_min, y_min) of the two fingers
    (b) slot[1] contains (x_max, y_max) of the two fingers
    (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
  (2) If one of the two fingers is removed, then the first slot is
used to report
      the remaining finger, whichever it is, without changing the
slot's tracking_id.
  (3) Advertise this behavior with the SEMI_MT device property

(B) This is what the proposed T5R2 driver does:
  (1) When N fingers are on the pad, report N MT-B slots, where:
    (a) The lowest indexed active slot (tracking_id != -1) contains
valid finger position data.
    (b) The highest indexed active slot (tracking_id != -1) contains
valid finger position data.
    (c) Any active slots (tracking_id != -1) between these does not
contain valid finger position data, these 'hidden' slots are just
active to indicate that there are that many fingers on the pad.
    (d) Total number of fingers on the pad is always the number of active slots.
  (2) When fingers are removed from the pad:
    (a) keep reporting the fingers that are left in the same slots,
with the same tracking_ids, if possible.
    (b) If the identities of the fingers that remain is ambiguous,
invalidate all slots,then re-assign the fingers that remain to new
slots, with new tracking ids.
  (3) Advertise this behavior with the T5R2 device property

(C) A third, compromise implementation might be to do something like this:
  (1) When >=2 fingers are on the pad, report 2 MT-B slots, where:
    (a) slot[0] reports finger 1
    (b) slot[1] reports finger 2
    (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
  (2) If 1 finger is removed, the tracking_id for its slot is invalidated;
      but, the finger that remains stays in its same slot with the
same tracking_id.
  (3) Whenever the number of fingers changes from/to 3 or more
fingers, both slots are always invalidated.
      New tracking_ids are assigned to both slots which contain the
two fingers now being reported.
  (4) No special driver property is required for this, not even "semi-mt".
      It should be as pure MT-B as we can get (plus BTN_TOOL_* hack).


IMHO, (C) is an improvement over (A) for two major reasons:
  (1) tracking the individual touches allows distinguishing a clicking
finger in bottom right versus bottom left, for example.
  (2) It makes it possible to track the touch that remains when one of
the two touches is released.
      The touch that remains will stay in the same slot, with the same
tracking id.
      The tracking id of the touch that is removed will be set to -1.
        => This eliminates unnecessary gaps in the event stream,
without introducing position jumps.
      This behavior occurs often when switching between 1-finger
motion and 2f-scroll, or when performing 2f-click+drag gestures.

Note: Tracking which fingers are left on the pad gets much more
complicated with 3, 4, or 5 fingers.
This is addressed more fully by the T5R2 solution, but (C), while
slightly less optimal, should at least not do the wrong thing.

Sorry, I find it a bit difficult to explain this clearly in writing.
I guess I'll just have to submit a new patchset that shows what I mean.


>> A bare minimum patchset might do:
>>    (1) Do true MT-B for two fingers
>>    (2) Improved number-of-finger tracking for just the 2-finger case.
>> (Keep tracking finger 1 when finger 2 is removed, and vice versa)
>
> In what way is this different from 1)?
>
>>    (3) Properly parse, but don't use, AGM_CONTACT packets

The image sensor AGM mode acts different than the profile sensor.  For
the profile sensor, there is always one AGM for every SGM when 2 or
more fingers are present.  With the image sensor, there may be more 1
AGM per SGM if the number of fingers is changing - especially when
there are more than 3 fingers present.  This is what I meant by
properly parse these packets.  At least it is a form of documentation
for the next poor guy who comes along and tries to figure out what in
the world his trackpad is sending him.

Thanks,
-Daniel

>
> I am tempted to write something about Schrödinger's cat here... ;-)
>
> 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
Chase Douglas July 6, 2011, 5:08 p.m. UTC | #5
On 07/06/2011 09:41 AM, Daniel Kurtz wrote:
> On Wed, Jul 6, 2011 at 3:27 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
>>> ...
>>> This implementation addresses the following issues:
>>>
>>>   (1) Improves handling of the 2-finger case.  Image sensors due allow
>>> true MT-B for two finger case.  This, for example, allows detecting
>>> whether the click in a click+drag is happening in bottom right or
>>> bottom left quadrant of the pad.
>>
>> In principle, this could be done within the semi-mt realm by adding a
>> binary value to the protocol, distinguishing the diagonals of the
>> bounding box. It would be ugly too, but at least it would be
>> compatible with the current semi-mt effort in userspace.
> 
> (A) I think the "semi-mt" protocol works like this:
>   (1) When two or more fingers are on the pad, report two MT-B slots, where:
>     (a) slot[0] contains (x_min, y_min) of the two fingers
>     (b) slot[1] contains (x_max, y_max) of the two fingers
>     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
>   (2) If one of the two fingers is removed, then the first slot is
> used to report
>       the remaining finger, whichever it is, without changing the
> slot's tracking_id.
>   (3) Advertise this behavior with the SEMI_MT device property
> 
> (B) This is what the proposed T5R2 driver does:
>   (1) When N fingers are on the pad, report N MT-B slots, where:
>     (a) The lowest indexed active slot (tracking_id != -1) contains
> valid finger position data.
>     (b) The highest indexed active slot (tracking_id != -1) contains
> valid finger position data.
>     (c) Any active slots (tracking_id != -1) between these does not
> contain valid finger position data, these 'hidden' slots are just
> active to indicate that there are that many fingers on the pad.
>     (d) Total number of fingers on the pad is always the number of active slots.
>   (2) When fingers are removed from the pad:
>     (a) keep reporting the fingers that are left in the same slots,
> with the same tracking_ids, if possible.
>     (b) If the identities of the fingers that remain is ambiguous,
> invalidate all slots,then re-assign the fingers that remain to new
> slots, with new tracking ids.
>   (3) Advertise this behavior with the T5R2 device property
> 
> (C) A third, compromise implementation might be to do something like this:
>   (1) When >=2 fingers are on the pad, report 2 MT-B slots, where:
>     (a) slot[0] reports finger 1
>     (b) slot[1] reports finger 2
>     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
>   (2) If 1 finger is removed, the tracking_id for its slot is invalidated;
>       but, the finger that remains stays in its same slot with the
> same tracking_id.
>   (3) Whenever the number of fingers changes from/to 3 or more
> fingers, both slots are always invalidated.
>       New tracking_ids are assigned to both slots which contain the
> two fingers now being reported.
>   (4) No special driver property is required for this, not even "semi-mt".
>       It should be as pure MT-B as we can get (plus BTN_TOOL_* hack).

This approach seems better, but there's still an ambiguity. When we go
from two to three or more fingers we get lossy. We can't tell what
touches cross the transition with their data intact.

I'm racking my brain trying to come up with a solution that would make
sense, but I don't think there is one that works seamlessly. I think we
should do what you've written above with two changes:

* Use a new property (T5R2?) to fully denote how screwed up this class
of devices is.
* Don't roll the tracking_id on any number of touch transitions. We're
already telling userspace that the number of touches is changing, so the
tracking_id change is superfluous. The tracking_id of a slot should only
change when we know that the touch is beginning or ending.

No matter what we do, userspace will have to rely on complex heuristics
for this device, which makes me wonder if these devices will really ever
be handled properly...

> IMHO, (C) is an improvement over (A) for two major reasons:
>   (1) tracking the individual touches allows distinguishing a clicking
> finger in bottom right versus bottom left, for example.
>   (2) It makes it possible to track the touch that remains when one of
> the two touches is released.
>       The touch that remains will stay in the same slot, with the same
> tracking id.
>       The tracking id of the touch that is removed will be set to -1.
>         => This eliminates unnecessary gaps in the event stream,
> without introducing position jumps.
>       This behavior occurs often when switching between 1-finger
> motion and 2f-scroll, or when performing 2f-click+drag gestures.
> 
> Note: Tracking which fingers are left on the pad gets much more
> complicated with 3, 4, or 5 fingers.
> This is addressed more fully by the T5R2 solution, but (C), while
> slightly less optimal, should at least not do the wrong thing.
> 
> Sorry, I find it a bit difficult to explain this clearly in writing.
> I guess I'll just have to submit a new patchset that shows what I mean.

You're not the first to be tied up trying to document Synaptics behavior :).

Thanks!

-- Chase
--
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
Dmitry Torokhov July 6, 2011, 5:45 p.m. UTC | #6
On Thu, Jul 07, 2011 at 12:41:26AM +0800, Daniel Kurtz wrote:
> On Wed, Jul 6, 2011 at 3:27 AM, Henrik Rydberg <rydberg@euromail.se> wrote:
> >> ...
> >> This implementation addresses the following issues:
> >>
> >>   (1) Improves handling of the 2-finger case.  Image sensors due allow
> >> true MT-B for two finger case.  This, for example, allows detecting
> >> whether the click in a click+drag is happening in bottom right or
> >> bottom left quadrant of the pad.
> >
> > In principle, this could be done within the semi-mt realm by adding a
> > binary value to the protocol, distinguishing the diagonals of the
> > bounding box. It would be ugly too, but at least it would be
> > compatible with the current semi-mt effort in userspace.
> 
> (A) I think the "semi-mt" protocol works like this:
>   (1) When two or more fingers are on the pad, report two MT-B slots, where:
>     (a) slot[0] contains (x_min, y_min) of the two fingers
>     (b) slot[1] contains (x_max, y_max) of the two fingers
>     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
>   (2) If one of the two fingers is removed, then the first slot is
> used to report
>       the remaining finger, whichever it is, without changing the
> slot's tracking_id.
>   (3) Advertise this behavior with the SEMI_MT device property
> 
> (B) This is what the proposed T5R2 driver does:
>   (1) When N fingers are on the pad, report N MT-B slots, where:
>     (a) The lowest indexed active slot (tracking_id != -1) contains
> valid finger position data.
>     (b) The highest indexed active slot (tracking_id != -1) contains
> valid finger position data.
>     (c) Any active slots (tracking_id != -1) between these does not
> contain valid finger position data, these 'hidden' slots are just
> active to indicate that there are that many fingers on the pad.
>     (d) Total number of fingers on the pad is always the number of active slots.
>   (2) When fingers are removed from the pad:
>     (a) keep reporting the fingers that are left in the same slots,
> with the same tracking_ids, if possible.
>     (b) If the identities of the fingers that remain is ambiguous,
> invalidate all slots,then re-assign the fingers that remain to new
> slots, with new tracking ids.
>   (3) Advertise this behavior with the T5R2 device property
> 

This is a no-go. I do not want to add TxRy or similar "properties". We
have a workable semi-mt (counding box) and full mt concepts and we
should present userspace with data stream that conforms either one or
another.

> (C) A third, compromise implementation might be to do something like this:
>   (1) When >=2 fingers are on the pad, report 2 MT-B slots, where:
>     (a) slot[0] reports finger 1
>     (b) slot[1] reports finger 2
>     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
>   (2) If 1 finger is removed, the tracking_id for its slot is invalidated;
>       but, the finger that remains stays in its same slot with the
> same tracking_id.
>   (3) Whenever the number of fingers changes from/to 3 or more
> fingers, both slots are always invalidated.
>       New tracking_ids are assigned to both slots which contain the
> two fingers now being reported.
>   (4) No special driver property is required for this, not even "semi-mt".
>       It should be as pure MT-B as we can get (plus BTN_TOOL_* hack).
> 

This is the best option in my opinion. We will present 2 finger position
data plus extended finger count.

Thanks.
Henrik Rydberg July 6, 2011, 6:47 p.m. UTC | #7
> > (C) A third, compromise implementation might be to do something like this:
> >   (1) When >=2 fingers are on the pad, report 2 MT-B slots, where:
> >     (a) slot[0] reports finger 1
> >     (b) slot[1] reports finger 2
> >     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
> >   (2) If 1 finger is removed, the tracking_id for its slot is invalidated;
> >       but, the finger that remains stays in its same slot with the
> > same tracking_id.
> >   (3) Whenever the number of fingers changes from/to 3 or more
> > fingers, both slots are always invalidated.
> >       New tracking_ids are assigned to both slots which contain the
> > two fingers now being reported.
> >   (4) No special driver property is required for this, not even "semi-mt".
> >       It should be as pure MT-B as we can get (plus BTN_TOOL_* hack).

I believe there is a strong userspace assumption that BTN_TOOL_* has
no meaning for real MT devices. Rightfully so, IMO. Hence, I think
semi-mt needs to be used here as well.

> > 
> 
> This is the best option in my opinion. We will present 2 finger position
> data plus extended finger count.

We never did put all the details of the bounding box coordinates in
writing, so perhaps this is an opportunity to both fix that and extend
usability to the case so described. The only question is whether there
are applications out there which now assume min/max instead of contact
positions. If anyone knows, please speak up. :-) Otherwise, I am very
much for Daniel's case C, with Dmitry's modification.

In short: Use the semi-MT property, and send two suitable fingers
along with it.

Cheers,
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
Dmitry Torokhov July 6, 2011, 6:58 p.m. UTC | #8
On Wed, Jul 06, 2011 at 08:47:59PM +0200, Henrik Rydberg wrote:
> > > (C) A third, compromise implementation might be to do something like this:
> > >   (1) When >=2 fingers are on the pad, report 2 MT-B slots, where:
> > >     (a) slot[0] reports finger 1
> > >     (b) slot[1] reports finger 2
> > >     (c) Total number of fingers on pad is indicated by EV_KEY/BTN_TOOL_* is set.
> > >   (2) If 1 finger is removed, the tracking_id for its slot is invalidated;
> > >       but, the finger that remains stays in its same slot with the
> > > same tracking_id.
> > >   (3) Whenever the number of fingers changes from/to 3 or more
> > > fingers, both slots are always invalidated.
> > >       New tracking_ids are assigned to both slots which contain the
> > > two fingers now being reported.
> > >   (4) No special driver property is required for this, not even "semi-mt".
> > >       It should be as pure MT-B as we can get (plus BTN_TOOL_* hack).
> 
> I believe there is a strong userspace assumption that BTN_TOOL_* has
> no meaning for real MT devices. Rightfully so, IMO. Hence, I think
> semi-mt needs to be used here as well.

I think we need to adjust userspace to pay attention to BTN_TOOL_* for
MT-B too so that if number of slots advertised does not match
BTN_TOOL_* capabilities that means that the device does not privide
tracking data for all contacts.

Luckily this should be backward-compatible (i.e. older userspace will
ignore "extended" fingercounts, newer will pay attention to it).

> 
> > > 
> > 
> > This is the best option in my opinion. We will present 2 finger position
> > data plus extended finger count.
> 
> We never did put all the details of the bounding box coordinates in
> writing, so perhaps this is an opportunity to both fix that and extend
> usability to the case so described. The only question is whether there
> are applications out there which now assume min/max instead of contact
> positions. If anyone knows, please speak up. :-) Otherwise, I am very
> much for Daniel's case C, with Dmitry's modification.
> 
> In short: Use the semi-MT property, and send two suitable fingers
> along with it.

Umm... but it is my understanding that 2 fingers will provide real
tracking data, not bounding box, so why would we set semi-MT?

Maybe we have different notions of what semi-MT property conveys? For me
semi-MT indicates that the device provides 2 coordinates for bounding
box.  However if semi-MT is not set does not mean that the device
provides true tracking for all contacts, but only for advertised slots.
There still may be additional data transmitted.

Thanks.
Henrik Rydberg July 6, 2011, 7:31 p.m. UTC | #9
> > I believe there is a strong userspace assumption that BTN_TOOL_* has
> > no meaning for real MT devices. Rightfully so, IMO. Hence, I think
> > semi-mt needs to be used here as well.
> 
> I think we need to adjust userspace to pay attention to BTN_TOOL_* for
> MT-B too so that if number of slots advertised does not match
> BTN_TOOL_* capabilities that means that the device does not privide
> tracking data for all contacts.

Well, it is possible, but it is a great deal more complex than just
looking at what the slots contain. At least we should all be able to
agree that MT-B is sufficient for any "proper" MT device.

> Luckily this should be backward-compatible (i.e. older userspace will
> ignore "extended" fingercounts, newer will pay attention to it).

OTOH, letting semi-mt engulf all devices which requires the use of
BTN_TOOL_* for finger count makes it easier to differentiate between
various userspace support levels. "This app supports pure MT-B only",
etc.

> > > This is the best option in my opinion. We will present 2 finger position
> > > data plus extended finger count.
> > 
> > We never did put all the details of the bounding box coordinates in
> > writing, so perhaps this is an opportunity to both fix that and extend
> > usability to the case so described. The only question is whether there
> > are applications out there which now assume min/max instead of contact
> > positions. If anyone knows, please speak up. :-) Otherwise, I am very
> > much for Daniel's case C, with Dmitry's modification.
> > 
> > In short: Use the semi-MT property, and send two suitable fingers
> > along with it.
> 
> Umm... but it is my understanding that 2 fingers will provide real
> tracking data, not bounding box, so why would we set semi-MT?

To indicate that a) the two positions may not represent true fingers
but a bounding box, and b) the contact count is determined by
BTN_TOOL_*.

True, there is no way to distinguish between the real-fingers and
bounding-box cases here (that is why I suggested another binary value
in a previous mail), but without semi-mt, there is no way to know a
priori if special logic is needed for the number of fingers.

> Maybe we have different notions of what semi-MT property conveys? For me
> semi-MT indicates that the device provides 2 coordinates for bounding
> box.  However if semi-MT is not set does not mean that the device
> provides true tracking for all contacts, but only for advertised slots.
> There still may be additional data transmitted.

Yes, it seems we do have different assumptions here. The more reason
to document it further. :-)

To me, it seems we do need a little bit of extra information to
determine this new type of device.

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
Dmitry Torokhov July 6, 2011, 8 p.m. UTC | #10
On Wed, Jul 06, 2011 at 09:31:20PM +0200, Henrik Rydberg wrote:
> > > I believe there is a strong userspace assumption that BTN_TOOL_* has
> > > no meaning for real MT devices. Rightfully so, IMO. Hence, I think
> > > semi-mt needs to be used here as well.
> > 
> > I think we need to adjust userspace to pay attention to BTN_TOOL_* for
> > MT-B too so that if number of slots advertised does not match
> > BTN_TOOL_* capabilities that means that the device does not privide
> > tracking data for all contacts.
> 
> Well, it is possible, but it is a great deal more complex than just
> looking at what the slots contain. At least we should all be able to
> agree that MT-B is sufficient for any "proper" MT device.
> 
> > Luckily this should be backward-compatible (i.e. older userspace will
> > ignore "extended" fingercounts, newer will pay attention to it).
> 
> OTOH, letting semi-mt engulf all devices which requires the use of
> BTN_TOOL_* for finger count makes it easier to differentiate between
> various userspace support levels. "This app supports pure MT-B only",
> etc.

Do app writers really want to exclude semi-MT devices even though they
might be usable? I can see wanting to support only MT-B protocol (as opposed
to chatty MT-A) but if semi-MT stream is usable why not use it?

> 
> > > > This is the best option in my opinion. We will present 2 finger position
> > > > data plus extended finger count.
> > > 
> > > We never did put all the details of the bounding box coordinates in
> > > writing, so perhaps this is an opportunity to both fix that and extend
> > > usability to the case so described. The only question is whether there
> > > are applications out there which now assume min/max instead of contact
> > > positions. If anyone knows, please speak up. :-) Otherwise, I am very
> > > much for Daniel's case C, with Dmitry's modification.
> > > 
> > > In short: Use the semi-MT property, and send two suitable fingers
> > > along with it.
> > 
> > Umm... but it is my understanding that 2 fingers will provide real
> > tracking data, not bounding box, so why would we set semi-MT?
> 
> To indicate that a) the two positions may not represent true fingers
> but a bounding box, and b) the contact count is determined by
> BTN_TOOL_*.
> 
> True, there is no way to distinguish between the real-fingers and
> bounding-box cases here

And that is the problem.

> (that is why I suggested another binary value
> in a previous mail), but without semi-mt, there is no way to know a
> priori if special logic is needed for the number of fingers.

This should be pretty straightforward:

	num_fingers = calc_fingers_from_btn_tool(device); // via EVIOCGKEY
	num_slots = get_number_of_slots(device); // EVIOCGABS
	num_untracked_contacts = max(num_fingers - num_slots, 0);

> 
> > Maybe we have different notions of what semi-MT property conveys? For me
> > semi-MT indicates that the device provides 2 coordinates for bounding
> > box.  However if semi-MT is not set does not mean that the device
> > provides true tracking for all contacts, but only for advertised slots.
> > There still may be additional data transmitted.
> 
> Yes, it seems we do have different assumptions here. The more reason
> to document it further. :-)

I'll take patches ;)

> 
> To me, it seems we do need a little bit of extra information to
> determine this new type of device.

I think we already have all we need (see above).

Thanks.
Henrik Rydberg July 6, 2011, 8:20 p.m. UTC | #11
> This should be pretty straightforward:
> 
> 	num_fingers = calc_fingers_from_btn_tool(device); // via EVIOCGKEY
> 	num_slots = get_number_of_slots(device); // EVIOCGABS
> 	num_untracked_contacts = max(num_fingers - num_slots, 0);

Heh, I forgot we _do_ know in advance how many fingers are supported
via BTN_TOOL_*. Ok, no more issues.

> > > Maybe we have different notions of what semi-MT property conveys? For me
> > > semi-MT indicates that the device provides 2 coordinates for bounding
> > > box.  However if semi-MT is not set does not mean that the device
> > > provides true tracking for all contacts, but only for advertised slots.
> > > There still may be additional data transmitted.
> > 
> > Yes, it seems we do have different assumptions here. The more reason
> > to document it further. :-)
> 
> I'll take patches ;)

And thou shalt receive them - some day ;-)

> > To me, it seems we do need a little bit of extra information to
> > determine this new type of device.
> 
> I think we already have all we need (see above).

I concur. So, to conclude:

a) The improved synaptics behavior can be achieved by simply using
MT-B plus BTN_TOOL_*.

b) Userspace should check BTN_TOOL_* for any discrepancies between the
maximum number of available slots (always two in this case) and the
maximum number of fingers reported (BTN_TOOL_TRIPLETAP etc). Extra
actions may then be taken to support more fingers than slots.

c) The semi-mt flag is only used to signal that the two points sent
via MT-B are the corners of a bounding box.

Cheers,
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
Chase Douglas July 6, 2011, 9:22 p.m. UTC | #12
On 07/06/2011 01:20 PM, Henrik Rydberg wrote:
>>> To me, it seems we do need a little bit of extra information to
>>> determine this new type of device.
>>
>> I think we already have all we need (see above).
> 
> I concur. So, to conclude:
> 
> a) The improved synaptics behavior can be achieved by simply using
> MT-B plus BTN_TOOL_*.
> 
> b) Userspace should check BTN_TOOL_* for any discrepancies between the
> maximum number of available slots (always two in this case) and the
> maximum number of fingers reported (BTN_TOOL_TRIPLETAP etc). Extra
> actions may then be taken to support more fingers than slots.
> 
> c) The semi-mt flag is only used to signal that the two points sent
> via MT-B are the corners of a bounding box.

This isn't quite enough. If we don't set the semi-mt flag or any other
new flag, then we'll have slots that become inconsistent when touches
are added or removed. For example, start with two touches being tracked
correctly. Now, add a touch. The second slot will now get the data of
the third touch, which is in a different location. You haven't changed
the tracking_id though, so it looks like the same touch. This is
incorrect behavior. Or, you could change the tracking_id, but that
implies that a touch was lifted and another was placed. This is also
incorrect behavior.

We need to tell userspace that this is a messed up device that can't
accurately track touch locations across touch up/down boundaries. Once
userspace sees this, it can act appropriately when it sees a transition
from BTN_TOOL_DOUBLETAP to BTN_TOOL_TRIPLETAP, for example. This is how
we handle transitions in the uTouch stack for semi-mt devices.

Perhaps a clean implementation would be to keep semi-mt as a flag
stating that there will only ever be two slots, the 0th will be the
minimum (x,y) of the bounding box and the 1st will be the maximum. Then,
we add a flag like NO_TOUCH_TRANSITION_TRACKING that would be set on
both semi-mt and these new devices that denote the slot data may
transition from one physical touchpoint to another when the number of
touches changes.

We could leave this up to userspace and have it detect a
NO_TOUCH_TRANSITION_TRACKING device based on the fact that the max slots
is less than the max fingers, but I would argue here that a more clear
protocol is a better protocol.

-- Chase
--
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
Dmitry Torokhov July 6, 2011, 9:36 p.m. UTC | #13
On Wed, Jul 06, 2011 at 02:22:53PM -0700, Chase Douglas wrote:
> On 07/06/2011 01:20 PM, Henrik Rydberg wrote:
> >>> To me, it seems we do need a little bit of extra information to
> >>> determine this new type of device.
> >>
> >> I think we already have all we need (see above).
> > 
> > I concur. So, to conclude:
> > 
> > a) The improved synaptics behavior can be achieved by simply using
> > MT-B plus BTN_TOOL_*.
> > 
> > b) Userspace should check BTN_TOOL_* for any discrepancies between the
> > maximum number of available slots (always two in this case) and the
> > maximum number of fingers reported (BTN_TOOL_TRIPLETAP etc). Extra
> > actions may then be taken to support more fingers than slots.
> > 
> > c) The semi-mt flag is only used to signal that the two points sent
> > via MT-B are the corners of a bounding box.
> 
> This isn't quite enough. If we don't set the semi-mt flag or any other
> new flag, then we'll have slots that become inconsistent when touches
> are added or removed. For example, start with two touches being tracked
> correctly. Now, add a touch. The second slot will now get the data of
> the third touch, which is in a different location. You haven't changed
> the tracking_id though, so it looks like the same touch. This is
> incorrect behavior. Or, you could change the tracking_id, but that
> implies that a touch was lifted and another was placed. This is also
> incorrect behavior.

The tracking ID needs to be changed as we start trackign and reporting
new touch. We could see that the old touch was not removed from the fact
that total number of finger reported increased.

> 
> We need to tell userspace that this is a messed up device that can't
> accurately track touch locations across touch up/down boundaries. Once
> userspace sees this, it can act appropriately when it sees a transition
> from BTN_TOOL_DOUBLETAP to BTN_TOOL_TRIPLETAP, for example. This is how
> we handle transitions in the uTouch stack for semi-mt devices.
> 
> Perhaps a clean implementation would be to keep semi-mt as a flag
> stating that there will only ever be two slots, the 0th will be the
> minimum (x,y) of the bounding box and the 1st will be the maximum. Then,
> we add a flag like NO_TOUCH_TRANSITION_TRACKING that would be set on
> both semi-mt and these new devices that denote the slot data may
> transition from one physical touchpoint to another when the number of
> touches changes.
> 
> We could leave this up to userspace and have it detect a
> NO_TOUCH_TRANSITION_TRACKING device based on the fact that the max slots
> is less than the max fingers, but I would argue here that a more clear
> protocol is a better protocol.

I'll ask this - how much realistically do we care about 3+ finger
transitions in context of these particular devices? This is a touchpad
so as long as basic 2 finger gestures work (zoom, pinch, 2-finger
scroll) with Synaptics X driver we should be fine. I do not want to add
all kinds of custom flags to the protocol to deal with this generation
of touchpads.

It sounds to me like latest generation of Synaptocs protocol is a dud
and hopefully they will fix it to something more flexible in the next
generationof chips...

Thanks.
Chase Douglas July 6, 2011, 10:16 p.m. UTC | #14
On 07/06/2011 02:36 PM, Dmitry Torokhov wrote:
> On Wed, Jul 06, 2011 at 02:22:53PM -0700, Chase Douglas wrote:
>> On 07/06/2011 01:20 PM, Henrik Rydberg wrote:
>>>>> To me, it seems we do need a little bit of extra information to
>>>>> determine this new type of device.
>>>>
>>>> I think we already have all we need (see above).
>>>
>>> I concur. So, to conclude:
>>>
>>> a) The improved synaptics behavior can be achieved by simply using
>>> MT-B plus BTN_TOOL_*.
>>>
>>> b) Userspace should check BTN_TOOL_* for any discrepancies between the
>>> maximum number of available slots (always two in this case) and the
>>> maximum number of fingers reported (BTN_TOOL_TRIPLETAP etc). Extra
>>> actions may then be taken to support more fingers than slots.
>>>
>>> c) The semi-mt flag is only used to signal that the two points sent
>>> via MT-B are the corners of a bounding box.
>>
>> This isn't quite enough. If we don't set the semi-mt flag or any other
>> new flag, then we'll have slots that become inconsistent when touches
>> are added or removed. For example, start with two touches being tracked
>> correctly. Now, add a touch. The second slot will now get the data of
>> the third touch, which is in a different location. You haven't changed
>> the tracking_id though, so it looks like the same touch. This is
>> incorrect behavior. Or, you could change the tracking_id, but that
>> implies that a touch was lifted and another was placed. This is also
>> incorrect behavior.
> 
> The tracking ID needs to be changed as we start trackign and reporting
> new touch. We could see that the old touch was not removed from the fact
> that total number of finger reported increased.

The evdev protocol is discrete, not continuous, so it's theoretically
possible that one touch could end at the same time that another begins.
IIRC, the time resolution of some MT devices makes this completely
possible, perhaps to the point that it would be trival to make this
happen in a few seconds of trying.

I think the MT-B protocol has only ever used tracking_id for signalling
touch begin and touch end, where the id goes from -1 to something else
and vice versa. Maybe the protocol could be "extended" by saying that a
transition from one valid id to another means there is inconsistent
touch state, but the old touch hasn't necessarily ended and the new
touch hasn't necessarily started at this point in time.

I'm not sure this is any easier than flagging these as bad devices
because now we need to watch tracking ID changes on top of touch count
changes. From someone who has attempted to implement semi-mt in X
synaptics, adding more complexity here should be avoided at all cost :).

>> We need to tell userspace that this is a messed up device that can't
>> accurately track touch locations across touch up/down boundaries. Once
>> userspace sees this, it can act appropriately when it sees a transition
>> from BTN_TOOL_DOUBLETAP to BTN_TOOL_TRIPLETAP, for example. This is how
>> we handle transitions in the uTouch stack for semi-mt devices.
>>
>> Perhaps a clean implementation would be to keep semi-mt as a flag
>> stating that there will only ever be two slots, the 0th will be the
>> minimum (x,y) of the bounding box and the 1st will be the maximum. Then,
>> we add a flag like NO_TOUCH_TRANSITION_TRACKING that would be set on
>> both semi-mt and these new devices that denote the slot data may
>> transition from one physical touchpoint to another when the number of
>> touches changes.
>>
>> We could leave this up to userspace and have it detect a
>> NO_TOUCH_TRANSITION_TRACKING device based on the fact that the max slots
>> is less than the max fingers, but I would argue here that a more clear
>> protocol is a better protocol.
> 
> I'll ask this - how much realistically do we care about 3+ finger
> transitions in context of these particular devices? This is a touchpad
> so as long as basic 2 finger gestures work (zoom, pinch, 2-finger
> scroll) with Synaptics X driver we should be fine. I do not want to add
> all kinds of custom flags to the protocol to deal with this generation
> of touchpads.

I've given up on trying to send semi-mt data through the proposed XInput
2.1 multitouch protocol. I think the best option is to send all this
data as valuators of a single touch (a touch and not a traditional
pointer event due to the multitouch/gesture semantics). Thus, we should
be focusing on what is possible in the gesture realm since we have
thrown full multiouch out the window for these devices.

With these devices we can support one touch drag, two touch pinch,
rotate, and zoom, and 1-5 touch tap. For these to work, we need to know
the number of touches at any given time, the locations of the two
touches when only two touches are active, and some representative
location for the 1 and 3-5 touch cases.

I am sitting here writing possible solutions trying to come up with sane
ways to handle all this, but every 5 minutes I erase what I came up with
and start over because you only see the problems once you've analysed
every scenario. I can't see any way to cater for these devices aside
from: handle them as single touch because they suck, or something
similar to what has been described in the past few hours.

> It sounds to me like latest generation of Synaptocs protocol is a dud
> and hopefully they will fix it to something more flexible in the next
> generationof chips...

We can only hope. In the meantime, it looks like Google is pushing to
use these devices on reference designs for Chrome OS, and big vendors
like Dell are perfectly happy to ship Ubuntu with the 100 times worse
(because we don't know their protocol) ALPS devices. Waiting for sanity
to win out seems like a lost cause to me :(.

-- Chase
--
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
Henrik Rydberg July 6, 2011, 10:35 p.m. UTC | #15
> The evdev protocol is discrete, not continuous, so it's theoretically
> possible that one touch could end at the same time that another begins.
> IIRC, the time resolution of some MT devices makes this completely
> possible, perhaps to the point that it would be trival to make this
> happen in a few seconds of trying.
> 
> I think the MT-B protocol has only ever used tracking_id for signalling
> touch begin and touch end, where the id goes from -1 to something else
> and vice versa. Maybe the protocol could be "extended" by saying that a
> transition from one valid id to another means there is inconsistent
> touch state, but the old touch hasn't necessarily ended and the new
> touch hasn't necessarily started at this point in time.

The in-flight change of tracking id is actually part of the design; it
makes the protocol independent of sample rate. If a particular
tracking id is no longer found in any slot, that touch has ended.

> I'm not sure this is any easier than flagging these as bad devices
> because now we need to watch tracking ID changes on top of touch count
> changes. From someone who has attempted to implement semi-mt in X
> synaptics, adding more complexity here should be avoided at all cost :).

The information available in the proposition suffices to determine
what the device is. Surely the method of transferring that information
will not have any impact on the extra code required.

> > I'll ask this - how much realistically do we care about 3+ finger
> > transitions in context of these particular devices? This is a touchpad
> > so as long as basic 2 finger gestures work (zoom, pinch, 2-finger
> > scroll) with Synaptics X driver we should be fine. I do not want to add
> > all kinds of custom flags to the protocol to deal with this generation
> > of touchpads.
> 
> I've given up on trying to send semi-mt data through the proposed XInput
> 2.1 multitouch protocol. I think the best option is to send all this
> data as valuators of a single touch (a touch and not a traditional
> pointer event due to the multitouch/gesture semantics). Thus, we should
> be focusing on what is possible in the gesture realm since we have
> thrown full multiouch out the window for these devices.
> 
> With these devices we can support one touch drag, two touch pinch,
> rotate, and zoom, and 1-5 touch tap. For these to work, we need to know
> the number of touches at any given time, the locations of the two
> touches when only two touches are active, and some representative
> location for the 1 and 3-5 touch cases.

Right, and we do, so there is no problem there, is there?

> I am sitting here writing possible solutions trying to come up with sane
> ways to handle all this, but every 5 minutes I erase what I came up with
> and start over because you only see the problems once you've analysed
> every scenario. I can't see any way to cater for these devices aside
> from: handle them as single touch because they suck, or something
> similar to what has been described in the past few hours.
> 
> > It sounds to me like latest generation of Synaptocs protocol is a dud
> > and hopefully they will fix it to something more flexible in the next
> > generationof chips...
> 
> We can only hope. In the meantime, it looks like Google is pushing to
> use these devices on reference designs for Chrome OS, and big vendors
> like Dell are perfectly happy to ship Ubuntu with the 100 times worse
> (because we don't know their protocol) ALPS devices. Waiting for sanity
> to win out seems like a lost cause to me :(.

Let us bide our time and see.

Cheers,
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
Chase Douglas July 6, 2011, 11:30 p.m. UTC | #16
On 07/06/2011 03:35 PM, Henrik Rydberg wrote:
>> The evdev protocol is discrete, not continuous, so it's theoretically
>> possible that one touch could end at the same time that another begins.
>> IIRC, the time resolution of some MT devices makes this completely
>> possible, perhaps to the point that it would be trival to make this
>> happen in a few seconds of trying.
>>
>> I think the MT-B protocol has only ever used tracking_id for signalling
>> touch begin and touch end, where the id goes from -1 to something else
>> and vice versa. Maybe the protocol could be "extended" by saying that a
>> transition from one valid id to another means there is inconsistent
>> touch state, but the old touch hasn't necessarily ended and the new
>> touch hasn't necessarily started at this point in time.
> 
> The in-flight change of tracking id is actually part of the design; it
> makes the protocol independent of sample rate. If a particular
> tracking id is no longer found in any slot, that touch has ended.

Ok. I agree that this is the best way to handle things.

It does mean that we can't just change tracking_ids when the number of
touches changes, so that option is out.

>> I'm not sure this is any easier than flagging these as bad devices
>> because now we need to watch tracking ID changes on top of touch count
>> changes. From someone who has attempted to implement semi-mt in X
>> synaptics, adding more complexity here should be avoided at all cost :).
> 
> The information available in the proposition suffices to determine
> what the device is. Surely the method of transferring that information
> will not have any impact on the extra code required.

My (unstated) question was: is watching tracking_id transitions
reasonable for noting inconsistent touch changes when the number of
touches changes, or should we have a way to tell if a device is broken
and we must assume touch state inconsistency when the finger count
changes. Given your reply above that we cannot repurpose valid
tracking_id -> valid tracking_id transitions as a means of denoting
touch state inconsistency, that leaves us with the latter option.

You're right that the information available from the axes is enough to
tell if the device is broken (i.e. if max finger count > max slot count).

Ancillary to this is the question of whether we should depend on the
userspace side knowing this hidden meaning, or if we should state it up
front by setting a separate flag in the properties bits. I really don't
want to leave this up to userspace developers having to figure out or
dive into kernel code to determine what is going on, so I'm in favor of
having an explicit (documented!) property flag for these devices. Why
have property bits if you aren't going to use them :).

>>> I'll ask this - how much realistically do we care about 3+ finger
>>> transitions in context of these particular devices? This is a touchpad
>>> so as long as basic 2 finger gestures work (zoom, pinch, 2-finger
>>> scroll) with Synaptics X driver we should be fine. I do not want to add
>>> all kinds of custom flags to the protocol to deal with this generation
>>> of touchpads.
>>
>> I've given up on trying to send semi-mt data through the proposed XInput
>> 2.1 multitouch protocol. I think the best option is to send all this
>> data as valuators of a single touch (a touch and not a traditional
>> pointer event due to the multitouch/gesture semantics). Thus, we should
>> be focusing on what is possible in the gesture realm since we have
>> thrown full multiouch out the window for these devices.
>>
>> With these devices we can support one touch drag, two touch pinch,
>> rotate, and zoom, and 1-5 touch tap. For these to work, we need to know
>> the number of touches at any given time, the locations of the two
>> touches when only two touches are active, and some representative
>> location for the 1 and 3-5 touch cases.
> 
> Right, and we do, so there is no problem there, is there?

Agreed, there is no problem if we go with the assumption that for these
devices the touch slot data is inconsistent on touch count changes.

I am satisfied with the approach that's been laid out, the only point of
contention is whether userspace must infer touch state inconsistency on
touch count changes by looking at max fingers and max slots, or if we
provide this detail as a device property.

-- Chase
--
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/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 0a51b0ba..2d7ac0a 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -286,7 +286,8 @@  static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
 	static unsigned char param = 0xc8;
 	struct synaptics_data *priv = psmouse->private;
 
-	if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+	if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
 		return 0;
 
 	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
@@ -434,7 +435,9 @@  static int synaptics_parse_hw_state(const unsigned char buf[],
 			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
 
-		if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
+		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)
+				|| SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))
+				&& hw->w == 2) {
 			/* Gesture packet: (x, y, z) at half resolution */
 			priv->agm.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
 			priv->agm.y = INVERT_Y((((buf[4] & 0xf0) << 4)
@@ -519,6 +522,92 @@  static void synaptics_report_semi_mt_data(struct input_dev *dev,
 	}
 }
 
+static void synaptics_report_mt_slot(struct input_dev *dev, int slot, int state,
+				     const struct synaptics_hw_state *sgm,
+				     const struct synaptics_hw_state *agm)
+{
+	input_mt_slot(dev, slot);
+	switch (state) {
+	case SYN_SLOT_EMPTY:
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+		break;
+	case SYN_SLOT_SGM:
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+		input_report_abs(dev, ABS_MT_POSITION_X, sgm->x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, sgm->y);
+		input_report_abs(dev, ABS_MT_PRESSURE, sgm->z);
+		if (sgm->w >= 4)
+			input_report_abs(dev, ABS_MT_TOUCH_MAJOR, sgm->w);
+		break;
+	case SYN_SLOT_AGM:
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+		input_report_abs(dev, ABS_MT_POSITION_X, agm->x);
+		input_report_abs(dev, ABS_MT_POSITION_Y, agm->y);
+		input_report_abs(dev, ABS_MT_PRESSURE, agm->z);
+		break;
+	}
+}
+
+static void synaptics_update_slots(struct synaptics_data *priv, int count,
+				   int sgm, int agm)
+{
+	int i;
+
+	/* First, clear previous slots. */
+	for (i = 0; i < SYN_TRACK_SLOT_COUNT; i++)
+		priv->slot[i] = SYN_SLOT_EMPTY;
+
+	if (count < 1)
+		return;
+	priv->slot[sgm] = SYN_SLOT_SGM;
+
+	if (count < 2)
+		return;
+	priv->slot[agm] = SYN_SLOT_AGM;
+}
+
+static void synaptics_process_hw_state(struct synaptics_data *priv,
+				       struct synaptics_hw_state *sgm)
+{
+	int new_num_fingers;
+
+	if (sgm->z == 0)
+		new_num_fingers = 0;
+	else if (sgm->w >= 4)
+		new_num_fingers = 1;
+	else if (sgm->w == 0)
+		new_num_fingers = 2;
+	else if (sgm->w == 1)
+		new_num_fingers = 3;
+
+	switch (new_num_fingers) {
+	case 0:
+		synaptics_update_slots(priv, 0, 0, 0);
+		break;
+	case 1:
+		synaptics_update_slots(priv, 1, 0, 0);
+		break;
+	case 2:
+	case 3: /* Fall-through case */
+		synaptics_update_slots(priv, 2, 0, 1);
+		break;
+	}
+
+	priv->num_fingers = new_num_fingers;
+}
+
+static void synaptics_report_mt_data(struct psmouse *psmouse,
+				     struct synaptics_hw_state *sgm)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct synaptics_data *priv = psmouse->private;
+	struct synaptics_hw_state *agm = &priv->agm;
+	int i;
+
+	for (i = 0; i < SYN_TRACK_SLOT_COUNT; i++)
+		synaptics_report_mt_slot(dev, i, priv->slot[i], sgm, agm);
+}
+
 /*
  *  called for each full received packet from the touchpad
  */
@@ -534,6 +623,15 @@  static void synaptics_process_packet(struct psmouse *psmouse)
 	if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
 		return;
 
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+		synaptics_process_hw_state(priv, &hw);
+		synaptics_report_mt_data(psmouse, &hw);
+		input_mt_report_pointer_emulation(dev, true);
+		input_report_key(dev, BTN_LEFT, hw.left);
+		input_sync(dev);
+		return;
+	}
+
 	if (hw.scroll) {
 		priv->scroll += hw.scroll;
 
@@ -705,7 +803,19 @@  static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 			     priv->y_max ?: YMAX_NOMINAL, fuzz, 0);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
-	if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
+	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
+		input_mt_init_slots(dev, SYN_TRACK_SLOT_COUNT);
+		input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
+				     priv->x_max ?: XMAX_NOMINAL, fuzz, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
+				     priv->y_max ?: YMAX_NOMINAL, fuzz, 0);
+		input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 4, 15, 0, 0);
+
+		input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res);
+		input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res);
+
+	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
 		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
 		input_mt_init_slots(dev, 2);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index e367239..1de2256 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -73,6 +73,8 @@ 
  * 2	0x04	reduced filtering	firmware does less filtering on
  *					position data, driver should watch
  *					for noise.
+ * 2	0x08	image sensor		image sensor tracks 5 fingers, but only
+ *					reports 2.
  */
 #define SYN_CAP_ADJ_THRESHOLD(ex0c)	((ex0c) & 0x010000)
 #define SYN_CAP_MAX_DIMENSIONS(ex0c)	((ex0c) & 0x020000)
@@ -84,6 +86,7 @@ 
 #define SYN_CAP_CLICKPAD2BTN(ex0c)	((ex0c) & 0x000100) /* 2-button ClickPad */
 #define SYN_CAP_DELUXE_LED(ex0c)	((ex0c) & 0x000200)
 #define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
+#define SYN_CAP_IMAGE_SENSOR(ex0c)	((ex0c) & 0x000800)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -113,6 +116,14 @@ 
 /* amount to fuzz position data when touchpad reports reduced filtering */
 #define SYN_REDUCED_FILTER_FUZZ		8
 
+/* synaptics tracking slot states */
+#define SYN_SLOT_EMPTY			0
+#define SYN_SLOT_SGM			1
+#define SYN_SLOT_AGM			2
+
+/* number of tracking slots for Image Sensor firmware */
+#define SYN_TRACK_SLOT_COUNT		2
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -148,6 +159,8 @@  struct synaptics_data {
 	struct serio *pt_port;			/* Pass-through serio port */
 
 	struct synaptics_hw_state agm;		/* last AGM packet */
+	int num_fingers;			/* current finger count */
+	int slot[SYN_TRACK_SLOT_COUNT];		/* finger slot state */
 };
 
 void synaptics_module_init(void);