evsieve icon indicating copy to clipboard operation
evsieve copied to clipboard

Remap controller dpad buttons to mouse

Open iuncuim opened this issue 3 months ago • 5 comments

Hi, I am trying to emulate a mouse using a gamepad without adc sticks.

My config:

sudo evsieve --input /dev/input/by-path/platform-gpio-keys-gamepad-event-joystick \
        --map btn:dpad_left:1~2      rel:x:-20 \
        --map btn:dpad_right:1~2     rel:x:20 \
        --map btn:dpad_up:1~2        rel:y:-20 \
        --map btn:dpad_down:1~2      rel:y:20 \
        --map btn:tl:0~1     btn:left  \
        --map btn:tr:0~1     btn:right \
        --output create-link=/dev/input/by-id/guest-mouse

When I launch evtest, I see that the remapping works, but mouse control does not. The LMB and RMB buttons do not work either.

But if I replace rel:x with abs:x, the cursor starts moving around the corners of the screen, and the RMB and LMB buttons also work.

I tried to do a similar setup on my laptop (with different dev names, of course) and it didn't work either. I used the numbered release and the -git version from the aur repository.

iuncuim avatar Sep 27 '25 04:09 iuncuim

My best guess is that the issue is that your virtual device is getting recognized as the wrong device type. Because most of the original joystick events will also be written to your virtual device, it is marked as capable of emitting various kinds of events you usually only encounter on joysticks, thus it is possible that libinput recognizes it as some kind of joystick and not as a mouse, and will subsequently interpret the rel/btn events as some kind of joystick gestures or buttons.

Try creating an output device that does not emit the original joystick events. Hopefully this device will be recognized as a proper mouse:

sudo evsieve --input /dev/input/by-path/platform-gpio-keys-gamepad-event-joystick \
        --map yield btn:dpad_left:1~2      rel:x:-20 \
        --map yield btn:dpad_right:1~2     rel:x:20 \
        --map yield btn:dpad_up:1~2        rel:y:-20 \
        --map yield btn:dpad_down:1~2      rel:y:20 \
        --map yield btn:tl:0~1             btn:left  \
        --map yield btn:tr:0~1             btn:right \
        `# Drop all events that have not been yielded.` \
        --block \
        --output create-link=/dev/input/by-id/guest-mouse

KarsMulder avatar Sep 30 '25 20:09 KarsMulder

Thanks for your reply. I'll try your recommendations later and let you know how it goes

iuncuim avatar Oct 03 '25 05:10 iuncuim

@KarsMulder Yeah, it works, thank you! Could you also tell me how to set up repeated pressing of a virtual button after a certain period of time when the real button is held down? For example, if I hold down dpad_left, I want the mouse cursor to move left all the time while the button is held down. Is that possible?

iuncuim avatar Oct 04 '25 05:10 iuncuim

Could you also tell me how to set up repeated pressing of a virtual button after a certain period of time when the real button is held down?

There was no way to get that done. I'd considered that feature several times in the past but never got around to adding it because I couldn't decide on the ideal user interface for it. With this issue I once again realized how ridiculous it is that there is still no way to do something simple like "repeatedly press a button", so I decided to just add it (commit bb6d662).

The interface is:

    --oscillate [KEYS...] period=SECONDS

For example, the following script will cause the A key to be pressed and released every second on the virtual device when the user holds the A key down on the physical keyboard:

evsieve --input /dev/input/by-id/keyboard \
        --oscillate key:a period=1 \
        --output

Limitations: it only works for key and btn-type events.

(The issue with making it work for everything is that "what should happen" is something different for each event type. For key and btn events, you want it to be periodically be pressed up and down. For rel-type events, you instead want the same event to be emitted repeatedly. For abs-type events, you may want a stick to move up and down over a certain interval? If I then add concerns like "should have similar syntax to the existing --hook and --map arguments, you get the reason why I never decided on a user interface before. That concern has hereby been solved by making it only work for key and btn-type events.)

So, to move the cursor left whenever the dpad_left is held, you need to jump through a couple of hoops, mapping the abs events to key events before oscillating them and then mapping them to rel-events.

sudo evsieve --input /dev/input/by-path/platform-gpio-keys-gamepad-event-joystick \
        --hook btn:dpad_left:1~2  send-key=key:left \
        --hook btn:dpad_right:1~2 send-key=key:right \
        --hook btn:dpad_up:1~2    send-key=key:up \
        --hook btn:dpad_down:1~2  send-key=key:down \
        --oscillate key:left key:right key:up key:down period=0.01 \
        --map yield key:left:1  rel:x:-4 \
        --map yield key:right:1 rel:x:4 \
        --map yield key:up:1    rel:y:-4 \
        --map yield key:down:1  rel:y:4 \
        --map yield btn:tl:0~1  btn:left \
        --map yield btn:tr:0~1  btn:right \
        `# Drop all events that have not been yielded.` \
        --block \
        --output create-link=/dev/input/by-id/guest-mouse

KarsMulder avatar Oct 04 '25 19:10 KarsMulder

Excellent work, it works like a charm. Your program is a swiss army knife in the world of input device event handling. At the moment, it completely solves the part of the task that I wanted to accomplish.

If you're wondering what I plan to use your program for: https://forum.manjaro.org/t/support-for-orangepi-zero2-h616-ddr3-zero3-and-zero-2w-h618-lpddr4/154679/49

Perhaps someday you will also want to implement a feature that allows the program to emulate an Xbox controller, which activates built-in controller support in some programs (but mainly in games). This feature is available in xboxdrv (--mimic-xpad). It's not that I personally need this feature; I'm mainly interested in just running something, but it's possible that someone else might find this feature useful.

Thanks again for your work.

iuncuim avatar Oct 05 '25 05:10 iuncuim