libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.79k stars 1.82k forks source link

DirectInput joystick incorrect initial axis positions #3816

Closed SDLBugzilla closed 2 years ago

SDLBugzilla commented 3 years ago

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: 2.0.13 Reported for operating system, platform: Windows 10, x86

Comments on the original bug report:

On 2020-09-03 20:19:51 +0000, Jean-Pierre Gygax wrote:

Created attachment 4457 DInput Poll() call immediately after opening a joystick

When first querying DirectInput joystick axis positions, they are reported as 0, even when their physical position is different.

After some research, it appears Windows requires some time between the call to IDirectInputDevice8_Poll() and the collecting of the resulting data via IDirectInputDevice8_GetDeviceData().

The attached patch is a crude but apparently functional solution to this problem.

zaphod77 commented 2 years ago

Why was the bug label removed?

You still need to poll once on windows to ensure that you can get an initial axis state. If the controller has never been polled, and the buffer is empty, the initial axis state is unknown. so you need to do one initial poll to kick everything off.

Since as far as I know, we can't tell SDL to perform the directinput poll, we need the joystick initializer to do it.

The DirectInput instructions for MS are very clear on the subject. We can't count on the info being there if the device hasn't been polled.

icculus commented 2 years ago

Why was the bug label removed?

The script that imported our old Bugzilla added this label to thousands of issues, but it’s just noise (everything is a bug), so we remove it when we pay attention to one of these issues.

zaphod77 commented 2 years ago

Except that as i just explained, it IS a real bug that you can't fetch the initial axis. and the patc of adding a dinput poll request and sleeping 50 MS does resolve it.

On Sat, May 21, 2022 at 9:50 AM Ryan C. Gordon @.***> wrote:

Why was the bug label removed?

The script that imported our old Bugzilla added this label to thousands of issues, but it’s just noise (everything is a bug), so we remove it when we pay attention to one of these issues.

— Reply to this email directly, view it on GitHub https://github.com/libsdl-org/SDL/issues/3816#issuecomment-1133646607, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQL7ZIDBHAD73WE7WNVRFDVLDZX7ANCNFSM4XOA7S7Q . You are receiving this because you commented.Message ID: @.***>

slouken commented 2 years ago

Yep, this is still a bug, thanks for the ping. I'll look at it for the next release.

icculus commented 2 years ago

Except that as i just explained, it IS a real bug

Yes, you're absolutely right, we just don't actually use the "BUG" label on GitHub for categorizing things here, so we remove the label and still treat the report as a legitimate bug. Sorry if I wasn't clear about that.

Socke81 commented 1 year ago

I have the same problem and landed here via google. My Logitech momo steering wheel reports the value 0 for all axes. Read out behind the SDL_JOYDEVICEADDED event. But this is wrong. After I have pressed a button or moved an axis, the same function reports the values 32767 for the gas and brake pedals when they are not moved.

Windows 10, SDL 2.28.1

Settings:

#if PLATFORM_WINDOWS
    SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "0");
    SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "1");
    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
    SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
    SDL_SetHint(SDL_HINT_JOYSTICK_ROG_CHAKRAM, "1");
#endif
    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
    SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
    SDL_SetHint(SDL_HINT_LINUX_JOYSTICK_DEADZONES, "1");

#if PLATFORM_WINDOWS | PLATFORM_MAC
    SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC);
#endif

    SDL_JoystickEventState(SDL_ENABLE);
    SDL_GameControllerEventState(SDL_ENABLE);
slouken commented 1 year ago

Some controllers don't send any input reports until the first motion on the controller, so we don't have any idea what the initial state is and can't report anything besides zero.

zaphod77 commented 1 year ago

If the controller won't wake up even when polled, then it's not gonna ever be possible to autocalibrate it, and it probably won't wok under linux either. Does that controller autocalibrate fine on linux?

Socke81 commented 1 year ago

