Jump to content
  • Advertisement
Sign in to follow this  
JackOfCandles

SDL2 - Unexpected Behavior When Hot Swapping Gamepads If One Or More Is Asleep

Recommended Posts

I created a small test application where I handle the SDL_CONTROLLERDEVICEADDED and SDL_CONTROLLERDEVICEREMOVED events, and output information about the controller being added/removed, based on the information in this blog.

I have two controllers connected to my PC, an Xbox 360 controller and a Logitech controller. What I found is that if they are both active and awake it produces the expected output, but if either one or both of them are asleep, it outputs the wrong name under certain conditions. I don't want to be overly verbose and go over every configuration I tested, but one example is if I start the application with both controllers in sleep mode, it fires the SDL_CONTROLLERDEVICEADDED for the Logitech controller but not the Xbox controller at application startup (The event for the Xbox control only happens when it is awakened), and then when I unplug/plug in the Logitech controller's USB receiver, it shows the device name as "X360" every time, until I wake them both up, at which point it outputs the correct name again.

Perhaps I'm worrying too much about this, as most people probably don't mix and match controllers and likely only use one, but I just found it curious. I'm wondering if it might be a bug in SDL2, or if maybe there is some insight someone might have related to xbox controllers and how they behave in sleep mode.

 

Here is the relevant code if anyone's interested:

struct SdlGamepad
{
	SDL_GameController*	controller;
	SDL_Joystick*		joystick;
	SDL_JoystickID		joystickId;
	std::string		deviceName;
	int			deviceId;
};



std::map<SDL_JoystickID, SdlGamepad> joystickIdToGamepadMap;

SDL_Event event;

bool hasQuit = false;

while (hasQuit == false)
{
	while (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
			case SDL_CONTROLLERDEVICEADDED:
			{
				std::cout << "Controller device added." << std::endl;

				if (SDL_IsGameController(event.cdevice.which))
				{
					SdlGamepad gamepad;

					gamepad.controller = SDL_GameControllerOpen(event.cdevice.which);
					gamepad.joystick = SDL_GameControllerGetJoystick(gamepad.controller);
					gamepad.joystickId = SDL_JoystickInstanceID(gamepad.joystick);

					std::string deviceName = SDL_GameControllerName(gamepad.controller);

					gamepad.deviceName = deviceName;
					gamepad.deviceId = event.cdevice.which;

					joystickIdToGamepadMap[gamepad.joystickId] = gamepad;

					std::cout 
						<< "Controller device name = " << gamepad.deviceName << std::endl
						<< "Controller device ID = " << gamepad.deviceId << std::endl
						<< "Joystick device ID = " << gamepad.joystickId << std::endl << std::endl;

				}

				break;
			}
			case SDL_CONTROLLERDEVICEREMOVED:
			{
				std::cout << "Controller device removed." << std::endl;

				SdlGamepad gamepad = joystickIdToGamepadMap[event.cdevice.which];

				std::cout
					<< "Controller device name = " << gamepad.deviceName << std::endl
					<< "Controller device ID = " << gamepad.deviceId << std::endl
					<< "Joystick device ID = " << gamepad.joystickId << std::endl << std::endl;
  
				SDL_GameControllerClose(gamepad.controller);

				joystickIdToGamepadMap.erase(event.cdevice.which);
  
				break;
			}
			case SDL_QUIT:
			{
				hasQuit = true;
				break;
			}
		}
	}
}

 

Share this post


Link to post
Share on other sites
Advertisement

Perhaps I'm misunderstanding. I'm using the joystick ID as the map key, obtained as the above link says, by calling SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(myController)), albeit factored out into multiple lines. Is that not correct?

Share this post


Link to post
Share on other sites

Your code looks right. The code that is relevant for this particular can be condensed to:

SDL_Event event;
while (SDL_PollEvent(&event))
{
  switch (event.type)
  {
    case SDL_CONTROLLERDEVICEADDED:
    {
      std::cout << "Controller device added." << std::endl;
      if (SDL_IsGameController(event.cdevice.which))
      {
        auto controller = SDL_GameControllerOpen(event.cdevice.which);
        std::cout << "Controller device name = " << SDL_GameControllerName(gamepad.controller) << std::endl;
      }
      break;
    }
  }
}

This should still reproduce the same problem. If it does, I suggest that you report this as a bug in SDL.

Edited by Ansou

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!