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
drivers/input/mouse/synaptics.c +21 -3
@@ -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 */
drivers/input/mouse/synaptics.h +6 -0
@@ -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 */
drivers/input/mousedev.c +19 -15
@@ -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 ; }
Quoted 8 lines · 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:
Quoted 4 lines
- 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.
Quoted 9 lines
- 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.
Quoted 6 lines
2. Add
absolute->relativeconversion 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
Quoted 4 lines · Dmitry Torokhov
- 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.
Quoted 11 lines · Felipe Alfaro Solana
Quoted 4 lines · Dmitry Torokhov
- 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
Apologies if you seen this already but it seems the list ate my previous replies...
Quoted 1 line · Neil Brown
On Tuesday July 1, [email protected] wrote:
... skip ...
Quoted 9 lines
Quoted 4 lines
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.
Quoted 10 lines
Quoted 6 lines
2. Add
absolute->relativeconversion 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
Quoted 16 lines · On Tuesday July 1, [email protected] wrote:
Apologies if you seen this already but it seems the list ate my previous replies...
Quoted 1 line · Neil Brown
On Tuesday July 1, [email protected] wrote:
... skip ...
Quoted 9 lines
Quoted 4 lines
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.
Quoted 8 lines
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/eventXto 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.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
2. Add
absolute->relativeconversion 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.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
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->relativeconversion.
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
Quoted 26 lines · Neil Brown
Quoted 16 lines · On Tuesday July 1, [email protected] wrote:
Apologies if you seen this already but it seems the list ate my previous replies...
Quoted 1 line · Neil Brown
On Tuesday July 1, [email protected] wrote:
... skip ...
Quoted 7 lines
Quoted 3 lines
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.
Quoted 8 lines
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/eventXto access them.
Quoted 4 lines
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?
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines
2. Add
absolute->relativeconversion 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.
Quoted 9 lines
Quoted 2 lines
Right, and if device says that it can generate relative packets mousedev should not get in its way and do its own
absolute->relativeconversion.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 :(
Quoted 5 lines
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
Quoted 4 lines · Dmitry Torokhov
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.
Quoted 4 lines
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.
Quoted 8 lines
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.
Quoted 8 lines
Quoted 5 lines
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.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR