libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.1k stars 1.81k forks source link

(Input) Proper analog trigger support #6920

Open Shoegzer opened 6 years ago

Shoegzer commented 6 years ago

From this issue, RA doesn't appear to support analog triggers properly, at least in linux. Hopefully with this fixed, cores such as reicast and other future cores making use of such inputs will function as they should.

Updated with details: In linux, attempting to set L2 and R2 within the RA GUI results in inproper digital values (axes 6 and 7 in my case) rather than proper analog values (axes +2 and +5 in my case). Manually editing retroarch.cfg to add the proper values will work, however this is counter-intuitive and not everyone would know to do that. All other details are in the upper part of this thread.

@hiddenasbestos realizing you're probably the best person on the team for this, if you could find some time to look into adding such support, I can help you test whatever you'd need. I currently have a test Intel Kaby Lake-based system with kernel 4.15 and ds4 pads, and can compile RA as needed. Thanks very much.

hiddenasbestos commented 6 years ago

I'm not sure I'm the best person to fix this but perhaps we can pool knowledge. The relevant lines of code are:

input/drivers/* -> function xxx_input_state, e.g. udev_input_state

input/input_driver.c -> function input_joypad_analog

To debug this on the faulty platform (I can't), put a printf to log the value of res in input_joypad_analog res = abs( drv->axis( joypad_info.joy_idx, axis ) );

The value should always be from 0 to 0x7FFF (+32767), just like the analogue sticks. If the driver is returning weird values, we're past the point of being able to do something about it at this stage - it's a driver bug to report out of range or compressed values.

ps. XInput triggers work great for me, FWIW

Shoegzer commented 6 years ago

Thanks so much. I added the printf at the very bottom of the input_joypad_analog function (right above "return res;"). I observed that the values thrown to terminal were constant at "0" unless I pushed either the left or right trigger, in which case the corresponding value immediately jumped to "32767". So they are registering, and within the expected range, just not treated as analog for some reason. Note that the values returned for the left and right joysticks (not triggers) are reported properly as analog, as they slowly change values up to 32767 as the joystick is pushed left or right slowly.

BTW, I think a good ingame test is in Daytona USA's "Analog Calibration" section - if you slowly push "Gas" (default right trigger) I'm pretty sure it should show the needle slowly moving from left to right. In my case, it goes immediately from far-left to far-right, as consistent with the printf test above. Try it yourself when you have a chance and let me know what you get in Xinput.

Also, in case it matters: Dolphin emulator's input settings applet lets you see analog trigger values as the triggers are pressed. In that applet, I can see the range slowly increasing when I slowly press the triggers, as it should.

hiddenasbestos commented 6 years ago

Ok, sounds like the common input code isn't getting any analog data back for the trigger and is falling back to digital input, as designed (in case you mapped a face button to an expected analog input)

Might wanna verify that by moving your printf to right after res = abs( drv->axis( joypad_info.joy_idx, axis ) ); because we need to know it's the call to drv->axis that's making the res = 0 happen.

Based on what you've told me, I'm wondering about what's happening deeper in the udev code. In the file input/drivers_joypad/udev_joypad.c in function udev_joypad_axis. I'd be very curious what's going on in there:

Also if that proves to be a bust - my next port of call would be udev_joypad_poll in the same file.

Past that I'm out of ideas...

DISCLAIMER: I've never looked at this udev code in my life before now, if someone else wrote this and knows more about it feel free to chip in, I'm just commenting using my general debugging experience.

Shoegzer commented 6 years ago

Okay, I moved the code, so now I have:

res = abs( drv->axis( joypad_info.joy_idx, axis ) ); printf ("Res: %d\n", res);

Now when I launch a game, all inputs report "0" whether buttons/triggers are pressed or not. Hopefully that helps.

Incidentally, since you mentioned udev code - not sure if it matters but I also changed the "Joypad Driver" in the RA UI from "udev" to "sdl2" and restarted, but I still get the same digital trigger behavior.

You ask some good questions, for example it would certainly be great to know whether the udev_joypad_axis function gets called at all for triggers. I'm happy to try out any other changes to the code you may suggest to get some answers together for us - e.g. I could printf some more test indicator values in certain spots to see if specific functions are being called when input occurs etc. Otherwise maybe @twinaphex knows or can find the person/people who wrote the original input code to provide more direct responses.

hiddenasbestos commented 6 years ago

If all inputs report 0, that means reicast's requests for triggers are calling the driver code and getting no analogue data. This fits what what you're describing but I can't explain why the driver is acting like that.

btw. you should be able to debug all my questions with printfs in the UDEV code. But if SDL2 isn't working that's sounding like maybe a config error? Have you tried binding a thumbstick axis to RetroPad's L2 / R2 and seeing what happens?

I'm going to take a step back at this point.

Shoegzer commented 6 years ago

Regarding debugging, I wouldn't know where in the udev code to put the printfs but if you give me an idea of where you'd like them, I'll certainly do that and provide results.

As you suggested I set the right thumbstick X axis to RetroPad's L2 / R2 - now the code with the printf in the new location returns values from 0 to 32767 properly, and Daytona's analog calibration tool works fine with the thumbstick. Otherwise I think my configuration is not a factor but maybe @mickski56 could comment here as well, as he encountered the same issue.

hiddenasbestos commented 6 years ago

printf's in the udev code: go crazy and pepper them all over!

Sounds like your controller's triggers aren't being read by the analog code. Definitely sounds like a bug in udev / config / linux.

Shoegzer commented 6 years ago

Hmm.. well it doesn't appear to be a bug in udev / linux, triggers are known to be working fine for many other games/emulators such as Dolphin (as I mentioned) that use analog triggers.

Update:

I have a linux graphical input tool called "jstest" which shows all axes and how they respond to input. This tool shows that the D-Pad is mapped to axes 6 and 7; whereas the L2 / R2 triggers are mapped to axes 2 and 5 respectively. With this tool, the analog triggers behave as they should, with values that slowly move as you slowly press them.

Out of curiosity I ran Dolphin and RA controller setups side-by-side, and I noticed that with Dolphin, it sets the D-Pad to axes 6 and 7, and sets the L2 / R2 analog triggers to axes 2 and 5, respectively - this matches my jstest tool, and as mentioned before, triggers behave as they should here too. However, RA sets the D-Pad to "Hat #0 up/down/left/right" and analog triggers to axes 6 and 7 (i.e. the D-Pad axes according to both jstest and Dolphin). So it appears that for some reason, RA wants to treat the triggers as if they're digital D-Pad axes.

Shoegzer commented 6 years ago

2nd Update:

I fixed it! Well, at least in the config. As I stated above, it appears that the RA UI doesn't set the analog triggers properly. However, you can manually edit the retroarch.cfg file to set them properly, as follows:

1) Determine what axes are being reported by the OS for L2 and R2 (in my case they are axes 2 and 5 respectively).

2) Manually edit the $home/.config/retroarch.cfg file. Using my example axes above, you'd change the following lines to:

input_player1_l2_axis = "+2"
input_player1_r2_axis = "+5"

3) Save and restart RA. Analog triggers should now work properly. @mickski56 when you have a chance, please confirm this works for you too.

Of course, a proper fix will involve fixing whatever code sets these values in the RA UI, so the above hack won't be necessary. The RA UI code to set other analog values seems to be fine, so I'm hoping this isn't too tricky to track down, but again I'm happy to help wherever I can.

hiddenasbestos commented 6 years ago

Hey @twinaphex , over to you :)

mickski56 commented 6 years ago

@Shoegzer annoyingly I'm still getting 50% dead zones on my triggers. My axes are mapped the same as yours. Printf's in input_driver.c print out values in the range 0 to 32676 but only for 50% to 100% trigger. Further investigation is required on my part. As an aside be careful with jstest it uses the old linux joystick (/dev/input/js) interface whereas udev/evdev uses the newer event (/dev/input/event) interface. jstest will report axis and button numbers correctly tho.

The "proper fix" is probably updates in retroarch-joypad-autoconfig, not having any overridden bindings in retroarch.cfg and using per core/game overides if you need to swap buttons around. Some of the latest autoconfigs have triggers enabled some don't. Tho if you have both triggers and buttons both enabled for the same trigger in the *controller.cfg you get buttons.

Shoegzer commented 6 years ago

@mickski56 are you sure the dead zone is an RA issue? How do you know it's exactly 50% or are you estimating? I've also found that in both Dolphin (input menu) and RA (reicast/Daytona calibration menu), when I press the trigger slowly, it doesn't actually register until about 10-15% of the way pressed (and changing the analog dead zone setting in RA's input menu doesn't seem to have any effect). Perhaps this is just the design of the hardware in both of our cases?

In any event you are quite right about jstest, I just don't know of an equivalent udev/evdev tool unless you do?

By the way, should I assume that you could set your analog triggers in RA's menu without my manual fix above? I still think there's an issue with the code somewhere in RA, as I can set the other analog sticks just fine, and I haven't overridden anything to my knowledge.

mickski56 commented 6 years ago

@Shoegzer pretty sure it's an RA issue. But first your second point about udev/evdev test tools, use evtest /dev/input/event to see output like jstest (also works with event mice and keyboards), use evdev-joystick from linux console tools to calibrate, set deadzones and signal noise reduction on event(udev) joypads. Tho you will have to write a udev rule if you want your settings to stick. "evdev-joystick -e /dev/input/event -f 1" is great to stop axes jittering so you can see the output of evtest.

Back to RA, using evtest I can tell where my triggers start to work it's around 5-10 % & I can also see where 50% is. Stand alone reicast also works how I would expect i.e. 5% to 100% on the triggers. I cheated a bit by editing my controllers autoconfig file, as i said some autoconfig files have triggers enabled some don't.

I'm going to try Dolphin (input menu) just for a double check. Tried Dolphin stand alone it initially picks the trigger up as button then with the trigger pressed a bit it picks it up as an axis. Displaying "Axis 2-+" for the left trigger. Displaying full range analog trigger movement.

btw if i change input_player1_l2_axis = "+2" to input_player1_l2_axis = "-2" i get the trigger working ~10% - 100% (full range) but it's inverted, i.e.0% is interpreted as full press. No it doesen't with some printf's in input_driver.c and sdl_joypad.c I can see this is not the case, it's just the way my triggers work making it less noticable when 50% - 100% is ignored. don't try this it stops the front end from working (don't plug the joystick in until you're in the game calibration page)

If you have the command line tool jstest, can you run "jstest /dev/input/js0" and tell me what the minimum value for the trigger axis is (trigger at 0%) please.

mickski56 commented 6 years ago

With the above mentioned printf's I can summarize the problem as follows. The low level driver in this case sdl_joystick.c reports trigger movement as -32767 -- 0 -- 32767 (which is what you want from a stick, but not a trigger). input_driver.c gets an axis bind by various means but they are always specified as half an axis (0 -- 32767 or 0 -- -32767) so 50% of the trigger movement is not bound and never used.

Can anyone confirm that trigger axes report this way for them on linux dualshock3 or xbox360. kernel 4.14.52 also what does a dualshock4 report ?

hiddenasbestos commented 6 years ago

The low level driver in this case sdl_joystick.c reports trigger movement as -32767 -- 0 -- 32767

Does this mean:

hands off -> 0 left trigger full, right trigger released -> -32767 right trigger full, left trigger released -> +32767 both triggers pulled -> 0

360 pad works like this on Windows in DirectInput mode and it's unhelpful! Which is why you need XInput to use triggers properly (as Xinput reports 0->255 for both triggers independently)

andres-asm commented 6 years ago

Ah that Yeah on windows/dinput L2+R2 are a single axis (axis 2) L2 being -2 and R2 +2

What happens if you press both triggers partially, I would assume the value is added?

This behavior is up to the underlying driver (OS level driver) and I don't think there is much that can be done in the retroarch side.

andres-asm commented 6 years ago

I assume both your triggers are axis 2? I guess you have a different underlying driver than @Shoegzer

mickski56 commented 6 years ago

L2 is axis 2, hands off is -32767 full pull is 32767 half pull is 0 R2 is axis 5 hands off is -32767 full pull is 32767 half pull is 0 L2 is fully independent of R2 The only test program on linux that I can find that returns 0 > 255 is evtest Maybe linux is not ready for triggers yet

andres-asm commented 6 years ago

Oh, that sounds fixable

On Thu, Jun 28, 2018, 7:17 PM mickski56 notifications@github.com wrote:

L2 is axis 2, hands off is -32767 full pull is 32767 R2 is axis 5hands off is -32767 full pull is 32767 The only test program on linux that I can find that returns 0 > 255 is evtest Maybe linux is not ready for triggers yet

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/libretro/RetroArch/issues/6920#issuecomment-401210587, or mute the thread https://github.com/notifications/unsubscribe-auth/ABpC0BV1x4zWtWiQiV0ye-4LB1N__ju9ks5uBXIUgaJpZM4U2hAp .

hiddenasbestos commented 6 years ago

@mickski56 well that's strange but totally explains what's happening with your 50% deadzone.

I wonder if it's possible to query the min/max value for an axis. The sdl_joystick code needs to shape triggers to be between 0 and 32767 with an offset and a scale.

Definitely outside of my wheelhouse to fix this, sorry

mickski56 commented 6 years ago

I had another look at sdl_joystick.c and came up with this. Thanks @hiddenasbestos

--- RetroArch-git/input/drivers_joypad/sdl_joypad.c.orig    2018-06-27 22:17:33.032243547 +0100
+++ RetroArch-git/input/drivers_joypad/sdl_joypad.c 2018-06-29 19:21:03.570781096 +0100
@@ -362,6 +362,10 @@
    if (AXIS_NEG_GET(joyaxis) < pad->num_axes)
    {
       val = sdl_pad_get_axis(pad, AXIS_NEG_GET(joyaxis));
+      if (strcmp(SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)AXIS_NEG_GET(joyaxis)), "rightx") == 0)
+         val = (val + 0x7fff) / 2;
+      if (strcmp(SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)AXIS_NEG_GET(joyaxis)), "righttrigger") == 0)
+         val = (val + 0x7fff) / 2;
       if (val > 0)
          val = 0;
       else if (val < -0x7fff) /* -0x8000 can cause trouble if we later abs() it. */
