diff mbox series

Proposal to support pressure sensitive "analog" buttons in evdev

Message ID 1DD62093774CEE42AFC16E785A1088049E38CBF6@USCULXMSG13.am.sony.com (mailing list archive)
State New, archived
Headers show
Series Proposal to support pressure sensitive "analog" buttons in evdev | expand

Commit Message

Colenbrander, Roderick July 30, 2018, 11:44 p.m. UTC
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


---
   Documentation/input/event-codes.rst    | 21 +++++++++++++++++++++
   include/uapi/linux/input-event-codes.h |  1 +
   include/uapi/linux/input.h             | 14 ++++++++++++++
   3 files changed, 36 insertions(+)

settings */
@@ -232,6 +243,9 @@ struct input_mask {
    */
   #define EVIOCSMASK		_IOW('E', 0x93, struct input_mask)	/* Set
event-masks */

+#define EVIOCGPSR		_IOR('E', 0x94, struct input_psrinfo)	/* get psr
value/limits */
+#define EVIOCSPSR		_IOW('E', 0x95, struct input_psrinfo)	/* set psr
value/limits */
+
   #define EVIOCSCLOCKID		_IOW('E', 0xa0, int)			/* Set clockid to be
used for timestamps */

   /*

Comments

David Herrmann July 31, 2018, 6:51 a.m. UTC | #1
Hi

(+CC Dmitry, Jiri, Peter, Benjamin)

On Tue, Jul 31, 2018 at 1:48 AM <Roderick.Colenbrander@sony.com> 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. Furthermore, the current
'input_device->absinfo' array is already quite big. Adding another one
with an entry for *every* possible key will probably not work out. So
the implementation will probably not be straightforward.

Thanks
David

>
> ---
>    Documentation/input/event-codes.rst    | 21 +++++++++++++++++++++
>    include/uapi/linux/input-event-codes.h |  1 +
>    include/uapi/linux/input.h             | 14 ++++++++++++++
>    3 files changed, 36 insertions(+)
>
> diff --git a/Documentation/input/event-codes.rst
> b/Documentation/input/event-codes.rst
> index a8c0873beb95..846562d4db4b 100644
> --- a/Documentation/input/event-codes.rst
> +++ b/Documentation/input/event-codes.rst
> @@ -41,6 +41,11 @@ Codes section for details on valid codes for each type.
>      - Used to describe state changes of keyboards, buttons, or other
> key-like
>        devices.
>
> +* EV_PSR:
> +
> +  - Used to describe pressure sensitive 'analog' buttons, e.g. analog
> buttons
> +    on arcade sticks, gamepads or keyboards.
> +
>    * EV_REL:
>
>      - Used to describe relative axis value changes, e.g. moving the
> mouse 5 units
> @@ -177,6 +182,22 @@ a value of 1 in the same synchronization frame.
> This usage is deprecated.
>    Note: In multitouch drivers, the input_mt_report_finger_count()
> function should
>    be used to emit these codes. Please see multi-touch-protocol.txt for
> details.
>
> +EV_PSR
> +------
> +
> +EV_PSR events describe absolute changes in a key press-like event. It
> is used
> +for devices reporting pressure senstive / analog key presses. These events
> +can't be described through EV_KEY as it is a digital only interface.
> +
> +Pressure senstive keys can be found on gaming devices, keyboards and
> other devices.
> +These devices often report both digital and pressure sensitive events
> for a given
> +key. For this reason, the KEY_<name> and BTN_<name> codes as defined
> for EV_KEY
> +are reused. A device supporting digital and pressure sensitive events
> for the same
> +key, should use the same key code across EV_KEY and EV_PSR.
> +
> +The value range and resolution for a pressure sensitive button can be
> obtained
> +through EVIOCGPRS.
> +
>    EV_REL
>    ------
>
> diff --git a/include/uapi/linux/input-event-codes.h
> b/include/uapi/linux/input-event-codes.h
> index 53fbae27b280..d142498fc64c 100644
> --- a/include/uapi/linux/input-event-codes.h
> +++ b/include/uapi/linux/input-event-codes.h
> @@ -41,6 +41,7 @@
>    #define EV_ABS                       0x03
>    #define EV_MSC                       0x04
>    #define EV_SW                        0x05
> +#define EV_PSR                 0x06
>    #define EV_LED                       0x11
>    #define EV_SND                       0x12
>    #define EV_REP                       0x14
> diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> index 7288a7c573cc..f5ce2abde800 100644
> --- a/include/uapi/linux/input.h
> +++ b/include/uapi/linux/input.h
> @@ -121,6 +121,17 @@ struct input_mask {
>         __u64 codes_ptr;
>    };
>
> +
> +/**
> + * struct input_psrinfo - used by EVIOCGPRS/EVIOSPRS ioctls.
> + * @code: pressure sensitive key to query.
> + * @info: value/limits for this key.
> + */
> +struct input_psrinfo {
> +       __u16 code;
> +       struct input_absinfo info; //should this be its own psr specfic struct??
> +};
> +
>    #define EVIOCGVERSION                _IOR('E', 0x01, int)                    /* get driver version */
>    #define EVIOCGID             _IOR('E', 0x02, struct input_id)        /* get device ID */
>    #define EVIOCGREP            _IOR('E', 0x03, unsigned int[2])        /* get repeat
> settings */
> @@ -232,6 +243,9 @@ struct input_mask {
>     */
>    #define EVIOCSMASK           _IOW('E', 0x93, struct input_mask)      /* Set
> event-masks */
>
> +#define EVIOCGPSR              _IOR('E', 0x94, struct input_psrinfo)   /* get psr
> value/limits */
> +#define EVIOCSPSR              _IOW('E', 0x95, struct input_psrinfo)   /* set psr
> value/limits */
> +
>    #define EVIOCSCLOCKID                _IOW('E', 0xa0, int)                    /* Set clockid to be
> used for timestamps */
>
>    /*
> --
> 2.14.3
>
> --
> 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
--
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
Bastien Nocera July 31, 2018, 9:38 a.m. UTC | #2
Hey,

On Mon, 2018-07-30 at 23:44 +0000, Roderick.Colenbrander@sony.com
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).
> 
<snip>
> 
> 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

Are there already user-space APIs, such as SDL, or the Steam joypad
user-space gunk, that support those types of input (even if that's not
implemented on Linux yet)?

What do those user-space APIs look like? Would they be a good fit for
this kernel API, and would the chatter/amount of data to process be too
much?

Cheers
--
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
Colenbrander, Roderick July 31, 2018, 6:57 p.m. UTC | #3
On 07/31/2018 02:39 AM, Bastien Nocera wrote:
> Hey,
> 
> On Mon, 2018-07-30 at 23:44 +0000, Roderick.Colenbrander@sony.com
> 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).
>>
> <snip>
>>
>> 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
> 
> Are there already user-space APIs, such as SDL, or the Steam joypad
> user-space gunk, that support those types of input (even if that's not
> implemented on Linux yet)?

I have seen a variety of proprietary APIs more in gamepad land. They 
often mimic the hardware closely. In case of gamepads they tend to 
report large self contained HID reports containing all axes, button and 
analog button state. The resulting APIs tend to look like the win32 
xinput API reporting a huge struct to user space.

I haven't seen anything in the SteamController API explicitly support 
these capabilities, but they have a concept of "analog action data" 
though currently coming from regular axes. I suppose they could extend 
this if they wanted to. SDL doesn't have a mechanism as far I'm aware.

As for analog keyboards, Jeroen can provide some more details, but my 
understanding is that there is no good OS support right now on any OS. 
As a initial approach the Wooting devices also report themselves as a 
HID gamepad and xinput gamepad. This allows them to at least inject some 
analog input into games through gaming APIs. DirectInput is most 
flexible as it supports a large number of axes and buttons.

> 
> What do those user-space APIs look like? Would they be a good fit for
> this kernel API, and would the chatter/amount of data to process be too
> much?

I'm not sure what the best API. Some of the proprietary APIs I have seen 
don't scale as they assume fixed data structures, but keep the number of 
calls low. DirectInput-like APIs which don't care about number of axes / 
buttons (and evdev is kind of like that) are probably best.

Amount of chatter is indeed a concern as evdev buffer sizes are 
typically small. Just of our gamepads I remember just on a table the 
values can easily fluctuate, so 'fuzz' like values should be important.
I think Wooting currently reports analog values for buttons 'pressed' 
and not if not pressed. I suspect they have an adjustable threshold or 
something. On gamepads we report them all the time (though we only have 
few buttons.

For me the question is what is the difference between a 'pressure 
sensitive button' and an 'axis'? At a high-level they are similar, but 
does one need extra APIs for best support?

Thanks,
Roderick

--
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
Colenbrander, Roderick July 31, 2018, 8:49 p.m. UTC | #4
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@sony.com> 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.

> Furthermore, the current
> 'input_device->absinfo' array is already quite big. Adding another one
> with an entry for *every* possible key will probably not work out. So
> the implementation will probably not be straightforward.

Yeah storage of the array needs consideration. I was considering an 
absinfo-like struct, which also contains 'code'. This can be handy for 
kernel side (e.g. storing the struct in some kind of list). It can also 
be handy if we want userspace to query multiple values through a single 
ioctl, though not a big fan of 'inout' parameters if they can be avoided.

> 
> Thanks
> David

--
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
Bastien Nocera Aug. 1, 2018, 12:12 p.m. UTC | #5
On Tue, 2018-07-31 at 18:57 +0000, Roderick.Colenbrander@sony.com
wrote:
> 
<snip>
> For me the question is what is the difference between a 'pressure 
> sensitive button' and an 'axis'? At a high-level they are similar,
> but 
> does one need extra APIs for best support?

3 things I think:
- you don't have a concept of "not pressed" for an axis. Sure it has a
resting/default position, but you have to encode that press boolean
somehow
- axis wouldn't be able to support something like the GameCube trigger,
which has a click when pushed down fully. I don't know how this is
encoded, and whether this is just a higher value for the axis, or
actually sends that data out.

I'm guessing you plan on sending both the analog and digital value at
the same time to user-space, if so, we really need a way to match
corresponding analog buttons with their digital counterparts, otherwise
user-space will have difficulty handling devices with a mix of digital-
only and analog-capable buttons.

Does that make sense?

If you want to decant the API a bit quicker, it would be great if you
also ported, say, the PS3/PS4 joypad driver, and had a patch to evtest
available. Then user-space developers would be able to test the API
before it lands fully in the kernel.

Cheers
--
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
Colenbrander, Roderick Aug. 4, 2018, 12:27 a.m. UTC | #6
On 08/01/2018 05:13 AM, Bastien Nocera wrote:
> On Tue, 2018-07-31 at 18:57 +0000, Roderick.Colenbrander@sony.com
> wrote:
>>
> <snip>
>> For me the question is what is the difference between a 'pressure
>> sensitive button' and an 'axis'? At a high-level they are similar,
>> but
>> does one need extra APIs for best support?
> 
> 3 things I think:
> - you don't have a concept of "not pressed" for an axis. Sure it has a
> resting/default position, but you have to encode that press boolean
> somehow

That's certainly a difference. I looked a bit at how different hardware 
is handling this. I think DS3 always reports non-zero analog values even 
if 'not pressed'. Wooting currently reports analog values for pressed 
keys. To be exact it maintains a small buffer containing the scancode of 
"pressed keys" and their analog value. They have an adjustable threshold 
in hardware at what "depth" to trigger a digital key press.

Maybe there will be hardware as well, which doesn't generate the digital 
click, but expects software to "fake digital press". Maybe we need to 
allow that flexibility somehow in the API or at least a way to adjust 
threshold long-term for drivers wanting to offer that. (Through a flag?)

> - axis wouldn't be able to support something like the GameCube trigger,
> which has a click when pushed down fully. I don't know how this is
> encoded, and whether this is just a higher value for the axis, or
> actually sends that data out.

Interesting wasn't aware of that. Something to explore how this is the case.

> I'm guessing you plan on sending both the analog and digital value at
> the same time to user-space, if so, we really need a way to match
> corresponding analog buttons with their digital counterparts, otherwise
> user-space will have difficulty handling devices with a mix of digital-
> only and analog-capable buttons.

My current thought in the proposal was to tie the EV_KEY and EV_PSR 
together by using the same codes (and maybe a special addition PSR 
specific range long-term). Though not the biggest fan. Another way is to 
offer in a "struct psrinfo" struct the value of an associated EV_KEY.

This is I think among the trickier parts to solve.

(Actually we kind of have the same issue already for regular axes. Some 
of these have a button press already. Left/right trigger is an axes, but 
also offers a digital press and the same for left/right sticks. There 
only few codes there, so I guess it is fine.)

> Does that make sense?
> 
> If you want to decant the API a bit quicker, it would be great if you
> also ported, say, the PS3/PS4 joypad driver, and had a patch to evtest
> available. Then user-space developers would be able to test the API
> before it lands fully in the kernel.
> 

We will write an initial implementation for evdev and at least 1 driver 
supporting it probably hid-sony for DS3 or uinput.

Thanks,
Roderick
--
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
Peter Hutterer Aug. 6, 2018, 6:50 a.m. UTC | #7
On Tue, Jul 31, 2018 at 08:49:08PM +0000, Roderick.Colenbrander@sony.com 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@sony.com> 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'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.

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)

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 :)

Cheers,
   Peter


> > Furthermore, the current
> > 'input_device->absinfo' array is already quite big. Adding another one
> > with an entry for *every* possible key will probably not work out. So
> > the implementation will probably not be straightforward.
> 
> Yeah storage of the array needs consideration. I was considering an 
> absinfo-like struct, which also contains 'code'. This can be handy for 
> kernel side (e.g. storing the struct in some kind of list). It can also 
> be handy if we want userspace to query multiple values through a single 
> ioctl, though not a big fan of 'inout' parameters if they can be avoided.
> 
> > 
> > Thanks
> > David
> 
> 
--
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
Roderick Colenbrander Aug. 27, 2018, 4:49 a.m. UTC | #8
On Sun, Aug 5, 2018 at 11:55 PM Peter Hutterer <peter.hutterer@who-t.net> wrote:
>
> On Tue, Jul 31, 2018 at 08:49:08PM +0000, Roderick.Colenbrander@sony.com 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@sony.com> 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?

> 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.

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

>
> 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.

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...

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

> 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
Peter Hutterer Aug. 29, 2018, 4:34 a.m. UTC | #9
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@who-t.net> wrote:
> >
> > On Tue, Jul 31, 2018 at 08:49:08PM +0000, Roderick.Colenbrander@sony.com 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@sony.com> 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
diff mbox series

Patch

diff --git a/Documentation/input/event-codes.rst
b/Documentation/input/event-codes.rst
index a8c0873beb95..846562d4db4b 100644
--- a/Documentation/input/event-codes.rst
+++ b/Documentation/input/event-codes.rst
@@ -41,6 +41,11 @@  Codes section for details on valid codes for each type.
     - Used to describe state changes of keyboards, buttons, or other
key-like
       devices.

+* EV_PSR:
+
+  - Used to describe pressure sensitive 'analog' buttons, e.g. analog
buttons
+    on arcade sticks, gamepads or keyboards.
+
   * EV_REL:

     - Used to describe relative axis value changes, e.g. moving the
mouse 5 units
@@ -177,6 +182,22 @@  a value of 1 in the same synchronization frame.
This usage is deprecated.
   Note: In multitouch drivers, the input_mt_report_finger_count()
function should
   be used to emit these codes. Please see multi-touch-protocol.txt for
details.

+EV_PSR
+------
+
+EV_PSR events describe absolute changes in a key press-like event. It
is used
+for devices reporting pressure senstive / analog key presses. These events
+can't be described through EV_KEY as it is a digital only interface.
+
+Pressure senstive keys can be found on gaming devices, keyboards and
other devices.
+These devices often report both digital and pressure sensitive events
for a given
+key. For this reason, the KEY_<name> and BTN_<name> codes as defined
for EV_KEY
+are reused. A device supporting digital and pressure sensitive events
for the same
+key, should use the same key code across EV_KEY and EV_PSR.
+
+The value range and resolution for a pressure sensitive button can be
obtained
+through EVIOCGPRS.
+
   EV_REL
   ------

diff --git a/include/uapi/linux/input-event-codes.h
b/include/uapi/linux/input-event-codes.h
index 53fbae27b280..d142498fc64c 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -41,6 +41,7 @@ 
   #define EV_ABS			0x03
   #define EV_MSC			0x04
   #define EV_SW			0x05
+#define EV_PSR			0x06
   #define EV_LED			0x11
   #define EV_SND			0x12
   #define EV_REP			0x14
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 7288a7c573cc..f5ce2abde800 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -121,6 +121,17 @@  struct input_mask {
   	__u64 codes_ptr;
   };

+
+/**
+ * struct input_psrinfo - used by EVIOCGPRS/EVIOSPRS ioctls.
+ * @code: pressure sensitive key to query.
+ * @info: value/limits for this key.
+ */
+struct input_psrinfo {
+	__u16 code;
+	struct input_absinfo info; //should this be its own psr specfic struct??
+};
+
   #define EVIOCGVERSION		_IOR('E', 0x01, int)			/* get driver version */
   #define EVIOCGID		_IOR('E', 0x02, struct input_id)	/* get device ID */
   #define EVIOCGREP		_IOR('E', 0x03, unsigned int[2])	/* get repeat