Example #1
0
static GamepadDevice* gamepad_find_device_by_guid(const char *guid_str, char *guid_out, size_t guid_out_sz, int *out_localdevnum) {
	if(gamepad.num_devices < 1) {
		*out_localdevnum = GAMEPAD_DEVNUM_INVALID;
		return NULL;
	}

	if(!strcasecmp(guid_str, "any")) {
		*out_localdevnum = GAMEPAD_DEVNUM_ANY;
		strlcpy(guid_out, "any", guid_out_sz);
		return NULL;
	}

	for(int i = 0; i < gamepad.num_devices; ++i) {
		*guid_out = 0;

		SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(gamepad.devices[i].sdl_id);
		SDL_JoystickGetGUIDString(guid, guid_out, guid_out_sz);

		if(!strcasecmp(guid_str, guid_out) || !strcasecmp(guid_str, "default")) {
			*out_localdevnum = i;
			return gamepad.devices + i;
		}
	}

	*out_localdevnum = GAMEPAD_DEVNUM_INVALID;
	return NULL;
}
FGuid FDeviceSDL::DeviceGUIDtoGUID(FDeviceIndex DeviceIndex)
{
	FGuid result;
	SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(DeviceIndex.value);
	memcpy(&result, &guid, sizeof(FGuid));
	return result;
}
Example #3
0
// static
QVariantList Joystick::enumerateDevices()
{
    QVariantList list;
    char guidbuf[128];
    int nconnected = SDL_NumJoysticks();

    if (!nconnected) {
        qCCritical(phxInput, "Unable to enumerate joysticks: %s", SDL_GetError());
    }

    for (int i = 0; i < nconnected; i++) {
        const char* jsname = SDL_JoystickNameForIndex(i);
        if (!jsname)
            continue;
        SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guidbuf, 128);
        list.append(QVariantMap {
            { "text", QString(jsname) }, // for QML model
            { "name", QString(jsname) },
            { "driver", QString(SDL_IsGameController(i) ? "sdl_gamecontroller"
                                                        : "sdl_joystick") },
            { "guid", QString(guidbuf) }
        });
    }
    return list;
}
Example #4
0
/*
 * Helper function to determine pre-calculated offset to certain joystick mappings
 */
ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
    SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
    ControllerMapping_t *mapping;

    mapping = SDL_PrivateGetControllerMappingForGUID(&jGUID);
#if SDL_JOYSTICK_XINPUT
    if (!mapping && SDL_SYS_IsXInputGamepad_DeviceIndex(device_index)) {
        mapping = s_pXInputMapping;
    }
#endif
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
    if (!mapping && s_pEmscriptenMapping) {
        mapping = s_pEmscriptenMapping;
    }
#endif
    if (!mapping) {
        const char *name = SDL_JoystickNameForIndex(device_index);
        if (name) {
            if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box")) {
                mapping = s_pXInputMapping;
            }
        }
    }
    return mapping;
}
Example #5
0
Uint16 SDL_JoystickGetDeviceVendor(int device_index)
{
    Uint16 vendor;
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);

    SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL);
    return vendor;
}
Example #6
0
Uint16 SDL_JoystickGetDeviceProductVersion(int device_index)
{
    Uint16 version;
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);

    SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version);
    return version;
}
Example #7
0
Uint16 SDL_JoystickGetDeviceProduct(int device_index)
{
    Uint16 product;
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);

    SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL);
    return product;
}
Example #8
0
static mrb_value
mrb_sdl2_joystick_get_guid(mrb_state *mrb, mrb_value self)
{
  SDL_JoystickGUID result;
  mrb_int index;
  mrb_get_args(mrb, "i", &index);
  result = SDL_JoystickGetDeviceGUID(index);
  return mrb_fixnum_value(*result.data);
}
FString FDeviceSDL::DeviceGUIDtoString(FDeviceIndex DeviceIndex)
{
	char buffer[32];
	int8 sizeBuffer = sizeof(buffer);

	SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(DeviceIndex.value);
	SDL_JoystickGetGUIDString(guid, buffer, sizeBuffer);
	return ANSI_TO_TCHAR(buffer);
}
Example #10
0
SDL_JoystickType SDL_JoystickGetDeviceType(int device_index)
{
    SDL_JoystickType type;
    SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);

    type = SDL_GetJoystickGUIDType(guid);
    if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
        if (SDL_IsGameController(device_index)) {
            type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
        }
    }
    return type;
}
Example #11
0
/*
 * Helper function to determine pre-calculated offset to certain joystick mappings
 */
ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
    if (SDL_SYS_IsXInputDeviceIndex(device_index) && s_pXInputMapping) {
        return s_pXInputMapping;
    }
    else