@@ -370,6 +374,10 @@
    else if (AXIS_POS_GET(joyaxis) < pad->num_axes)
    {
       val = sdl_pad_get_axis(pad, AXIS_POS_GET(joyaxis));
+      if (strcmp(SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)AXIS_POS_GET(joyaxis)), "rightx") == 0)
+         val = (val + 0x7fff) / 2;
+      if (strcmp(SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)AXIS_POS_GET(joyaxis)), "righttrigger") == 0)
+         val = (val + 0x7fff) / 2;
       if (val < 0)
          val = 0;
    }

My programming skills are sadly lacking. It hard codes the axis numbers which means it works as expected on a dualshock 3 but not on an xbox360 pad. Maybe check if any axes are reporting -0x7fff during initialisation.

andres-asm commented 6 years ago

Why are you using the SDL joypad driver though? It's one of the least mature and well developed drivers.

mickski56 commented 6 years ago

SDL joypad because the rumble cuts off nicely in metropolis street racer reicast core, with udev once it starts it doesn't stop. I've just looked at udev_joypad.c I could modify that just as well the axis read code is very similar.

andres-asm commented 6 years ago

​​Actually the libretro convention for axes is -32768 to 32766. If xinput uses 0-255 for the triggers, xinput is the anomaly.

The analog button system should try to follow that, and the xinput driver too I guess. I'll try to do some testing with dinput / xinput on the weekend, just got home.

