SDL_Joystick event `jdevice.which` reports wrong IDs

I’m doing a test with multiple connected joysticks.

The test consist in Remove/Add the same controller multiple times. To reproduce the test do:

  1. Connect PS3 joystick;

    INFO: Joystick device 0 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: Joystick device 1 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad

  2. Connect PS4 Joystick;

    INFO: Joystick device 2 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller

  3. Connect XBOX One joystick.

    INFO: Joystick device 3 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller
    INFO: JoyID: 3 - Name: Xbox One S Controller

  4. Remove XBOX One Joystick

    INFO: Joystick device 3 removed.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller

  5. Add XBOX One Joystick

    INFO: Joystick device 3 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller
    INFO: JoyID: 3 - Name: Xbox One S Controller

TO THIS POINT ALL SEEMS CORRECT

  1. Remove XBOX One Joystick

    INFO: Joystick device 4 removed.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller

  2. Add XBOX One Joystick

    INFO: Joystick device 3 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller
    INFO: JoyID: 3 - Name: Xbox One S Controller

  3. Remove XBOX One Joystick

    INFO: Joystick device 5 removed.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller

  4. Add XBOX One Joystick

    INFO: Joystick device 3 added.
    INFO: JoyID: 0 - Name: Gasia Co.,Ltd PS® Gamepad Motion Sensors
    INFO: JoyID: 1 - Name: Gasia Co.,Ltd PS® Gamepad
    INFO: JoyID: 2 - Name: Sony Interactive Entertainment Wireless Controller
    INFO: JoyID: 3 - Name: Xbox One S Controller

  5. The pattern continues. Every time I remove a controller (in this case XBOXOne), it keeps increasing one. The pattern also occurs when removing other joysticks too. This was just a particular case.

As far as I can tell the IDs returned by jdevice.which in SDL_JOYDEVICEREMOVED event is reporting the wrong IDs.

The code to reproduce the problem is

#include <SDL2/SDL.h>

void list_joysticks(void);

int main(void)
{ 
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
    int sdl_flags = SDL_INIT_JOYSTICK;
    int is_running = 1;

    SDL_Init(sdl_flags);
    SDL_Event event;
    while(is_running == 1)
    {
        while(SDL_PollEvent(&event)) {
            switch(event.type)
            {
                case SDL_JOYDEVICEADDED:
                    SDL_Log("Joystick device %d added.\n", (int) event.jdevice.which);
                    list_joysticks();
                    break;
                case SDL_JOYDEVICEREMOVED:
                    SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
                    list_joysticks();
                    break;
                case SDL_QUIT:
                    is_running = 0;
                    break;
                default:
                    break;
            }
        }
    }
    SDL_Quit();
    return 0;
}

void
list_joysticks(void)
{
    for (Uint8 i=0; i < SDL_NumJoysticks(); i++)
        SDL_Log("JoyID: %d - Name: %s\n", i, SDL_JoystickNameForIndex(i));
}

There are 2 index for joystick:

  • “device index”, used before joystick is open (SDL_OpenJoystick, SDL_JOYDEVICEADDED…)
  • “instance id”, used once joystick is opened (SDL_JOYDEVICEREMOVED, …)

See the remark in the wiki:
https://wiki.libsdl.org/SDL_JoystickOpen?highlight=(\bCategoryJoystick\b)|(CategoryEnum)|(CategoryStruct)

1 Like