2003-07-01 07:49:36

by Dmitry Torokhov

[permalink] [raw]
Subject: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

Hi,

I was trying to teach mousedev to bind to new synaptics driver. This
may be useful for gpm and other programs that don't have native event
processing module written yet. Unfortunately absolute to relative
conversion in mousedev only suits for tablets (digitizers) and not for
touchpads because:

- touchpads are not precise; when I take my finger off touchpad and then
touch it again somewhere else I do not expect my cursor jump anywhere,
I only expect cursor to move when I move my finger while pressing
touchpad.
- synaptics has Y axis reversed from what mousedev expects.

I tried to modify mousedev to account for differences between touchpads
in absolute mode and digitizers in absolute mode but all my solutions
required ugly flags - brrr... So what if we:

1. Modify mousedev so if an input device announces that it generates both
relative and absolute events mousedev will discard all absolute axis
events and will rely on device supplied relative events.
2. Add absolute->relative conversion code to touchpad drivers themselves
as drivers should know the best how to do that. If they turn out to be
similar across different touchpads then the common module could be
made.

What you think?

Dmitry

diff -urN --exclude-from=/usr/src/exclude 2.5.72-vanilla/drivers/input/mouse/synaptics.c linux-2.5.72/drivers/input/mouse/synaptics.c
--- 2.5.72-vanilla/drivers/input/mouse/synaptics.c 2003-06-19 20:23:32.000000000 -0500
+++ linux-2.5.72/drivers/input/mouse/synaptics.c 2003-07-01 02:54:34.000000000 -0500
@@ -244,9 +244,9 @@
set_bit(BTN_FORWARD, psmouse->dev.keybit);
set_bit(BTN_BACK, psmouse->dev.keybit);

- clear_bit(EV_REL, psmouse->dev.evbit);
- clear_bit(REL_X, psmouse->dev.relbit);
- clear_bit(REL_Y, psmouse->dev.relbit);
+ set_bit(EV_REL, psmouse->dev.evbit);
+ set_bit(REL_X, psmouse->dev.relbit);
+ set_bit(REL_Y, psmouse->dev.relbit);

return 0;

@@ -302,11 +302,14 @@
/*
* called for each full received packet from the touchpad
*/
+#define fx(i) priv->old_x[(priv->pkt_count - (i)) & 03]
+#define fy(i) priv->old_y[(priv->pkt_count - (i)) & 03]
static void synaptics_process_packet(struct psmouse *psmouse)
{
struct input_dev *dev = &psmouse->dev;
struct synaptics_data *priv = psmouse->private;
struct synaptics_hw_state hw;
+ int dx, dy;

synaptics_parse_hw_state(priv, &hw);

@@ -332,6 +335,21 @@
}
if (!w_ok)
hw.w = 5;
+
+ if (hw.z > SYN_REL_PRESSURE_THRESHOLD) {
+ fx(0) = hw.x;
+ fy(0) = hw.y;
+ if (priv->pkt_count >= 2) {
+ dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / SYN_REL_DECEL_FACTOR;
+ dy = ((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / SYN_REL_DECEL_FACTOR;
+
+ input_report_rel(dev, REL_X, dx);
+ input_report_rel(dev, REL_Y, -dy);
+ }
+ priv->pkt_count++;
+ } else {
+ priv->pkt_count = 0;
+ }
}

/* Post events */
diff -urN --exclude-from=/usr/src/exclude 2.5.72-vanilla/drivers/input/mouse/synaptics.h linux-2.5.72/drivers/input/mouse/synaptics.h
--- 2.5.72-vanilla/drivers/input/mouse/synaptics.h 2003-06-19 20:23:32.000000000 -0500
+++ linux-2.5.72/drivers/input/mouse/synaptics.h 2003-07-01 03:00:43.000000000 -0500
@@ -72,6 +72,9 @@
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)

+#define SYN_REL_DECEL_FACTOR 8
+#define SYN_REL_PRESSURE_THRESHOLD 30
+
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
@@ -100,6 +103,9 @@
int proto_buf_tail;

int old_w; /* Previous w value */
+ int old_x[4];
+ int old_y[4];
+ int pkt_count; /* number of packets with pressure above threshold */
};

