Re: Proposal to support pressure sensitive "analog" buttons in evdev

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Aug 26, 2018 at 09:49:45PM -0700, Roderick Colenbrander wrote:
> On Sun, Aug 5, 2018 at 11:55 PM Peter Hutterer <peter.hutterer@xxxxxxxxx> wrote:
> >
> > On Tue, Jul 31, 2018 at 08:49:08PM +0000, Roderick.Colenbrander@xxxxxxxx wrote:
> > > On 07/30/2018 11:52 PM, David Herrmann wrote:
> > > > Hi
> > > >
> > > > (+CC Dmitry, Jiri, Peter, Benjamin)
> > > >
> > > > On Tue, Jul 31, 2018 at 1:48 AM <Roderick.Colenbrander@xxxxxxxx> wrote:
> > > >> Hi all,
> > > >>
> > > >> I would like to share a proposal to extend evdev with support for
> > > >> pressure sensitive "analog" buttons. It is a feature common on gaming
> > > >> peripherals (arcade sticks, gamepads, wii guitar) as well now on analog
> > > >> keyboards such as Wooting One / Two keyboards on which every button is
> > > >> both analog and digital (so ~100 analog keys).
> > > >>
> > > >> These devices are difficult to support using the existing evdev API. The
> > > >> problem is the EV_KEY event type was meant for digital keys, whereas the
> > > >> EV_ABS could be used for this purpose except that it has reached its
> > > >> axes limit due to the EVIOCGABS/SABS limitation of 0x40.
> > > >>
> > > >> The proposal is to add a new event type "EV_PSR" to evdev to describe
> > > >> pressure sensitive keys. Keys reported to this mechanism can report
> > > >> analog values. Often devices also report a digital value for the same
> > > >> button, so EV_PSR analog keys can have a matching digital EV_KEY. For
> > > >> this reason, we suggest to share key codes. (This is up for debate of
> > > >> course to tie both together like this.)
> > > >>
> > > >> Pressure sensitive keys, have similarities with regular absolute axes as
> > > >> they have min/max values and probably fuzz makes sense as well. It could
> > > >> be said we should extend ABS like David Herrmann proposed in his ABS2
> > > >> proposal a while ago and remove the EVIOCGABS/SABS limitations.
> > > >>
> > > >> This is an initial proposal to address limitations in evdev to improve
> > > >> device support in existing drivers such as hid-sony, hid-betopff,
> > > >> psxpad-spi, hid-wii and probably others as well as new devices such as
> > > >> Wooting keyboards
> > > >>
> > > >> Thanks,
> > > >> Roderick Colenbrander
> > > >
> > > > I like it. Reporting pressure information of keys is currently a huge
> > > > hassle and this would simplify it a lot.
> > > >
> > > > The question I see is whether to extend evdev with EV_PSR (or EV_ABS2
> > > > for that matter), or to switch to multitouch'ish reports, which simply
> > > > combine multiple input-events.
> > >
> > > What do you mean with multitouch'ish reports? Reporting something other
> > > than input_event or something through the fd? I guess you are looking at
> > > a way to not send too many reports through evdev? It can be quite noisy
> > > many modern game devices have sample rates close to 1kHz, so a lot of
> > > events events just for digital buttons and some analog sticks alone already.
> >
> > I *think* what David meant is some sort of multiplexing where the key
> > itself would be just one value and the actual events refer to state of that
> > value. the mt protocol gives you ABS_MT_SLOT and then a bunch of axes you
> > can send for that slot. Moving the EV_PSR to something similar would likely
> > be using PSR_SLOT like the slot and then using other axes/identifiers to
> > send specific information.
> >
> > The biggest advantage here is that you can add information later that you
> > haven't thought of now. A made-up event sequence would be something like:
> >
> > EV_PSR PSR_SLOT 1
> > EV_PSR PSR_KEY_MAP KEY_A
> > EV_PSR PSR_PRESSURE 80
> > SYN_REPORT
> > EV_PSR PSR_PRESSURE 85
> > EV_PSR PSR_LOGICALLY_DOWN 1
> > EV_KEY KEY_A 1
> > SYN_REPORT
> > EV_PSR PSR_PRESSURE 82
> > SYN_REPORT
> > EV_PSR PSR_PRESSURE 80
> > EV_PSR PSR_LOGICALLY_DOWN 0
> > EV_KEY KEY_A 0
> > SYN_REPORT
> > .. maybe some terminating event equivalent to TRACKING_ID -1
> >
> > PSR_KEY_MAP would be the "this key maps to EV_KEY KEY_A" event which can now
> > tie those together. Pressure is obvious. It's fairly easy to add things like
> > EV_PSR/PSR_LOGICALLY_DOWN for binary click emulation. Together with the
> > PSR_KEY_MAP event this would allow for filtering of EV_KEY events provided
> > they come in the same frame. Free backwards compatibility, what's not to
> > like!
> 
> I had to think a bit before coming back and I kind of like the
> direction In this sample sequence I guess you were assuming the
> mapping of slots to 'keys' was dynamic. If I understood it correctly
> upon activation of a particular slot, PSR_KEY_MAP would be emitted?