hiddenasbestos commented 6 years ago

XInput gets 0,255 from the API but scales up to 0,32767 before passing the data on.

The convention for analog buttons is 0 means fully released and +32767 means fully pulled (or "pressed", keeping in mind analog face buttons for some future PS2 core)

Shoegzer commented 6 years ago

Great to see some new developments and thoughts shared on this since I've been out. @mickski56 I've confirmed that my controller (ds4) goes from -32767 (released) to +32757 (fully pressed), hence matching your observation. Sounds like this is pretty well established by now though.

Thanks also for your tip regarding jstest/evdev. That motivated me to research the differences further and I found this interesting Reddit post from a Linux gamedev a year or so ago regarding joydev and evdev. I'm not sure how much of it is still relevant though I suspect at least most.

I too have encountered the rumbling problems you mentioned (though rumble should eventually stop once rumble events are called again) but it never occurred to me that it could be specific to the evdev driver as I've always just used that driver for its other benefits. Do you feel this deserves a separate issue report to fix?

I'm happy to test any new code to fix the immediate issue though - and yes, @hiddenasbestos it could affect a future ps2 core, as it already affects both reicast and dolphin cores since they both use analog triggers. It would likely affect the upcoming supermodel core too since I imagine most users will want to map analog triggers to gas/brake in Daytona 2, Scud Race etc.