#endif /* _SYNAPTICS_H */
diff -urN --exclude-from=/usr/src/exclude 2.5.72-vanilla/drivers/input/mousedev.c linux-2.5.72/drivers/input/mousedev.c
--- 2.5.72-vanilla/drivers/input/mousedev.c 2003-06-14 14:18:33.000000000 -0500
+++ linux-2.5.72/drivers/input/mousedev.c 2003-07-01 00:37:01.000000000 -0500
@@ -90,25 +90,29 @@
if (test_bit(BTN_TRIGGER, handle->dev->keybit))
break;
switch (code) {
- case ABS_X:
- size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
- if (size != 0) {
- list->dx += (value * xres - list->oldx) / size;
- list->oldx += list->dx * size;
- } else {
- list->dx += value - list->oldx;
- list->oldx += list->dx;
+ case ABS_X:
+ if (!test_bit(REL_X, handle->dev->relbit)) {
+ size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
+ if (size != 0) {
+ list->dx += (value * xres - list->oldx) / size;
+ list->oldx += list->dx * size;
+ } else {
+ list->dx += value - list->oldx;
+ list->oldx += list->dx;
+ }
}
break;

case ABS_Y:
- size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
- if (size != 0) {
- list->dy -= (value * yres - list->oldy) / size;
- list->oldy -= list->dy * size;
- } else {
- list->dy -= value - list->oldy;
- list->oldy -= list->dy;
+ if (!test_bit(REL_Y, handle->dev->relbit)) {
+ size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
+ if (size != 0) {
+ list->dy -= (value * yres - list->oldy) / size;
+ list->oldy -= list->dy * size;
+ } else {
+ list->dy -= value - list->oldy;
+ list->oldy -= list->dy;
+ }
}
break;
}


2003-07-01 09:27:22

by NeilBrown

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tuesday July 1, [email protected] wrote:
> Hi,
>
> I was trying to teach mousedev to bind to new synaptics driver. This
> may be useful for gpm and other programs that don't have native event
> processing module written yet. Unfortunately absolute to relative
> conversion in mousedev only suits for tablets (digitizers) and not for
> touchpads because:
>
> - touchpads are not precise; when I take my finger off touchpad and then
> touch it again somewhere else I do not expect my cursor jump anywhere,
> I only expect cursor to move when I move my finger while pressing
> touchpad.

Yep, that's a bug. mousedev needs to know when there is or isn't a
finger and ignore absolute differences when there is no finger.

> - synaptics has Y axis reversed from what mousedev expects.
>
> I tried to modify mousedev to account for differences between touchpads
> in absolute mode and digitizers in absolute mode but all my solutions
> required ugly flags - brrr... So what if we:
>
> 1. Modify mousedev so if an input device announces that it generates both
> relative and absolute events mousedev will discard all absolute axis
> events and will rely on device supplied relative events.

Nah. I have an ALPS dualpoint which generates ABSolute events for the
touchpad part and RElative events for the pointstick part. I want
them both.

> 2. Add absolute->relative conversion code to touchpad drivers themselves
> as drivers should know the best how to do that. If they turn out to be
> similar across different touchpads then the common module could be
> made.
>
> What you think?

I think that mousedev should be just clever enough to mostly work and
no cleverer. Anything more interesting should be done in user-space.

For example, there is the idea of treating one edge of a touch pad
like a scroll wheel. I don't think this should be done in the
kernel.
I have just started working on a program to do this. It opens
/dev/input/event1 (in my case) to read events from the touchpad. It
uses an ioctl to "grab" the device so mousedev doesn't see any events
directly.
Then it opens /dev/input/uinput and registers itself as a mouse-like
device. It copies event from one to the other with some translation.
It will eventually do all the magic abs->rel translations that I want
and notice corner-taps and such. At the moment it only does some
simple mapping of button events so that I can use one of my two 'left'
buttons as a 'middle' button.

I actually think that it should be possible to do everything in
user-space. I find it quite awkward that I *cannot* get a clear
channel from a user-space program to the PS/2 aux port like I could in
2.4 via /dev/psaux. I would really like to be able to open some
device, "GRAB" it, and then have complete control of the PS/2 AUX
port. Then I could similarly open /dev/input/uinput and do exactly
what translations I wanted.

NeilBrown

2003-07-01 11:48:40

by Felipe Alfaro Solana

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tue, 2003-07-01 at 10:03, Dmitry Torokhov wrote:

> - touchpads are not precise; when I take my finger off touchpad and then
> touch it again somewhere else I do not expect my cursor jump anywhere,
> I only expect cursor to move when I move my finger while pressing
> touchpad.

Uhmmm... Maybe I'm losing something here, but my NEC Chrom@'s
ALPS/GlidePoint touchpad doesn't cause the mouse cursor to jump/move
when I lift off my finger from it and then touch it again elsewhere. The
mouse cursor moves only when I drag my finger over the touchpad surface.

2003-07-01 18:03:43

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tuesday 01 July 2003 07:02 am, Felipe Alfaro Solana wrote:
> On Tue, 2003-07-01 at 10:03, Dmitry Torokhov wrote:
> > - touchpads are not precise; when I take my finger off touchpad and then
> > touch it again somewhere else I do not expect my cursor jump anywhere,
> > I only expect cursor to move when I move my finger while pressing
> > touchpad.
>
> Uhmmm... Maybe I'm losing something here, but my NEC Chrom@'s
> ALPS/GlidePoint touchpad doesn't cause the mouse cursor to jump/move
> when I lift off my finger from it and then touch it again elsewhere. The
> mouse cursor moves only when I drag my finger over the touchpad surface.
>

Apologies if you seen this already but it seems the list ate my previous
replies...

My touchpad works well in relative mode, it's new synaptics driver code
in 2.5 that switches the touchpad in absolute mode that gives me trouble.
Right now in stock kernel synaptics driver does not register with
mousedev and only provides /dev/input/eventX interface. I want it to also
plug in into /dev/input/mouseX and /dev/psaux so programs that do not
have special code for event processing could still use it. The problem
is that conversion from absolute to relative mode in mousedev isn't
working well for touchpads. When to take your finger off touchpad and
touch it in other place mousedev does not account for that and calculates
huge delta which causes your cursor to jump.

Dmitry

2003-07-01 18:15:07

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

Apologies if you seen this already but it seems the list ate my previous
replies...

On Tuesday 01 July 2003 04:40 am, Neil Brown wrote:
> On Tuesday July 1, [email protected] wrote:
... skip ...
> >
> > 1. Modify mousedev so if an input device announces that it generates both
> > relative and absolute events mousedev will discard all absolute axis
> > events and will rely on device supplied relative events.
>
> Nah. I have an ALPS dualpoint which generates ABSolute events for the
> touchpad part and RElative events for the pointstick part. I want
> them both.
>

So pass relative events as is and do conversion of absolute to relatives.
That's what I gonna do about my track stick as well.

Remember that mousedev provides _emulation_ of [Ex]PS/2 mouse protocol for
almost any device, it does not do any advanced tricks it's here to use with
old software that does not have advanced drivers yet, you are not "loosing"
your absolute mode packets, you hav /dev/input/eventX to access them.

> > 2. Add absolute->relative conversion code to touchpad drivers themselves
> > as drivers should know the best how to do that. If they turn out to be
> > similar across different touchpads then the common module could be
> > made.
> >
> > What you think?
>
> I think that mousedev should be just clever enough to mostly work and
> no cleverer. Anything more interesting should be done in user-space.
>

Right, and if device says that it can generate relative packets mousedev
should not get in its way and do its own absolute->relative conversion.

Dmitry

2003-07-01 23:29:27

by NeilBrown

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tuesday July 1, [email protected] wrote:
> Apologies if you seen this already but it seems the list ate my previous
> replies...
>
> On Tuesday 01 July 2003 04:40 am, Neil Brown wrote:
> > On Tuesday July 1, [email protected] wrote:
> ... skip ...
> > >
> > > 1. Modify mousedev so if an input device announces that it generates both
> > > relative and absolute events mousedev will discard all absolute axis
> > > events and will rely on device supplied relative events.
> >
> > Nah. I have an ALPS dualpoint which generates ABSolute events for the
> > touchpad part and RElative events for the pointstick part. I want
> > them both.
> >
>
> So pass relative events as is and do conversion of absolute to relatives.
> That's what I gonna do about my track stick as well.
>
> Remember that mousedev provides _emulation_ of [Ex]PS/2 mouse protocol for
> almost any device, it does not do any advanced tricks it's here to use with
> old software that does not have advanced drivers yet, you are not "loosing"
> your absolute mode packets, you hav /dev/input/eventX to access them.
>

If I do that, then on the eventX device I will see both 'real'
relative events and 'synthesised' (from absoule) relative events and I
won't be able to tell the difference.

> > > 2. Add absolute->relative conversion code to touchpad drivers themselves
> > > as drivers should know the best how to do that. If they turn out to be
> > > similar across different touchpads then the common module could be
> > > made.
> > >
> > > What you think?
> >
> > I think that mousedev should be just clever enough to mostly work and
> > no cleverer. Anything more interesting should be done in user-space.
> >
>
> Right, and if device says that it can generate relative packets mousedev
> should not get in its way and do its own absolute->relative conversion.

A device should present raw events. Whatever the user says to the
device should come out eventX uninterpreted.
mousedev should interpret what it can and present this out
/dev/psaux. As it can do limited interpretation of ABS events, it
should.

This seems different to your perspective, but seeing there is not
standard or other document that we can make reference too, it is not
clear that anyone can decide who is *right*.....

NeilBrown

2003-07-02 00:42:23

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tuesday 01 July 2003 06:43 pm, Neil Brown wrote:
> On Tuesday July 1, [email protected] wrote:
> > Apologies if you seen this already but it seems the list ate my previous
> > replies...
> >
> > On Tuesday 01 July 2003 04:40 am, Neil Brown wrote:
> > > On Tuesday July 1, [email protected] wrote:
> >
> > ... skip ...
> >
> > > > 1. Modify mousedev so if an input device announces that it generates
> > > > both relative and absolute events mousedev will discard all absolute
> > > > axis events and will rely on device supplied relative events.
> > >
> > > Nah. I have an ALPS dualpoint which generates ABSolute events for the
> > > touchpad part and RElative events for the pointstick part. I want
> > > them both.
> >
> > So pass relative events as is and do conversion of absolute to relatives.
> > That's what I gonna do about my track stick as well.
> >
> > Remember that mousedev provides _emulation_ of [Ex]PS/2 mouse protocol
> > for almost any device, it does not do any advanced tricks it's here to
> > use with old software that does not have advanced drivers yet, you are
> > not "loosing" your absolute mode packets, you hav /dev/input/eventX to
> > access them.
>
> If I do that, then on the eventX device I will see both 'real'
> relative events and 'synthesised' (from absoule) relative events and I
> won't be able to tell the difference.
>

I see there are 2 possible solutions. If I understand what Vojtech wrote
regarding synaptics driver the track stick (or other pass-through device)
is best implemented as a separate serio. So you could have your touchpad
in absolute mode and stick as a separate device in native relative.

Other way is to check (in your userspace driver) whether your motion
packets contains absolute packets and if they are present discard any
relative events in this batch.

Hmmm... what if we introduce something like sythrelbit[NBITS(REL__MAX)]
for passing synthesized relative events and have mousedev use values in
following order of precedence:
- absbit - lowest priority
- synthrelbit
- relbit - highest.

What you think?
> > > > 2. Add absolute->relative conversion code to touchpad drivers
> > > > themselves as drivers should know the best how to do that. If they
> > > > turn out to be similar across different touchpads then the common
> > > > module could be made.
> > > >
> > > > What you think?
> > >
> > > I think that mousedev should be just clever enough to mostly work and
> > > no cleverer. Anything more interesting should be done in user-space.
> >
> > Right, and if device says that it can generate relative packets mousedev
> > should not get in its way and do its own absolute->relative conversion.
>
> A device should present raw events. Whatever the user says to the
> device should come out eventX uninterpreted.
> mousedev should interpret what it can and present this out
> /dev/psaux. As it can do limited interpretation of ABS events, it
> should.
>

The thing is that the result is not useable with touchpads right now.
It just does not work :(

> This seems different to your perspective, but seeing there is not
> standard or other document that we can make reference too, it is not
> clear that anyone can decide who is *right*.....
>
> NeilBrown

Dmitry

2003-07-02 06:45:23

by Vojtech Pavlik

[permalink] [raw]
Subject: Re: [RFC/PATCH] Touchpads in absolute mode (synaptics) and mousedev

On Tue, Jul 01, 2003 at 07:57:22PM -0500, Dmitry Torokhov wrote:

> I see there are 2 possible solutions. If I understand what Vojtech wrote
> regarding synaptics driver the track stick (or other pass-through device)
> is best implemented as a separate serio. So you could have your touchpad
> in absolute mode and stick as a separate device in native relative.

And if a separate serio is not possible, then at least a separate input
device. It definitely should not be mixed together into one input device
when in reality there are two.

> Other way is to check (in your userspace driver) whether your motion
> packets contains absolute packets and if they are present discard any
> relative events in this batch.
>
> Hmmm... what if we introduce something like sythrelbit[NBITS(REL__MAX)]
> for passing synthesized relative events and have mousedev use values in
> following order of precedence:
> - absbit - lowest priority
> - synthrelbit
> - relbit - highest.
>
> What you think?

... why? I really don't see a reason why we should generate any
synthetic events in the kernel. Not at the device driver level, not at
the handler level.

> > A device should present raw events. Whatever the user says to the
> > device should come out eventX uninterpreted.
> > mousedev should interpret what it can and present this out
> > /dev/psaux. As it can do limited interpretation of ABS events, it
> > should.
>
> The thing is that the result is not useable with touchpads right now.
> It just does not work :(

There exists an XFree86 driver that uses eventX for Synaptics. Same
thing hopefully will be added to GPM soon. AND, I hope I'll be able to
get rid of the relativization code in mousedev soon, too, because it's
beyond ugly, as soon as a similar XFree86 driver is written for 'generic
tablet's.

--
Vojtech Pavlik
SuSE Labs, SuSE CR