#endif
    {
        SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
        return SDL_PrivateGetControllerMappingForGUID(&jGUID);
    }
}
Example #12
0
/*
 * Helper function to determine pre-calculated offset to certain joystick mappings
 */
ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
#if SDL_JOYSTICK_XINPUT
    if (SDL_SYS_IsXInputGamepad_DeviceIndex(device_index) && s_pXInputMapping) {
        return s_pXInputMapping;
    }
    else
#endif /* SDL_JOYSTICK_XINPUT */
    {
        SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
        return SDL_PrivateGetControllerMappingForGUID(&jGUID);
    }
}
/*
 * Helper function to determine pre-calculated offset to certain joystick mappings
 */
ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
#if SDL_JOYSTICK_XINPUT
    if (SDL_SYS_IsXInputGamepad_DeviceIndex(device_index) && s_pXInputMapping) {
        return s_pXInputMapping;
    }
    else
#endif
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
    if (s_pEmscriptenMapping) {
        return s_pEmscriptenMapping;
    }
    else
#endif
    {
        SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
        return SDL_PrivateGetControllerMappingForGUID(&jGUID);
    }
}
Example #14
0
bool Joystick::deviceAdded(const SDL_Event *event)
{
    int which = event->type == SDL_CONTROLLERDEVICEADDED ? event->cdevice.which
                                                         : event->jdevice.which;
    if (!m_mapping->matchJoystick(SDL_JoystickGetDeviceGUID(which)))
        return false;

    if (event->type == SDL_CONTROLLERDEVICEADDED) {
        attachGameController(which);
    } else {
        if (SDL_IsGameController(which)) {
            // joystick is a supported game controller
            // let's wait for the CONTROLLERADDED event to add it
            return false;
        }
        attachJoystick(which);
    }
    return true;
}
Example #15
0
/*
 * Helper function to determine pre-calculated offset to certain joystick mappings
 */
static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index)
{
    SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID(device_index);
    ControllerMapping_t *mapping;

    mapping = SDL_PrivateGetControllerMappingForGUID(&jGUID);
#if SDL_JOYSTICK_XINPUT
    if (!mapping && SDL_SYS_IsXInputGamepad_DeviceIndex(device_index)) {
        mapping = s_pXInputMapping;
    }
#endif
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
    if (!mapping && s_pEmscriptenMapping) {
        mapping = s_pEmscriptenMapping;
    }
#endif
#ifdef __LINUX__
    if (!mapping) {
        const char *name = SDL_JoystickNameForIndex(device_index);
        if (name) {
            if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) {
                /* The Linux driver xpad.c maps the wireless dpad to buttons */
                SDL_bool existing;
                mapping = SDL_PrivateAddMappingForGUID(jGUID,
"none,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
                              &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT);
            }
        }
    }
#endif /* __LINUX__ */

    if (!mapping) {
        const char *name = SDL_JoystickNameForIndex(device_index);
        if (name) {
            if (SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box")) {
                mapping = s_pXInputMapping;
            }
        }
    }
    return mapping;
}
Example #16
0
	void Joystick::open() {
		if (m_joystickHandle) {
			close();
		}

		m_joystickHandle = SDL_JoystickOpen(m_deviceIndex);
		if (m_joystickHandle) {
			m_instanceId = SDL_JoystickInstanceID(m_joystickHandle);

			char tmp[33];
			SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(m_deviceIndex);
			SDL_JoystickGetGUIDString(guid, tmp, sizeof(tmp));
			m_guidStr = std::string(tmp);

			openController();
			const char* name = SDL_JoystickNameForIndex(m_deviceIndex);
			if (isController() && !name) {
				name = SDL_GameControllerNameForIndex(m_deviceIndex);
			}
			m_name = std::string(name);
		} else {
			throw SDLException(SDL_GetError());
		}
	}
