What to compare to SDL_Joy*Event::which

When I want to match up an event to a joystick I look at a “which"
value such as event.jbutton.which. I have been comparing this to the
value returned from SDL_JoystickInstanceID(SDL_Joystick * joystick)
because its return type is SDL_JoystickID just like the type of
"which.” However, I have a case with multiple game controllers where
these values don’t match up the way they should. Is there something
other than SDL_JoystickInstanceID() I should be using to compare with
"which"?–
Terry Welsh
www.reallyslick.com

This should be correct. This can go wrong if you pass
SDL_JoystickInstanceID() a closed/disconnected stick (in which case
it’ll give you -1), or a bogus pointer (in which case it can give you
any random value).

If you have a simple reproduction case, though, I’ll take a look at it.

–ryan.On 08/12/2013 12:36 AM, Terry Welsh wrote:

When I want to match up an event to a joystick I look at a “which"
value such as event.jbutton.which. I have been comparing this to the
value returned from SDL_JoystickInstanceID(SDL_Joystick * joystick)
because its return type is SDL_JoystickID just like the type of
"which.” However, I have a case with multiple game controllers where
these values don’t match up the way they should. Is there something
other than SDL_JoystickInstanceID() I should be using to compare with
"which"?

Hi Ryan,
This problem only appears on Windows, not Linux. It’s my lucky day,
though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

There are 2 joysticks attached
Joystick 0: Controller (Xbox 360 Wireless Receiver for Windows)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 1
guid: 5e04a102000000000000504944564944
Joystick 1: XBOX 360 For Windows (Controller)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 0
guid: 5e048e02000000000000504944564944

Then if I run testjoystick with a 0 or 1 on the command line, the
wired controller is the one that is opened each time. The output will
call it joystick 1 in the first case and joystick 0 in the second
case. The wireless controller never has any effect.

If I add a Logitech RumblePad 2 to the scenario, it behaves normally
and the Xbox controllers still have a problem. If I use the Logitech
and just one Xbox controller, everything works as it should. So the
problem seems to be confined to my Xbox controllers.

The problem in my game is slightly different: the two Xbox controllers
will be swapped and control the wrong players. They appear to command
different event “which” values than their instance ids. Of course, the
big difference here is that testjoystick opens only one controller for
testing and my game opens multiple controllers at the same time.

On a side note, my game crashes using SDL_HapticOpenFromJoystick(). It
succeeds for the wireless controller, but crashes the second time it
is called on wired controller. Using SDL_HapticOpen() instead works
fine. I wonder if this is related to the first problem. The crash does
not occur if I add HapticOpenFromJoystick() to testjoystick, perhaps
because only one controller is opened at a time.

  • Terry>

On 08/12/2013 12:36 AM, Terry Welsh wrote:

When I want to match up an event to a joystick I look at a “which"
value such as event.jbutton.which. I have been comparing this to the
value returned from SDL_JoystickInstanceID(SDL_Joystick * joystick)
because its return type is SDL_JoystickID just like the type of
"which.” However, I have a case with multiple game controllers where
these values don’t match up the way they should. Is there something
other than SDL_JoystickInstanceID() I should be using to compare with
"which"?

This should be correct. This can go wrong if you pass
SDL_JoystickInstanceID() a closed/disconnected stick (in which case
it’ll give you -1), or a bogus pointer (in which case it can give you
any random value).

If you have a simple reproduction case, though, I’ll take a look at it.

–ryan.

This problem only appears on Windows, not Linux. It’s my lucky day,
though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

Thank you, this is good information, and definitely sounds like an SDL
bug (in fact, I suspect it’s two separate bugs we’ve already got in the
bugtracker).

I’ll go find some Xbox controllers and reproduce it here.

Thanks!

–ryan.

Thanks Ryan, this will be a good one to fix.On Mon, Aug 12, 2013 at 11:02 AM, Ryan C. Gordon wrote:

This problem only appears on Windows, not Linux. It’s my lucky day,

though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

Thank you, this is good information, and definitely sounds like an SDL bug
(in fact, I suspect it’s two separate bugs we’ve already got in the
bugtracker).

I’ll go find some Xbox controllers and reproduce it here.

Thanks!

–ryan.

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