mickski56 commented 6 years ago

@Shoegzer you could try this patch to udev_joystick.c .If you can't wait for full range trigger action.

--- RetroArch-git/input/drivers_joypad/udev_joypad.c.orig   2018-06-29 22:07:42.717870411 +0100
+++ RetroArch-git/input/drivers_joypad/udev_joypad.c    2018-06-30 19:27:21.660027053 +0100
@@ -662,12 +662,16 @@
    if (AXIS_NEG_GET(joyaxis) < NUM_AXES)
    {
       val = pad->axes[AXIS_NEG_GET(joyaxis)];
+      if ((AXIS_NEG_GET(joyaxis) == ABS_Z) || (AXIS_NEG_GET(joyaxis) == ABS_RZ))
+         val = (val + 0x7fff) / 2;
       if (val > 0)
          val = 0;
    }
    else if (AXIS_POS_GET(joyaxis) < NUM_AXES)
    {
       val = pad->axes[AXIS_POS_GET(joyaxis)];
+      if ((AXIS_POS_GET(joyaxis) == ABS_Z) || (AXIS_POS_GET(joyaxis) == ABS_RZ))
+         val = (val + 0x7fff) / 2;
       if (val < 0)
          val = 0;
    } 

I'd be quite interested to see if this works on a dualshock 4, as ABS_Z & ABS_RZ are just numeric constants defined in <linux/input.h>. Although I have a xbox360 pad that also defines triggers as axes 4 & 5, So I can test it myself.