Example #17
0
Joystick::Joystick(InputDeviceMapping *mapping) : InputDevice(mapping)
{
    device_attached = false;
    joystick = nullptr;
    controller = nullptr;
    m_mapping = reinterpret_cast<Mapping *>(InputDevice::m_mapping);
    Q_ASSERT(m_mapping != nullptr);

    callback = std::bind(&Joystick::handleSDLEvent, this, std::placeholders::_1);
    sdl_events.registerCallback(&callback);

    for (int i = 0; i < SDL_NumJoysticks(); i++) {
        if (!m_mapping->matchJoystick(SDL_JoystickGetDeviceGUID(i)))
            continue;

        if (SDL_IsGameController(i)) {
            attachGameController(i);
            break;
        } else {
            attachJoystick(i);
            break;
        }
    }
}
Example #18
0
/*
 * Initializes the backend
 */
void
IN_Init(void)
{
	Com_Printf("------- input initialization -------\n");

	mouse_x = mouse_y = 0;

#if SDL_VERSION_ATLEAST(2, 0, 0)
	joystick_yaw = joystick_pitch = joystick_forwardmove = joystick_sidemove = 0;
#endif

	exponential_speedup = Cvar_Get("exponential_speedup", "0", CVAR_ARCHIVE);
	freelook = Cvar_Get("freelook", "1", 0);
	in_grab = Cvar_Get("in_grab", "2", CVAR_ARCHIVE);
	lookstrafe = Cvar_Get("lookstrafe", "0", 0);
	m_filter = Cvar_Get("m_filter", "0", CVAR_ARCHIVE);
	m_up = Cvar_Get("m_up", "1", 0);
	m_forward = Cvar_Get("m_forward", "1", 0);
	m_pitch = Cvar_Get("m_pitch", "0.022", 0);
	m_side = Cvar_Get("m_side", "0.8", 0);
	m_yaw = Cvar_Get("m_yaw", "0.022", 0);
	sensitivity = Cvar_Get("sensitivity", "3", 0);

#if SDL_VERSION_ATLEAST(2, 0, 0)
	joy_haptic_magnitude = Cvar_Get("joy_haptic_magnitude", "0.0", CVAR_ARCHIVE);

	joy_yawsensitivity = Cvar_Get("joy_yawsensitivity", "1.0", CVAR_ARCHIVE);
	joy_pitchsensitivity = Cvar_Get("joy_pitchsensitivity", "1.0", CVAR_ARCHIVE);
	joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
	joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
	joy_upsensitivity = Cvar_Get("joy_upsensitivity", "1.0", CVAR_ARCHIVE);

	joy_axis_leftx = Cvar_Get("joy_axis_leftx", "sidemove", CVAR_ARCHIVE);
	joy_axis_lefty = Cvar_Get("joy_axis_lefty", "forwardmove", CVAR_ARCHIVE);
	joy_axis_rightx = Cvar_Get("joy_axis_rightx", "yaw", CVAR_ARCHIVE);
	joy_axis_righty = Cvar_Get("joy_axis_righty", "pitch", CVAR_ARCHIVE);
	joy_axis_triggerleft = Cvar_Get("joy_axis_triggerleft", "triggerleft", CVAR_ARCHIVE);
	joy_axis_triggerright = Cvar_Get("joy_axis_triggerright", "triggerright", CVAR_ARCHIVE);

	joy_axis_leftx_threshold = Cvar_Get("joy_axis_leftx_threshold", "0.15", CVAR_ARCHIVE);
	joy_axis_lefty_threshold = Cvar_Get("joy_axis_lefty_threshold", "0.15", CVAR_ARCHIVE);
	joy_axis_rightx_threshold = Cvar_Get("joy_axis_rightx_threshold", "0.15", CVAR_ARCHIVE);
	joy_axis_righty_threshold = Cvar_Get("joy_axis_righty_threshold", "0.15", CVAR_ARCHIVE);
	joy_axis_triggerleft_threshold = Cvar_Get("joy_axis_triggerleft_threshold", "0.15", CVAR_ARCHIVE);
	joy_axis_triggerright_threshold = Cvar_Get("joy_axis_triggerright_threshold", "0.15", CVAR_ARCHIVE);
#endif

	vid_fullscreen = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
	windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);

	Cmd_AddCommand("+mlook", IN_MLookDown);
	Cmd_AddCommand("-mlook", IN_MLookUp);

#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_StartTextInput();
#else
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
#endif

