KarsMulder / evsieve

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

how to output as a virtual joystick? #34

Open zacharyburnett opened 1 year ago

zacharyburnett commented 1 year ago

Hello! I have a spacenavigator 6dof mouse, and am trying to convert its events to a joystick output. It currently resides at /dev/input/event3.

evtest shows relative events:

evtest /dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x46d product 0xc626 version 0x111
Input device name: "3Dconnexion SpaceNavigator"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 256 (BTN_0)
    Event code 257 (BTN_1)
  Event type 2 (EV_REL)
    Event code 0 (REL_X)
    Event code 1 (REL_Y)
    Event code 2 (REL_Z)
    Event code 3 (REL_RX)
    Event code 4 (REL_RY)
    Event code 5 (REL_RZ)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
  Event type 17 (EV_LED)
    Event code 8 (LED_MISC) state 0
Properties:
Testing ... (interrupt to exit)
Event: time 1687015718.431329, type 2 (EV_REL), code 3 (REL_RX), value -4
Event: time 1687015718.431329, -------------- SYN_REPORT ------------
Event: time 1687015718.439301, type 2 (EV_REL), code 1 (REL_Y), value -10
Event: time 1687015718.439301, -------------- SYN_REPORT ------------
Event: time 1687015718.447323, type 2 (EV_REL), code 3 (REL_RX), value -30
Event: time 1687015718.447323, -------------- SYN_REPORT ------------

Additionally, I can run evsieve with the following arguments:

sudo evsieve --input /dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00 --output create-link=/dev/input/js0

and then read /dev/input/js0 with evtest to get the same relative events as before.

However, this is obviously just passing the raw events and not outputting a proper joystick / controller format; KDE's fancy Game Controller page tells me this: image

I apologize if this is trivial, but after going through the README I am still confused on how to actually make joystick output with evsieve. What mappings should I be using? Should these be absolute events instead?

Thanks!

zacharyburnett commented 1 year ago

I did look into using spacenavd and libspnav; they appear, however, to be focused on providing input to CAD software instead of outputting as a joystick.

KarsMulder commented 1 year ago

I think the reason that your mouse is not getting detected as a joystick is because most joysticks use EV_ABS events, whereas your mouse is emitting EV_REL events. On the latest stable evsieve, you could try using

evsieve --input /dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00 \
        --map rel:x abs:x \
        --map rel:y abs:y \
        --map rel:z abs:z \
        --map rel:rx abs:rx \
        --map rel:ry abs:ry \
        --map rel:rz abs:rz \
        --output abs create-link=/dev/input/js0

... but you will probably run into issues because this results in the possible output values being theoretically unbounded (and with 32-bit integer limitations, bounded by [-2147483648, 2147483647]). Since I suppose much software will determine how far the joystick has been moved by comparing its current value to the range of the axes, a value of 30 will probably be treated as a negligible movement.

To fix this on the latest stable version, I suppose you could try to multiply the movement by a big value?

evsieve --input /dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00 \
        --map rel:x abs:x \
        --map rel:y abs:y \
        --map rel:z abs:z \
        --map rel:rx abs:rx \
        --map rel:ry abs:ry \
        --map rel:rz abs:rz \
        `Multiply the value of all EV_ABS events by 30000000.` \
        --map abs ::30000000x \
        --output abs create-link=/dev/input/js0

For a more sensible solution to this problem, I made it possible on the development main branch to specify a range of values for output keys, to clip the axes within a certain range of values, e.g.

evsieve --input /dev/input/by-id/usb-3Dconnexion_SpaceNavigator-event-if00 \
        --map rel:x abs:x:-64~64 \
        --map rel:y abs:y:-64~64 \
        --map rel:z abs:z:-64~64 \
        --map rel:rx abs:rx:-64~64 \
        --map rel:ry abs:ry:-64~64 \
        --map rel:rz abs:rz:-64~64 \
        --output abs create-link=/dev/input/js0

will clip the values for all EV_ABS events in the range [-64, 64]. Depending on the range of what your mouse output, another range may be more suitable.

(The reason this is not possible on the stable version yet is because I wasn't sure whether I wanted to use ranges on output events for clipping or for scaling, so I had left unimplemented. By now, we already have another way to scale events but no way to clip them, so I suppose it makes sense to use ranges on output events for clipping.)


The above is based on the assumption that your mouse uses EV_REL events to report absolute values, which seems the most likely way based on what the mouse looks like. If I am wrong and the above does not work properly because it uses EV_REL events to report actually relative values, then check out the new --rel-to-abs argument that I just implemented on the main branch for issue #33.)

zacharyburnett commented 1 year ago

wow, installing evsieve-git and then using your third example with [-350, 350] worked perfectly!

Thanks for your help!