[SOLVED] Selection jumps after the first input of a controller
-
@louiehummv i did get my old F30 connected to my Pi4 in switch mode and i can say that it does not jump like it did before.
and when i connect it in android mode it jumps again.
so it seems something with android mode. not sure what
-
@exarkuniv Interesting. I know in Switch mode the 8Bitdo controllers have its own problems.. at least according to my SF30/SN30 Pro findings 3 years ago. Unfortunately for me, I have 2 Logitech USB gamepads specifically using direct input (D-Input) with no mode-selection & are experiencing this problem too. Guess I'll keep chipping away..
-
@louiehummv i think those problems for the most part has been fixed or i think they have. i helped a friend build a system and he has 2 of the SN90 Pro+ and so far has not had any problems.
personally i dont use turbo mode so i dont know about that. but the bit that i did play i did not notice any analog range is only 85% that you found before.
granted they are the newest ones so different hardware.
ill play around with my F30 in switch mode and see if i can notice anything.
-
@exarkuniv Well, I must be getting old.. cause it turns out the selection was jumping on my RasPi 3B after all. Never noticed it (facepalm).. but like the old engineer I am, I now must do what I can to fix it. Luckily, I think I reached a stopping point.. get ready for a mind dump.
Turns out the cause is 2-fold, where one affects the other. The 1st issue is how the ranges of a controller's joystick axes are reported in the input systems (js or evdev, doesn't matter which). Those ranges vary by controller, varied again by mode. With regard to my setup, I've confirmed the axis ranges in evdev as follows:
SF30 Pro & SN30 Pro (firmware v1.34)
- Switch : 0 to 65535
- MacOS : couldn't retrieve because no event# or js# was generated by evdev or js (respectively).. go figure
- Windows (Xinput) : 0 to 65535
- Android (Dinput) : 0 to 255
Logitech USB Wireless Gamepad F710
- Xinput : -32768 to 32767
- Dinput : 0 to 255
Logitech USB Wireless RumblePad2
- Dinput only : 0 to 255
Meanwhile, the 2nd issue is the Northwest problem identified by Raphnet. In reality, it's not quite a "northwest" problem.. it's an initial value of 0 problem that updates/centers after the first input of the controller. Yes, I tried Raphnet's fixes.. but his diffs failed before I could try building the latest kernel. They are indeed outdated.. let alone too complex for me to debug.
So.. for x & y axis ranges starting at 0, what position is an initial value of 0? Northwest. But for x & y axis ranges where 0 is the midpoint? The position is center. Guess which controller of mine ended up not jumping the selection after all? My Logitech 710 in Xinput mode! But as expected, all the rest did jump the selection.
With regard to your F30, I have a hunch that its Switch mode reports axis ranges where 0 is the midpoint.. hence why it worked for you. You'd have to confirm those ranges using the evdev-joystick -s /dev/input/event# command, where # is the number assigned to your F30.
I also tried forcing the range maximums to 0 using a udev add-action rule with the evdev-joystick command. And because an initial value of 0 does fall between 0 (min) to 0 (max), the selection jumps didn't happen after tapping the direction pad! But at the same time, the joysticks were rendered unresponsive.
Guess now is a good time for me to stop. Either a controller's manufacturer has to fix the axis ranges with a 0 midpoint, someone really smart at Raphnet or affiliated with Linux needs to patch the latest kernel, or someone must offer a way to manually override the evdev initial value.. or to refresh a controller after being connected. And to add insult to injury, using jstest still mysteriously reports values between -32768 and 32767 as you push the joysticks, despite the aforementioned ranges.
TL;DR - Unless you buy the right controller with the right mode that reports axis ranges with a 0 midpoint,
there's currently no way to fix its selection jumps. -
@louiehummv hate to say it, but you have lost me with all of that. sorry
it is a bummer that its not working for you. i have done a half full of retropie systems all with 8bitdo controllers of different models. so far no one has complained about them other then the system jump after first power on. and for most, its not a big deal.
still odd either way though
-
@exarkuniv lol Np. That's the 15 years of technical writing in me.
In any case.. I wonder if there's a way to configure Emulation Station (not Retroarch) to use the js input driver instead of evdev. Doing so may work around this problem. Can't seem to find an option like that though.. but it could just be hidden or undocumented.
-
@louiehummv said in Selection jumps after the first input of a controller:
In any case.. I wonder if there's a way to configure Emulation Station (not Retroarch) to use the js input system instead of evdev. Doing so may work around this problem. Can't seem to find an option like that though.. but it could just be hidden or undocumented.
EmulationStation uses the SDL joystick sub-system, so it's a change that needs to be done on that level.
-
@mitu Is it worth explaining how to make that change? I don't know what that entails.
-
@louiehummv said in Selection jumps after the first input of a controller:
I don't know what that entails.
Neither do I, I was just pointing out that EmulationStation doesn't use the Linux joystick/evdev APIs directly, but SDL handles the joysticks. I think SDL uses the evdev interface for that.
-
@mitu I see now. I was hoping for something similar to Retroarch's "input driver" option in settings, but for Emulation Station. If not, sounds like the SDL source would require changing.. not really my expertise.
-
[BETTER SOLUTION] ..but keeping this post for reference & continuity.
Well.. I finally did the thing. Here's my workaround:
- Install the at job utility.
sudo apt install at
- Enable the atd scheduling daemon to start on-boot & run it.
sudo systemctl enable --now atd
- After connecting your controllers, record the exact name and event handler # of each one.
cat /proc/bus/input/devices
- Now record the axis #s, minimums, & maximums of each controller's analog axes. IGNORE ANY AXIS WHERE ITS MINIMUM & MAXIMUM NEGATE EACH OTHER; ITS MIDPOINT IS 0 AND THE AXIS SHOULD BE LEFT ALONE BY THIS WORKAROUND. In the following command, substitute the event# with that of the associated controller.
evdev-joystick --s /dev/input/event#
- Create a new udev rule. You may change the name, but leave the numerical prefix & file extension as-is.
sudo nano /etc/udev/rules.d/99-joystick.rules
- Add the following code line in the rules file per controller using the name, axis #s, minimums, & maximums you gathered earlier. You will need to edit the following template at the [BRACKETED ENTRIES]. Notice that before the at command, there is a evdev-joystick command for each axis to override its minimum & maximum to 0. And after the grep command, the original minimums & maximums for each axis are restored. In my controller, I had four analog axes.. so add/remove axes (aka the evdev-joystick commands) as needed for your controller.
SUBSYSTEM=="input", KERNEL=="event*", ACTION=="add", ATTRS{name}=="[EXACT CONTROLLER NAME]", RUN+="/bin/bash -c \"evdev-joystick --e %E{DEVNAME} --a [1st AXIS #] --minimum 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a [2nd AXIS #] --minimum 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a [3rd AXIS #] --minimum 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a [4th AXIS #] --minimum 0 --maximum 0 ; at -M now <<< 'timeout 30s evtest %E{DEVNAME} | grep -m 1 '\''time .*'\'' ; evdev-joystick --e %E{DEVNAME} --a [1st AXIS #] --minimum [1st AXIS MIN] --maximum [1st AXIS MAX]; evdev-joystick --e %E{DEVNAME} --a [2nd AXIS #] --minimum [2nd AXIS MIN] --maximum [2nd AXIS MAX] ; evdev-joystick --e %E{DEVNAME} --a [3rd AXIS #] --minimum [3rd AXIS MIN] --maximum [3rd AXIS MAX] ; evdev-joystick --e %E{DEVNAME} --a [4th AXIS #] --minimum [4th AXIS MIN] --maximum [4th AXIS MAX]'\""
- If you haven't already, follow the previous step for your remaining controllers as new code lines. Then Ctrl-X to exit, Y to save, Enter to confirm. Here is my finished udev rule file for comparison (I didn't need to override the minimums since mine were already 0, so you'll notice them missing from my evdev-joystick commands):
SUBSYSTEM=="input", KERNEL=="event*", ACTION=="add", ATTRS{name}=="Logitech Logitech Cordless RumblePad 2", RUN+="/bin/bash -c \"evdev-joystick --e %E{DEVNAME} --a 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 0 ; at -M now <<< 'timeout 30s evtest %E{DEVNAME} | grep -m 1 '\''time .*'\'' ; evdev-joystick --e %E{DEVNAME} --a 0 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 255'\"" SUBSYSTEM=="input", KERNEL=="event*", ACTION=="add", ATTRS{name}=="8Bitdo SF30 Pro", RUN+="/bin/bash -c \"evdev-joystick --e %E{DEVNAME} --a 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 0 ; at -M now <<< 'timeout 30s evtest %E{DEVNAME} | grep -m 1 '\''time .*'\'' ; evdev-joystick --e %E{DEVNAME} --a 0 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 255'\"" SUBSYSTEM=="input", KERNEL=="event*", ACTION=="add", ATTRS{name}=="8Bitdo SN30 Pro", RUN+="/bin/bash -c \"evdev-joystick --e %E{DEVNAME} --a 0 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 0 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 0 ; at -M now <<< 'timeout 30s evtest %E{DEVNAME} | grep -m 1 '\''time .*'\'' ; evdev-joystick --e %E{DEVNAME} --a 0 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 1 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 2 --maximum 255 ; evdev-joystick --e %E{DEVNAME} --a 5 --maximum 255'\""
- Reload the udev interface to take on the new rule file.
sudo udevadm control --reload
- Reconnect your controllers.. or reboot to force reconnection.
sudo reboot
This workaround was inspired by my previous tests, where I noticed the "Northwest" issue (responsible for the selection jumps) not affecting controllers whose analog axes are using 0 as a midpoint.
So upon first connection of a controller, the new udev rule will override the min/max of any offending axis to 0/0.. thereby forcing 0 as the axis's midpoint. Then, an asynchronous at job is created to await for any button-press on the controller. Once that happens (or the timeout expires), the original min/max value of the controller's axes will immediately restore.. but not after your button-press took action AND without any selection jump! :-D
Important notes:
-
The workaround is meant to avoid the selection jump on first input of a connected controller IN EMULATION STATION. If you manage to (re)connect it during gameplay, the running emulator may halt or render control unresponsive until it's restarted.
-
I set the timeout for button-press monitoring to 30s.. partly because you may need a moment to press something after connection.. partly because it's a way to avoid accumulating jobs in the at queue by not waiting indefinitely. If the selection jumps are still happening, press something sooner! ...or you can increase the timeout in the udev rule. But I wouldn't make it higher than 60s.
Otherwise, enjoy your better RetroPie experience everyone!
-
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.