#if SDL_VERSION_ATLEAST(2, 0, 0)
	/* joystik init */
	if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC))
	{
		if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == -1)
		{
			Com_Printf ("Couldn't init SDL joystick: %s.\n", SDL_GetError ());
		} else {
			Com_Printf ("%i joysticks were found.\n", SDL_NumJoysticks());
			if (SDL_NumJoysticks() > 0) {
				int i;
				for (i=0; i<SDL_NumJoysticks(); i ++) {
					joystick = SDL_JoystickOpen(i);
					Com_Printf ("The name of the joystick is '%s'\n", SDL_JoystickName(joystick));
					Com_Printf ("Number of Axes: %d\n", SDL_JoystickNumAxes(joystick));
					Com_Printf ("Number of Buttons: %d\n", SDL_JoystickNumButtons(joystick));
					Com_Printf ("Number of Balls: %d\n", SDL_JoystickNumBalls(joystick));
					Com_Printf ("Number of Hats: %d\n", SDL_JoystickNumHats(joystick));

					joystick_haptic = SDL_HapticOpenFromJoystick(joystick);
					if (joystick_haptic == NULL)
						Com_Printf ("Most likely joystick isn't haptic\n");
					else
						IN_Haptic_Effects_Info();

					if(SDL_IsGameController(i))
					{
						SDL_GameControllerButtonBind backBind;
						controller = SDL_GameControllerOpen(i);
						Com_Printf ("Controller settings: %s\n", SDL_GameControllerMapping(controller));
						Com_Printf ("Controller axis: \n");
						Com_Printf (" * leftx = %s\n", joy_axis_leftx->string);
						Com_Printf (" * lefty = %s\n", joy_axis_lefty->string);
						Com_Printf (" * rightx = %s\n", joy_axis_rightx->string);
						Com_Printf (" * righty = %s\n", joy_axis_righty->string);
						Com_Printf (" * triggerleft = %s\n", joy_axis_triggerleft->string);
						Com_Printf (" * triggerright = %s\n", joy_axis_triggerright->string);

						Com_Printf ("Controller thresholds: \n");
						Com_Printf (" * leftx = %f\n", joy_axis_leftx_threshold->value);
						Com_Printf (" * lefty = %f\n", joy_axis_lefty_threshold->value);
						Com_Printf (" * rightx = %f\n", joy_axis_rightx_threshold->value);
						Com_Printf (" * righty = %f\n", joy_axis_righty_threshold->value);
						Com_Printf (" * triggerleft = %f\n", joy_axis_triggerleft_threshold->value);
						Com_Printf (" * triggerright = %f\n", joy_axis_triggerright_threshold->value);

						backBind = SDL_GameControllerGetBindForButton(controller, SDL_CONTROLLER_BUTTON_BACK);

						if (backBind.bindType == SDL_CONTROLLER_BINDTYPE_BUTTON) {
							back_button_id = backBind.value.button;
							Com_Printf ("\nBack button JOY%d will be unbindable.\n", back_button_id+1);
						}
						break;
					}
					else
					{
						char joystick_guid[256] = {0};
						SDL_JoystickGUID guid;
						guid = SDL_JoystickGetDeviceGUID(i);
						SDL_JoystickGetGUIDString(guid, joystick_guid, 255);
						Com_Printf ("For use joystic as game contoller please set SDL_GAMECONTROLLERCONFIG:\n");
						Com_Printf ("e.g.: SDL_GAMECONTROLLERCONFIG='%s,%s,leftx:a0,lefty:a1,rightx:a2,righty:a3,back:b1,...\n", joystick_guid, SDL_JoystickName(joystick));
					}
				}
			}
			else
			{
				joystick_haptic = SDL_HapticOpenFromMouse();
				if (joystick_haptic == NULL)
					Com_Printf ("Most likely mouse isn't haptic\n");
				else
					IN_Haptic_Effects_Info();
			}
		}
	}
