KarsMulder / evsieve

A utility for mapping events from Linux event devices.
GNU General Public License v2.0
199 stars 11 forks source link

Missing Event Codes between BTN_BASE6 and BTN_DEAD? #20

Closed Karnith-Sylass closed 1 year ago

Karnith-Sylass commented 1 year ago

Hi I have found evsieve very useful to create a virtual device merging a joystick and throttle (HOTAS) for use with older games that can only handle one joystick.

However, both the joystick and throttle have buttons whose event_codes show as '?' in evtest, with numeric values for the codes from 300 to 302.

Looking at linux/input-event-codes.h I can see there is a gap from BTN_BASE6, 0x12b (299) to BTN_DEAD, 0x12f (303).

If these points will not have codes assigned to them is there a way to permit providing the actual code value instead (whether in hex or decimal)? Thank you.

KarsMulder commented 1 year ago

I didn't think that "events codes show up that don't have a name" would actually happen, but it turns out I was wrong. The current stable version does not make it possible to generate unnamed event codes. Some libevdev functions say that they have undefined behaviour if called with the wrong code (though libevdev_uinput_write_event is not one of those functions) so I had been a bit paranoid about not generating invalid (type, code) pairs. However, if unnamed codes actually have an use, then I suppose it is very much in line with the UNIX philosophy to allow users to shoot themselves in the foot if they want to.

I added a feature to refer to types/codes by their numeric value to the main branch. For example, the following arguments are now all equivalent to each other:

        --map key:a key:b
        --map key:%30 key:%48
        --map %1:%30 %1:%48

The % prefix is required when using numeric types/codes because otherwise there would be edge cases like key:1 getting interpreted as (EV_KEY, KEY_1) instead of (EV_KEY, 1). I'm not a particular fan of the % character for this purpose, but the # character has a special interpretation in some shells and I couldn't think of another more suitable character.


Now for a design issue that may not have an elegant answer:

The kernel sorts all KEY_* and BTN_* under EV_KEY whereas evsieve considers them to be different types, so e.g. --print key will print key:left events but not btn:left events. Now, suppose an unknown event code is introduced by --map key:a %1:%300 --print key, should this event be printed or not?

In case the user actually specifies the type like --map key:a key:%300 or --map key:a btn:%300 the above question seems answerable, but that introduces another edge case:

Suppose that some input device generates events (EV_KEY, 300) and suppose that --input $DEVICE --print key prints this event, and the user then later adds a map like --input $DEVICE --print key --map key:a btn:%300, indicating that the user considers code 300 to belong to the btn type, should the the argument --print key now suddenly start behaving differently because of another unrelated argument that came after it?

Karnith-Sylass commented 1 year ago

Thank you very much for this update and the detailed response. I think this closes the issue I had and have marked this closed.

As for the issues you mentioned as to key vs btn, I am not sure I follow your last example as the --map happens after the --print. Given the "pipe" like approach shouldn't this mean that a subsequent --map cannot affect an earlier --print? On the point of principle though, it seems to me that given evsieve has made the separation between key and btn that after a mapping print would respect that distinction. Of course this would align with the UNIX philosophy you mentioned.

KarsMulder commented 1 year ago

Let's look at a more concrete sample:

evsieve --input /dev/input/by-id/joystick-1 grab \
        --output key create-link=/dev/input/by-id/keys-1 \
        --output btn create-link=/dev/input/by-id/buttons-1

Assume that joystick-1 generates (EV_KEY, 300) events. These events should be sent to either the keys-1 virtual device or the buttons-1 virtual device, but since the is no name available for code 300, there is no real sensible way to decide to which it goes. (In the current main branch, said event would be sent to the buttons-1 device.)

Now suppose that the user were to add something after the script:

evsieve --input /dev/input/by-id/joystick-1 grab \
        --output key create-link=/dev/input/by-id/keys-1 \
        --output btn create-link=/dev/input/by-id/buttons-1 \
        --input /dev/input/by-id/joystick-2 grap \
        --print key:%300 \
        --output key create-link=/dev/input/by-id/keys-2 \
        --output btn create-link=/dev/input/by-id/buttons-2

Assume that joystick-2 also generates (EV_KEY, 300) events. Because the user calls it key:%300, you could say that it should be treated as a key type event.

There are three different things evsieve could do in this case, each of which is "incorrect" in some way:

  1. The (EV_KEY, 300) events from joystick-1 get sent to buttons-1 while the (EV_KEY, 300) event from joystick-2 get sent to keys-2, even though the --print argument shouldn't actually modify key:%300 events;
  2. The mere presence at of key:300 some point in the program causes all (EV_KEY, 300) from joystick-1 to get sent to keys-1 instead of buttons-1, even though the --print argument should have no impact on joystick-1;
  3. All (EV_KEY, 300) events get sent to the buttons-* devices even though the user called them key:300.
KarsMulder commented 1 year ago

... maybe I just misunderstood the problem in the original post, but I just realized there is a much bigger problem than just being unable to name event codes like (EV_KEY, 300).

In the current stable version, something simple like evsieve --input $DEVICE grab --output fails to replicate the (EV_KEY, 300) events emitted by the input device because it currently only tests the input device's capabilities for all named event types.

I just fixed this bug in the main branch.

Karnith-Sylass commented 1 year ago

Hi KarsMulder. Thank you very much for the further fix; I was experiencing the bug you mention and trying to work out what could be done as capabilities of the output virtual device did not match the input when testing with evtest (due to the testing issue you mentioned).

In relation to your thoughts on key vs btn conflict, I see the issue you raise. Now that you have introduced reference to event codes by number it probably should be addressed (whereas before I understand the key / btn dichotomy was strictly enforced automatically).

Given the split into key and btn within evsieve I think the only principled solution would be to limit use of key and btn to refer to actual event code numbers by reference to specified ranges of numbers. From input-event-codes.h it appears justifiable ranges would be key: 1-248, 352-542, 560-700, 767-768 and btn: 256-337, 544-547, 704-743.

Thanks again for your help.