Logitech does not offer a Linux driver. That is why I have not tried linux. As a workaround, I have implemented a loop that reads the axis values the first time a button is pressed. This works. I have also implemented this on the first move of an axis but when the axis that is moved is read out the values are of course falsified. Can you not implement this in SDL? That at the first joystick action then all default values of the axes are read? If this is done at the very beginning, the axis value is perhaps not as distorted as when I do this.

The reason for the whole thing is that some axes return 0 when not moved and others return a positive or negative value. According to my tests the maximum value instead of 0. You must be able to recognize this somehow.

slouken commented 1 year ago

I just tested with the Logitech G920 wheel, which has the same behavior you're describing. I loaded up testcontroller, and the axes are at zero. I pressed the accelerator and the accelerator, brake and clutch all snapped to the maximum value (and decrease when pressed)

So, at least with the G920, SDL works the way you are requesting.

zaphod77 commented 1 year ago

so this is under linux too, or just windows? The G920 should work under linux.

slouken commented 1 year ago

@Socke81 and I are both talking about Windows.

zaphod77 commented 1 year ago

need to work out if this is the usual "windows only directinput" problem which is fixed by poll and sleep, or if it's truly a new problem, and if it' only under windows.

Socke81 commented 1 year ago

Have you forgotten me? ;)

icculus commented 1 year ago

When last this was discussed, SDL was behaving the way you wanted it to...is there something more it should be doing, or did we misunderstand?

Socke81 commented 1 year ago

Nothing has changed in version 2.28.2. When I release throttle and brake pedal I get the value 32767. Correct would be 0. For better understanding compare the values of SDL_CONTROLLERAXISMOTION with SDL_JOYAXISMOTION with an Xbox gamepad at the analog triggers.

SDL_JOYAXISMOTION = wrong values SDL_CONTROLLERAXISMOTION = correct values

What I need is a 0 when an axis is not used by a human.

icculus commented 1 year ago

When I release throttle and brake pedal I get the value 32767

But that's what the joystick is reporting to us. It doesn't report anything until touched, which is why it starts at zero, and we can't do anything about that.

SDL_JOYAXISMOTION = wrong values SDL_CONTROLLERAXISMOTION = correct values

I assume this is because the game controller subsystem knows what the Xbox controller defaults to when idle, but that information is not available to the joystick API (the game controller API is built on top of the joystick API and adds information about specific controllers, including that Xbox controller's triggers don't idle at zero).

If you can use the Logitech wheel as a game controller that only has one axis (left and right on the wheel?), then you can make this work with SDL2 by setting up a controller mapping for it. But with the lower-level joystick API, we're all at the mercy of what information the hardware and platform provide us, which isn't much.

(If I'm still misunderstanding the problem, though, please let me know!)

Socke81 commented 1 year ago

But I have a workaround described above. Couldn't this be implemented optionally in SDL? So with a SET HINT THIS WORKAROUND = 1 or so.

You will also probably have the opportunity to test many different steering wheels. Is that generally so that the values for pedals are not 0? Then I can solve this myself easily or you add a separate move event for pedals as with the controller.

zaphod77 commented 1 year ago

the main issue is that many controllers report zero for anything until something changes.

Specifically they don't report anything at all, and so sdl assumes it's zero.

For many of them, but apparently not all, if you actually poll the state of the controller using the normal directinput callback to do so, and then wait a bit for it to wake up, it will start sending data with the usual buffer method.

The change should have fixed this for directinput controllers that autocalibrate fine on linux and not windows. Hence me asking if the aforementioned controller still worked fine on linux without the bug.

On Sat, Sep 2, 2023 at 1:51 AM Socke81 @.***> wrote:

But I have a workaround described above. Couldn't this be implemented optionally in SDL? But I have a workaround described above. Couldn't this be implemented optionally in SDL? So with a SET HINT THIS WORKAROUND = 1 or so.

— Reply to this email directly, view it on GitHub https://github.com/libsdl-org/SDL/issues/3816#issuecomment-1703768139, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQL7ZJ2I2WK3GRYKHRAOR3XYLXLLANCNFSM4XOA7S7Q . You are receiving this because you commented.Message ID: @.***>