#endif

	Com_Printf("------------------------------------\n\n");
}
Example #19
0
static bool gamepad_update_device_list(void) {
	int cnt = SDL_NumJoysticks();
	log_info("Updating gamepad devices list");

	if(gamepad.num_devices > 0) {
		assume(gamepad.devices != NULL);

		for(uint i = 0; i < gamepad.num_devices; ++i) {
			SDL_GameControllerClose(gamepad.devices[i].controller);
		}
	}

	gamepad.num_devices = 0;

	if(!cnt) {
		free(gamepad.devices);
		gamepad.devices = NULL;
		gamepad.num_devices_allocated = 0;
		log_info("No joysticks attached");
		return false;
	}

	if(gamepad.num_devices_allocated != cnt) {
		free(gamepad.devices);
		gamepad.devices = calloc(cnt, sizeof(GamepadDevice));
		gamepad.num_devices_allocated = cnt;
	}

	GamepadDevice *dev = gamepad.devices;

	for(int i = 0; i < cnt; ++i) {
		SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i);
		char guid_str[33] = { 0 };
		SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));

		if(!*guid_str) {
			log_warn("Failed to read GUID of joystick at index %i: %s", i, SDL_GetError());
			continue;
		}

		if(!SDL_IsGameController(i)) {
			log_warn("Joystick at index %i (name: \"%s\"; guid: %s) is not recognized as a game controller by SDL. "
					 "Most likely it just doesn't have a mapping. See https://git.io/vdvdV for solutions",
				i, SDL_JoystickNameForIndex(i), guid_str);
			continue;
		}

		dev->sdl_id = i;
		dev->controller = SDL_GameControllerOpen(i);

		if(dev->controller == NULL) {
			log_sdl_error(LOG_WARN, "SDL_GameControllerOpen");
			continue;
		}

		dev->joy_instance = SDL_JoystickGetDeviceInstanceID(i);

		if(dev->joy_instance < 0) {
			log_sdl_error(LOG_WARN, "SDL_JoystickGetDeviceInstanceID");
			continue;
		}

		log_info("Found device '%s' (#%i): %s", guid_str, DEVNUM(dev), gamepad_device_name_unmapped(i));

		++gamepad.num_devices;
		++dev;
	}

	if(!gamepad.num_devices) {
		log_info("No usable devices");
		return false;
	}

	return true;
}
int main(int argc, char *argv[]) {
  int i;
  int nController = 0;
  int retcode = 0;
  char guid[64];
  SDL_GameController *gamecontroller;

  /* Enable standard application logging */
  SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

  /* Initialize SDL (Note: video is required to start event loop) */
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) <
      0) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n",
                 SDL_GetError());
    return 1;
  }

  SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

  /* Print information about the controller */
  for (i = 0; i < SDL_NumJoysticks(); ++i) {
    const char *name;
    const char *description;

    SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), guid, sizeof(guid));

    if (SDL_IsGameController(i)) {
      nController++;
      name = SDL_GameControllerNameForIndex(i);
      description = "Controller";
    } else {
      name = SDL_JoystickNameForIndex(i);
      description = "Joystick";
    }
    SDL_Log("%s %d: %s (guid %s)\n", description, i, name ? name : "Unknown",
            guid);
  }
  SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n",
          nController, SDL_NumJoysticks());

  if (argv[1]) {
    SDL_bool reportederror = SDL_FALSE;
    SDL_bool keepGoing = SDL_TRUE;
    SDL_Event event;
    int device = atoi(argv[1]);
    if (device >= SDL_NumJoysticks()) {
      SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
                   "%i is an invalid joystick index.\n", device);
      retcode = 1;
    } else {
      SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device), guid,
                                sizeof(guid));
      SDL_Log("Attempting to open device %i, guid %s\n", device, guid);
      gamecontroller = SDL_GameControllerOpen(device);

      /* - this requires SDL 2.0.4
if (gamecontroller != NULL) {
SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller)))
== gamecontroller);
}
*/

      while (keepGoing) {
        if (gamecontroller == NULL) {
          if (!reportederror) {
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
                         "Couldn't open gamecontroller %d: %s\n", device,
                         SDL_GetError());
            retcode = 1;
            keepGoing = SDL_FALSE;
            reportederror = SDL_TRUE;
          }
        } else {
          reportederror = SDL_FALSE;
          keepGoing = WatchGameController(gamecontroller);
          SDL_GameControllerClose(gamecontroller);
        }

        gamecontroller = NULL;
        if (keepGoing) {
          SDL_Log("Waiting for attach\n");
        }
        while (keepGoing) {
          SDL_WaitEvent(&event);
          if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN) ||
              (event.type == SDL_MOUSEBUTTONDOWN)) {
            keepGoing = SDL_FALSE;
          } else if (event.type == SDL_CONTROLLERDEVICEADDED) {
            gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
            /* - this requires SDL 2.0.4
            if (gamecontroller != NULL) {
                SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller)))
            == gamecontroller);
            }
            */
            break;
          }
        }
      }
    }
  }

  SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK |
                    SDL_INIT_GAMECONTROLLER);

  return retcode;
}