Still needs some method of detecting how the axis behaves tho. It will do weird things to any trigger that is 0 -> 32676 or -32676 -> 0. The Linux Gamepad Specification link say triggers should report 0 -> 32676 but legacy devices can report anything they like.

As for the rumble I'm not sure if it's in retroarch or reicast. I think I saw an open issue on reicast about needing to implement some functions to make rumble quit. reicast-emulator/issues/47

Shoegzer commented 6 years ago

@mickski56 thanks. I see what you did in the code, and it seems like it should work; however it didn't. I tried setting the axes in the UI and I still get axes 6 and 7 instead of +2 and +5.

Also thanks for pointing out that issue report about rumble in reicast, I missed that one.

hiddenasbestos commented 6 years ago

Solving the problem with a hard coded scale and offset is just kicking the can down the road for the next bug report to come in one day saying "I get weirdness on my triggers with DualShock5" because it's using some other range that this code doesn't correct properly.

Is there a way to ask the low-level driver what the min/max range of each axis is? DirectInput can query the driver - surely Linux can too?

... or maybe Linux is a fixed spec like XInput and this is fine. I'm not an expert, just magic numbers making me feel like there's a potential problem waiting for future generations.

mickski56 commented 6 years ago

I think it's fixed sort of. The Linux Gamepad Specification says "ABS trigger values start at 0, pressure is reported as positive values" "Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL) " Neither the dualshock3 (hid_sony driver) or xbox360 (xpad driver) do this. So clearly there's going to be a choice of at least 2 different ranges depending whether the driver treats the trigger as an axis or a trigger( although the axis names may signify which scheme is in use) . Also udev seems to report the correct axis name ie ABS_Z & ABS_RZ for triggers regardles of the axis index. So this looks doable, i think. Further research to be sure of various things is required.

mickski56 commented 6 years ago

@Shoegzer do you still have input_player1_l2_axis = "+2" input_player1_r2_axis = "+5" input_player1_l2_axis_label = "LT" input_player1_r2_axis_label = "RT" in your retroarch.cfg. my diff doesn't alter the fact you need them. It just makes the triggers work over their full physical range.

Shoegzer commented 6 years ago

@mickski56 ah, yes of course - and I tested your code in Daytona USA's analog calibration menu, comparing old vs. new builds, and trigger presses do seem to register much earlier now / full physical range. You could create a separate PR with your code to merge into master?

Regardless, in the meantime I'll keep this open until we have a fix for RA's inability to set the triggers from within the UI.

hiddenasbestos commented 6 years ago

btw. one issue with @mickski56 's patch is that ABS_Z and ABS_RZ might not always be triggers - what if you connect a Joystick to the computer to play a flight-sim in DOSBox? - the Z or RZ axes might be a rudder or throttle, where the full axis range makes perfect sense. I wonder if the patch prevents that from working?