yep, that's a direct equivalent to the mt approach.

> > I'm not sure whether we need an event for sequence tracking. the states
> > aren't necessarily sequence based like a touch is but they're pretty close.
> > It certainly relies on the driver knowing what the neutral state is and
> > emulating that.
> >
> > That aside, I'd strongly advocate **not** using struct absinfo but making
> > new ones even if it looks exactly the same. Anything using EV_PSR needs new
> > code anyway, might as well not accidentally limit yourself to something you
> > can't independently extend.
> 
> For absinfo, I have been thinking of having an ioctl (EVIOCGPSRINFO)
> which returns a list of 'key value' pairs instead of a struct to be
> more future proof. Kind of like EVIOCGMTSLOTS e.g.
> 
> struct input_psrinfo {
>     __u32 code;
>     struct input_psr_value values[num_values];
> }
> 
> Code would be something like KEY_A if we used the key codes, though
> could also be the slot id if they are fixed. Though KEY_A I think
> makes more sense also in relation to EVIOCGBIT for which I'm currently
> reusing the key codes.

just to state this again: I think it's a bad idea to use any non-PSR_foo
defines as identifiers in any PSR-related ioctls/structs/functions. Having a
mapping between them is fine as separate request, but if you want psrs, you
should interact with evdev through PSR_foo defines.

It cuts a lot of corners now and makes things easy, but long-term these
things have a tendency to come back and bite you. Like the simple case of
having a PSR that's not tied to any specific key code.

> Possible 'keys' in values could be: PSR_MIN, PSR_MAX, PSR_RES,..

So basically this?

struct input_psr_value {
        int key; /* one of PSR_MIN */
        int value;
}

for each key in values:
   if key == PSR_MIN:
       minimum = values[key];

This should work, yes, at least until we need something other than ints :)

fwiw, this isn't really what EVIOCGMTSLOTS does, mostly because that one is
the case of multiple slots using the same absinfo but have different values
for that axis. In your case it's more like  a generic implementation of
EVIOCGABS, but let's not compare because it just gets confusing if we liken
it to an existing ioctl.


> > Anyway, there are a few other things like: is the key map static for the
> > slot? If so you can make it available through your ioctl and simply rely on
> > the client to know this. Instead of slots you can then use magic
> > identifiers (i.e. PSR_SLOT 13 is always that thing that maps to KEY_A when
> > pressed). Not sure that's a useful solution. It probably requires more
> > storage and handling client-side but I'll throw it out there anyway)
> 
> I have been going back and forth about whether they map should be
> static or dynamic, but I'm still not sure. Let me clarify we mean the
> same with dynamic/static.
> 
> I assume you are referring to static as in a static mapping for a
> given device, so once the application enumerated the device and its
> capabilities it can assume as you said PSR_SLOT 13 always maps to
> KEY_A. In this case the event sequence would more simple as there is
> no need for a PSR_KEY_MAP.

correct, that's what I meant by static.

> For dynamic you mean the slot is picked dynamically at runtime based
> on buttons pressed kind of like the multitouch interface? Wooting
> devices kind of mimic this behaviour as it maintains a buffer of
> analog values for 'pressed buttons'. If I look at our devices the
> input report contains all device state independent of pressed buttons,
> so a fairly static mapping I guess. Unless only a slot is allocated
> for 'non-zero PSR values' and the slot is 'released' upon return to 0.
> Though I fear complicated book keeping driver side, an input driver
> would need to keep track of which slots are mapped to which 'pressure
> button' and 'release' slots when not needed anymore. Unless I missed
> something or if there is a better way...

I think that's what I meant yeah. The slot ID in this case would merely be
an id of slots (though the indices are not sequential). This works fine for
MT devices already and userspace can deal with it too - usually by
allocating some array[num_slots] and using the slot as index into that
array. Most drivers re-use slot numbers but one of the apple drivers (magic
trackpad?) just goes up sequentially and loops around.
You only need a bitfield to tell you whether a slot is active or not.

The main drawback of this approach is that it *has* to be sequence-based. If
buttons never return to a neutral end-state, then dynamic slots cannot work.
It works fine for touches where there is a definitive end, for PSR - not
sure.

> How to manage the slots and query their info is definitely the main
> challenge left.

my gut feeling is: start with dynamic slots and switch to static if you run
into walls. The other way round (static first) is less likely to show
whether dynamic slots might be sufficient.

Cheers,
   Peter

 
> > Is pressure the only thing that matters? If no, then you almost have to go
> > with this approach or something similar. I suspect by the time we get this
> > ready someone comes up with a hover-sensitve and pressure-sensitive
> > button :)
> 
> I'm sure something new pops up, standards exist to break ...
> 
> > Cheers,
> >    Peter
> 
> Thanks,
> Roderick



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux