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; }
/* * Open a joystick for use - the index passed as an argument refers to * the N'th joystick on the system. This index is the value which will * identify this joystick in future joystick events. * * This function returns a joystick identifier, or NULL if an error occurred. */ SDL_Joystick * SDL_JoystickOpen(int device_index) { SDL_Joystick *joystick; SDL_Joystick *joysticklist; const char *joystickname = NULL; if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); return (NULL); } SDL_LockJoystickList(); joysticklist = SDL_joysticks; /* If the joystick is already open, return it * it is important that we have a single joystick * for each instance id */ while (joysticklist) { if (SDL_JoystickGetDeviceInstanceID(device_index) == joysticklist->instance_id) { joystick = joysticklist; ++joystick->ref_count; SDL_UnlockJoystickList(); return (joystick); } joysticklist = joysticklist->next; } /* Create and initialize the joystick */ joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1); if (joystick == NULL) { SDL_OutOfMemory(); SDL_UnlockJoystickList(); return NULL; } if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) { SDL_free(joystick); SDL_UnlockJoystickList(); return NULL; } joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index); if (joystickname) joystick->name = SDL_strdup(joystickname); else joystick->name = NULL; if (joystick->naxes > 0) { joystick->axes = (SDL_JoystickAxisInfo *) SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo)); } if (joystick->nhats > 0) { joystick->hats = (Uint8 *) SDL_calloc(joystick->nhats, sizeof(Uint8)); } if (joystick->nballs > 0) { joystick->balls = (struct balldelta *) SDL_calloc(joystick->nballs, sizeof(*joystick->balls)); } if (joystick->nbuttons > 0) { joystick->buttons = (Uint8 *) SDL_calloc(joystick->nbuttons, sizeof(Uint8)); } if (((joystick->naxes > 0) && !joystick->axes) || ((joystick->nhats > 0) && !joystick->hats) || ((joystick->nballs > 0) && !joystick->balls) || ((joystick->nbuttons > 0) && !joystick->buttons)) { SDL_OutOfMemory(); SDL_JoystickClose(joystick); SDL_UnlockJoystickList(); return NULL; } joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; /* If this joystick is known to have all zero centered axes, skip the auto-centering code */ if (SDL_JoystickAxesCenteredAtZero(joystick)) { int i; for (i = 0; i < joystick->naxes; ++i) { joystick->axes[i].has_initial_value = SDL_TRUE; } } joystick->is_game_controller = SDL_IsGameController(device_index); /* Add joystick to list */ ++joystick->ref_count; /* Link the joystick in the list */ joystick->next = SDL_joysticks; SDL_joysticks = joystick; SDL_UnlockJoystickList(); SDL_SYS_JoystickUpdate(joystick); return (joystick); }