mickski56 commented 6 years ago

The linux device drivers that use the event interface seem to be quite well written and provide meaningful names for their axes. from input-event-codes.h

define ABS_X 0x00

define ABS_Y 0x01

define ABS_Z 0x02

define ABS_RX 0x03

define ABS_RY 0x04

define ABS_RZ 0x05

define ABS_THROTTLE 0x06

define ABS_RUDDER 0x07

define ABS_WHEEL 0x08

define ABS_GAS 0x09

define ABS_BRAKE 0x0a

define ABS_HAT0X 0x10

define ABS_HAT0Y 0x11

define ABS_HAT1X 0x12

define ABS_HAT1Y 0x13

define ABS_HAT2X 0x14

define ABS_HAT2Y 0x15

define ABS_HAT3X 0x16

define ABS_HAT3Y 0x17

define ABS_PRESSURE 0x18

define ABS_DISTANCE 0x19

define ABS_TILT_X 0x1a

define ABS_TILT_Y 0x1b

define ABS_TOOL_WIDTH 0x1c

define ABS_VOLUME 0x20

define ABS_MISC 0x28

The numbers not necessarily being directly related to axis numbers. The event interface driver should know the hardware and report the correct axis name. There will have to be some testing with different hardware. I think hard coded scale and offset is fine as all joypads should report the same range unless they are broken in some way, and I'm hoping ABS_Z and ABS_RZ are always triggers. Unless they are reported as ABS_HAT* in which case they should do the right thing as they are linux gamepad specification complient.

I'm away til next weekend now. I will try to do some reading but the internet is well flaky where I'm going.

Shoegzer commented 6 years ago

@mickski56 just following up. Your code to fix the analog trigger range seems pretty solid to me and works well - any chance you could merge it?

mickski56 commented 6 years ago

@Shoegzer I'm taking @hiddenasbestos comments about long term viability on board. It's taking me some time to get my head around the udev code not to mention trying to account for different joysticks on linux. I haven't had much time to sit down with it recently I'm afraid.

Shoegzer commented 6 years ago

@mickski56 ah, fair enough. My thoughts only of course: @hiddenasbestos does make a good point and I'm certainly glad there's discussion on future-proofing the code. That said, your comments about axes naming and hard-coded scale/offset values seemed logical to me too, and I agree that ABS_Z and ABS_RZ should always be triggers.

Perhaps if the code is commented appropriately and if an edge-case is ever encountered/reported it can be changed? Just thinking that on balance, it might be best to add it in with a flag for now so today's known input cases can benefit from your improvements, as we're aware.

In any event though, take whatever time you need. There's always time.

hiddenasbestos commented 6 years ago

Possibly the 'right thing' to do is have a separate 'get analog button' function for the input drivers, rather than piggybacking on the 'abs( get axis )' that I've done. This would be quite a big patch but means that both flight sticks and game pads can better co-exist.

(My fault here for assuming that axes would return zero when released.)

mickski56 commented 6 years ago

Are patches accepted or does it have to be a pull request ?

--- input/drivers_joypad/udev_joypad.c.orig 2018-06-29 22:07:42.717870411 +0100
+++ input/drivers_joypad/udev_joypad.c  2018-07-24 21:17:51.039248184 +0100
@@ -80,6 +80,8 @@
    char *path;
    int32_t vid;
    int32_t pid;
+   /* Deal with analog triggers that report -32767 to 32767 */
+   bool neg_trigger[NUM_AXES];
 };

 struct joypad_udev_entry
@@ -217,6 +219,14 @@
          if (abs->maximum > abs->minimum)
          {
             pad->axes[axes]   = udev_compute_axis(abs, abs->value);
+            /* Deal with analog triggers that report -32767 to 32767
+               by testing if the axis initial value is negative, allowing for
+               for some slop (1300 =~ 4%)in an axis centred around 0.
+               The actual work is done in udev_joypad_axis.
+               All bets are off if you're sitting on it. Reinitialise it by unplugging
+               and plugging back in. */
+            if (udev_compute_axis(abs, abs->value) < -1300)
+              pad->neg_trigger[i] = true;
             pad->axes_bind[i] = axes++;
          }
       }