The problem seems to be the assignments of
JoyStick_DeviceData::XInputUserId. This is the value that XInput calls
take as their dwUserIndex parameter. They are being assigned in
SDL_SYS_JoystickOpen in SDL_dxjoystick.c.

I think XInputUserId should really be assigned in
EnumJoysticksCallback() because that is where
JoyStick_DeviceData::joystickname is assigned a name. If you try to
guess the XInpuUserId later on, behavior is inconsistent. I don’t see
any pattern but it appears that XInput can reorder these values from
one day to the next, maybe depending on the order you plug in devices
and other factors.

I’ve been browsing XInput docs on the web for a while, but I can’t see
any way that the dwUserIndex can be retrieved for a specific device.
You would think this number would be passed to EnumJoysticksCallback()
inside the DIDEVICEINSTANCE structure. Any XInput experts out there?–
Terry Welsh
www.reallyslick.com

On Mon, Aug 12, 2013 at 9:54 AM, Terry Welsh <@Terry_Welsh> wrote:

Hi Ryan,
This problem only appears on Windows, not Linux. It’s my lucky day,
though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

There are 2 joysticks attached
Joystick 0: Controller (Xbox 360 Wireless Receiver for Windows)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 1
guid: 5e04a102000000000000504944564944
Joystick 1: XBOX 360 For Windows (Controller)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 0
guid: 5e048e02000000000000504944564944

Then if I run testjoystick with a 0 or 1 on the command line, the
wired controller is the one that is opened each time. The output will
call it joystick 1 in the first case and joystick 0 in the second
case. The wireless controller never has any effect.

If I add a Logitech RumblePad 2 to the scenario, it behaves normally
and the Xbox controllers still have a problem. If I use the Logitech
and just one Xbox controller, everything works as it should. So the
problem seems to be confined to my Xbox controllers.

The problem in my game is slightly different: the two Xbox controllers
will be swapped and control the wrong players. They appear to command
different event “which” values than their instance ids. Of course, the
big difference here is that testjoystick opens only one controller for
testing and my game opens multiple controllers at the same time.

On a side note, my game crashes using SDL_HapticOpenFromJoystick(). It
succeeds for the wireless controller, but crashes the second time it
is called on wired controller. Using SDL_HapticOpen() instead works
fine. I wonder if this is related to the first problem. The crash does
not occur if I add HapticOpenFromJoystick() to testjoystick, perhaps
because only one controller is opened at a time.

  • Terry

On 08/12/2013 12:36 AM, Terry Welsh wrote:

When I want to match up an event to a joystick I look at a “which"
value such as event.jbutton.which. I have been comparing this to the
value returned from SDL_JoystickInstanceID(SDL_Joystick * joystick)
because its return type is SDL_JoystickID just like the type of
"which.” However, I have a case with multiple game controllers where
these values don’t match up the way they should. Is there something
other than SDL_JoystickInstanceID() I should be using to compare with
"which"?

This should be correct. This can go wrong if you pass
SDL_JoystickInstanceID() a closed/disconnected stick (in which case
it’ll give you -1), or a bogus pointer (in which case it can give you
any random value).

If you have a simple reproduction case, though, I’ll take a look at it.

–ryan.

Hi Ryan,
The attached patch is my best stab at fixing this problem. It also
fixes Bug 1984. The problem I had with crashes on
SDL_HapticOpenFromJoystick() is not fixed. Maybe I’ll look for that
one tomorrow.

Unfortunately, I don’t think DirectInput/XInput has a complete API. I
found no way to match XInpuUserId with a specific device enumerated by
EnumJoysticksCallback(). In my game’s case, I let the user choose and
configure input devices based on their name. You might see a “wired
Xbox controller” and a “wireless Xbox controller” but their
XInpuUserIds could be swapped internally leading to a bit of
confusion. The patch makes a best guess at assigning ids. If anyone
can find a way to fix that particular issue, I’d love to see it.–
Terry Welsh
www.reallyslick.com
-------------- next part --------------
A non-text attachment was scrubbed…
Name: SDL_dxjoystick.c.patch
Type: application/octet-stream
Size: 5137 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20130820/89664c7b/attachment-0001.obj

Please don’t apply this patch. Someone at Valve has a fix that I haven’t
pushed upstream yet, and I’d like to see if it takes care of this issue
first.On Tue, Aug 20, 2013 at 5:39 PM, Terry Welsh wrote:

Hi Ryan,
The attached patch is my best stab at fixing this problem. It also
fixes Bug 1984. The problem I had with crashes on
SDL_HapticOpenFromJoystick() is not fixed. Maybe I’ll look for that
one tomorrow.

Unfortunately, I don’t think DirectInput/XInput has a complete API. I
found no way to match XInpuUserId with a specific device enumerated by
EnumJoysticksCallback(). In my game’s case, I let the user choose and
configure input devices based on their name. You might see a “wired
Xbox controller” and a “wireless Xbox controller” but their
XInpuUserIds could be swapped internally leading to a bit of
confusion. The patch makes a best guess at assigning ids. If anyone
can find a way to fix that particular issue, I’d love to see it.

Terry Welsh
www.reallyslick.com


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I haven’t had a chance to debug this at all, but let me know if I should
take Valve’s and Terry’s work and figure out what to do with all of it.

I have multiple Xbox360 controllers and a good reproduction case ready
when you say. :slight_smile:

–ryan.On 08/21/2013 01:08 AM, Sam Lantinga wrote:

Please don’t apply this patch. Someone at Valve has a fix that I
haven’t pushed upstream yet, and I’d like to see if it takes care of
this issue first.

Sure, I’ll push it tomorrow and you can look at them and see what is best.On Wed, Aug 21, 2013 at 1:12 AM, Ryan C. Gordon wrote:

On 08/21/2013 01:08 AM, Sam Lantinga wrote:

Please don’t apply this patch. Someone at Valve has a fix that I
haven’t pushed upstream yet, and I’d like to see if it takes care of
this issue first.

I haven’t had a chance to debug this at all, but let me know if I should
take Valve’s and Terry’s work and figure out what to do with all of it.

I have multiple Xbox360 controllers and a good reproduction case ready
when you say. :slight_smile:

–ryan.

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Can you try the latest in Mercurial? This should all be fixed now.

(I gave up on trying to match XInput userids to DirectInput GUIDs. Now
we keep the two APIs completely separate, which will be useful for later
anyhow, since apparently using DirectInput is forbidden for Microsoft
Store apps.)

–ryan.On 08/12/2013 12:54 PM, Terry Welsh wrote:

Hi Ryan,
This problem only appears on Windows, not Linux. It’s my lucky day,
though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

There are 2 joysticks attached
Joystick 0: Controller (Xbox 360 Wireless Receiver for Windows)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 1
guid: 5e04a102000000000000504944564944
Joystick 1: XBOX 360 For Windows (Controller)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 0
guid: 5e048e02000000000000504944564944

Then if I run testjoystick with a 0 or 1 on the command line, the
wired controller is the one that is opened each time. The output will
call it joystick 1 in the first case and joystick 0 in the second
case. The wireless controller never has any effect.

If I add a Logitech RumblePad 2 to the scenario, it behaves normally
and the Xbox controllers still have a problem. If I use the Logitech
and just one Xbox controller, everything works as it should. So the
problem seems to be confined to my Xbox controllers.

The problem in my game is slightly different: the two Xbox controllers
will be swapped and control the wrong players. They appear to command
different event “which” values than their instance ids. Of course, the
big difference here is that testjoystick opens only one controller for
testing and my game opens multiple controllers at the same time.

On a side note, my game crashes using SDL_HapticOpenFromJoystick(). It
succeeds for the wireless controller, but crashes the second time it
is called on wired controller. Using SDL_HapticOpen() instead works
fine. I wonder if this is related to the first problem. The crash does
not occur if I add HapticOpenFromJoystick() to testjoystick, perhaps
because only one controller is opened at a time.

  • Terry

On 08/12/2013 12:36 AM, Terry Welsh wrote:

When I want to match up an event to a joystick I look at a “which"
value such as event.jbutton.which. I have been comparing this to the
value returned from SDL_JoystickInstanceID(SDL_Joystick * joystick)
because its return type is SDL_JoystickID just like the type of
"which.” However, I have a case with multiple game controllers where
these values don’t match up the way they should. Is there something
other than SDL_JoystickInstanceID() I should be using to compare with
"which"?

This should be correct. This can go wrong if you pass
SDL_JoystickInstanceID() a closed/disconnected stick (in which case
it’ll give you -1), or a bogus pointer (in which case it can give you
any random value).

If you have a simple reproduction case, though, I’ll take a look at it.

–ryan.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Can you try the latest in Mercurial? This should all be fixed now.

Looking good. Thank you. I thought there was a new bug, but it looks
like you fixed it about 30 minutes ago :slight_smile:

(I gave up on trying to match XInput userids to DirectInput GUIDs. Now
we keep the two APIs completely separate, which will be useful for later
anyhow, since apparently using DirectInput is forbidden for Microsoft
Store apps.)

Your choice to call all these devices “XInput Controller” is sensible
since these APIs are so deficient and the devices can’t be properly
indexed. However, I don’t think the “#1”, “#2” should be part of the
name since it is inconsistent with the way other devices are named; my
non-XInput controllers don’t have that suffix. Also, those numbers
will change depending on the order in which you plug in your devices.

(I would explain to Microsoft how to properly render an API obsolete,
but I don’t think I could be civil after all this.)

  • Terry> --ryan.

On 08/12/2013 12:54 PM, Terry Welsh wrote:

Hi Ryan,
This problem only appears on Windows, not Linux. It’s my lucky day,
though. A similar problem appears using testjoystick. If I use an Xbox
wired controller and and Xbox wireless controller I get this output
from testjoystick:

There are 2 joysticks attached
Joystick 0: Controller (Xbox 360 Wireless Receiver for Windows)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 1
guid: 5e04a102000000000000504944564944
Joystick 1: XBOX 360 For Windows (Controller)
axes: 6
balls: 0
hats: 0
buttons: 15
instance id: 0
guid: 5e048e02000000000000504944564944

Then if I run testjoystick with a 0 or 1 on the command line, the
wired controller is the one that is opened each time. The output will
call it joystick 1 in the first case and joystick 0 in the second
case. The wireless controller never has any effect.

If I add a Logitech RumblePad 2 to the scenario, it behaves normally
and the Xbox controllers still have a problem. If I use the Logitech
and just one Xbox controller, everything works as it should. So the
problem seems to be confined to my Xbox controllers.

The problem in my game is slightly different: the two Xbox controllers
will be swapped and control the wrong players. They appear to command
different event “which” values than their instance ids. Of course, the
big difference here is that testjoystick opens only one controller for
testing and my game opens multiple controllers at the same time.

On a side note, my game crashes using SDL_HapticOpenFromJoystick(). It
succeeds for the wireless controller, but crashes the second time it
is called on wired controller. Using SDL_HapticOpen() instead works
fine. I wonder if this is related to the first problem. The crash does
not occur if I add HapticOpenFromJoystick() to testjoystick, perhaps
because only one controller is opened at a time.

  • Terry

Your choice to call all these devices “XInput Controller” is sensible
since these APIs are so deficient and the devices can’t be properly
indexed. However, I don’t think the “#1”, “#2” should be part of the
name since it is inconsistent with the way other devices are named; my
non-XInput controllers don’t have that suffix. Also, those numbers
will change depending on the order in which you plug in your devices.

True, but they match the number next to the light in the center of the
controller. If you got “XInput Controller #2”, then the light with the
"#2" next to it should be lit up on that device. Plug in two joysticks,
yank the first one out, and SDL will still report seeing only device #2.

Even if we could get real names for these, if you have 4 wireless
controllers connected, “XBOX 360 Wireless Controller” is less useful
information. :slight_smile:

–ryan.

Your choice to call all these devices “XInput Controller” is sensible
since these APIs are so deficient and the devices can’t be properly
indexed. However, I don’t think the “#1”, “#2” should be part of the
name since it is inconsistent with the way other devices are named; my
non-XInput controllers don’t have that suffix. Also, those numbers
will change depending on the order in which you plug in your devices.

True, but they match the number next to the light in the center of the
controller. If you got “XInput Controller #2”, then the light with the
"#2" next to it should be lit up on that device. Plug in two joysticks,
yank the first one out, and SDL will still report seeing only device #2.

Hmm. That’s a good point. I think I still prefer consistent behavior,
but I’ll just have to get over it. On a related note, those lights
rarely work correctly in Vista (my controllers usually both show light
#1). Fortunately, I’m the only person in the world who is still
running Vista. The lights usually work in Win7. How about Win8? I
don’t have Win8 to test on.

  • Terry