[SOLVED] Selection jumps after the first input of a controller
-
@louiehummv this problem has been around for a bit
it will be cool if there is a fix for this, but as of yet i have not seen it.i have FC30, SN30 and N30pro 2. and they all do it.
i think it has to do with what mode it is in.
i think i have mine in android mode. but i dont have them in front of me so i take a looki think if you have it in switch mode it does not do that
-
@exarkuniv I'm slowly getting to the bottom of this problem..
but I can attest to it being a non-issue on my RasPi 2B & 3B (which ran the latest supported RetroPie images). Only until last month when I bought a RasPi 4B & installed the latest supported image, this problem surfaced.As for my findings.. Looks like there's an issue with how the controllers are calibrated & initially read in Linux. I did some homework to see Linux offers 2 different input systems, js & evdev, where the latter is newer & utilized in RetroArch. Not sure which is utilized in Emulation Station, but there is strange behavior going on in both systems with the analog sticks.
Regarding the js system.. After running jstest, I confirmed the range of -32768 to 32767 on each axis of each analog stick.. quite normal. Yet when I run jscal on each of the gamepads, only a range of 0 to 255 is detected.. that's interesting. So I followed thru with jscal-store to maintain the "true" ranges, & I confirmed using nano that the /var/lib/joystick/joystick.state file was generated with content. Yet after rebooting the Pi & running jstest again, the range of -32768 to 32767 is still detected on each axis of my gamepads.
Regarding the evdev system.. After running evdev-joystick --s, I see min & max values of 0 &255 on each axis of each analog stick.. that's weird. This happens whether the joystick.state file from my js testing exists or not, btw. What's also weird is the value on each axis is set to 0.. kinda hints at the whole North-West anomaly. Once I press any button or move any stick on the gamepad (causing the ES selection to "jump") & then run evdev-joystick --s again, the value on each axis suddenly reads 127.. wtf. I thought using evdev-joystick --e to change the min & max to -32768 & 32767 (right after connecting my gamepad but before I pressed anything) would help, but still the ES selection "jumps" with the axis values changing abruptly to 127.
So at this point, I'm stuck. Neither input system is behaving as expected.. whether it's my USB or Bluetooth controllers. The North-West issue seems to be responsible for initializing axis values to 0,
but I'm surprised it hasn't been a problem on my other RasPi's until now.Hopefully someone can point out what I've been overlooking. -
@louiehummv it is funny that you just now have gotten the probem. i have the same issue with my pi3b and i have 4.5.1 on it.
every time i start my system and connected my controller it jumps. has, for me at least done that since day one for 4.5. for me at least.im going to be connecting my FC30 to my pi4 today, and im going to try the different modes to see what i find on my end
-
@exarkuniv Much appreciated. Meanwhile, I'm going to hook up my old RasPi 3B and run the same tests I did on my 4B.. maybe I'll notice the differences.
-
@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.