@@ -662,12 +672,20 @@
    if (AXIS_NEG_GET(joyaxis) < NUM_AXES)
    {
       val = pad->axes[AXIS_NEG_GET(joyaxis)];
+      /* Deal with analog triggers that report -32767 to 32767 */
+      if (((AXIS_NEG_GET(joyaxis) == ABS_Z) || (AXIS_NEG_GET(joyaxis) == ABS_RZ))
+            && (pad->neg_trigger[AXIS_NEG_GET(joyaxis)]))
+         val = (val + 0x7fff) / 2;
       if (val > 0)
          val = 0;
    }
    else if (AXIS_POS_GET(joyaxis) < NUM_AXES)
    {
       val = pad->axes[AXIS_POS_GET(joyaxis)];
+      /* Deal with analog triggers that report -32767 to 32767 */
+      if (((AXIS_POS_GET(joyaxis) == ABS_Z) || (AXIS_POS_GET(joyaxis) == ABS_RZ))
+            && (pad->neg_trigger[AXIS_POS_GET(joyaxis)]))
+         val = (val + 0x7fff) / 2;
       if (val < 0)
          val = 0;
    }

This is probably the limit of my c programming skills. A well written linux driver should report triggers as axes Z and RZ. Further test during initialisation to check the axis at rest is a negative value. I would be interested in anyone who has any of the following controlers and is willing to apply my patch. As these controler use different axis numbers to DS3 and Xbox360.

ASUS Gamepad EXEQ_PROACTION Mayflash_GameCube_to_USB_Adapter NVIDIA Corporation NVIDIA Controller v01.04 NVIDIA_Controller_v01_03 iPEGA_PG_9021_BT

mickski56 commented 6 years ago

@hiddenasbestos I know the hid_sony (Dualshock 3/4) driver on linux only reports analog triggers no analog buttons or motion sense unless you want to go to the hid_raw driver.

inactive123 commented 5 years ago

Sorry for looking past this for so long, it should now be merged.

Do modifications have to be made to other existing input drivers other than just udev_joypad.c?

mickski56 commented 5 years ago

sdl_joypad at least I did some work on it I'll dig it out and have a look. It could be slightly more complex if sdl_joypad is available on more os's than just linux. linux raw and hid I don't know but will try to test and get back to you.

inactive123 commented 5 years ago

Cool, thanks.

We would also need to cover Windows as well.

mickski56 commented 5 years ago

I have no windows box available, but I think the windows system drivers behave differently.

Shoegzer commented 5 years ago

@mickski56 Fantastic work, thanks for this fix. I've tested and it works fine here.

I've updated the issue above to document the details behind the main reason it was opened, involving digital mapping of L2 and R2 analog triggers in the GUI. This seems to be the only direct problem remaining.

Regarding the rumble problems @mickski56 reported in this thread, I opened this issue which I believe has something to do with this.

Finally, there is still the problem of Dolphin analog triggers being mapped as digital, as noted in this issue.

orbea commented 5 years ago

This seems to have been fixed and the remaining issues have their own issues so I am going to close this, please correct me if I have misunderstood!

Shoegzer commented 5 years ago

@orbea actually a big reason I opened the issue was due to the fact that the RA UI treats L2 and R2 as digital buttons, not analog axes - so when I try to set them through the UI, they get mapped incorrectly. Currently I have to manually edit retroarch.cfg with the proper values. I updated the issue summary accordingly. Can you please reopen?

MatiasFernandez commented 5 years ago

Not sure if it's useful but I confirm this is still happening in Retroarch 1.7.8 running on Windows 10 and using xinput driver. If you try to map L2/R2 analog triggers of a Dual Shock 4 using Retroarch UI it detects them as buttons instead of axes.

I opened a PR in retroarch-joypad-autoconfig repository to fix default Dual Shock 4 mapping to use axes. But this Retroarch's UI limitation is still an issue for all the other controllers that people may try to setup through the UI

davidhedlund commented 2 months ago

Retroarch's UI limitation is still an issue for all the other controllers that people may try to setup through the UI

Zoltan added an analog button and keyboard tester to the inbuilt Remote RetroPad core (Load Core -> Start Remote RetroPad). So controller mappings can be fully evaluated with it.

davidhedlund commented 2 months ago

Should the title of this issue include "L2/R2"?

Only L2/R2 are configured incorrectly by RetroArch for me, not L3/R3 axes: