From 16092f58bbc1ac99121b23a8d4a03a36c3e12f25 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 27 Dec 2022 18:10:06 -0800
Subject: [PATCH] Updated gamepad, joystick, sensor APIs, removing device
indices
Instead of indexing into an internal list of devices which requires locking, we return a list of device IDs which can then be queried individually.
Reference: https://github.com/libsdl-org/SDL/issues/6889
---
WhatsNew.txt | 3 +
docs/README-migration.md | 105 +++++--
include/SDL3/SDL_events.h | 4 +-
include/SDL3/SDL_gamepad.h | 187 ++++++++----
include/SDL3/SDL_joystick.h | 163 +++++------
include/SDL3/SDL_oldnames.h | 19 --
include/SDL3/SDL_sensor.h | 67 ++---
src/dynapi/SDL_dynapi.sym | 47 +--
src/dynapi/SDL_dynapi_overrides.h | 47 +--
src/dynapi/SDL_dynapi_procs.h | 63 ++--
src/events/SDL_events.c | 17 +-
src/joystick/SDL_gamepad.c | 157 ++++++----
src/joystick/SDL_joystick.c | 289 +++++++------------
src/joystick/SDL_joystick_c.h | 9 +-
src/joystick/SDL_sysjoystick.h | 2 +-
src/joystick/hidapi/SDL_hidapi_gamecube.c | 20 +-
src/joystick/virtual/SDL_virtualjoystick.c | 36 ++-
src/joystick/virtual/SDL_virtualjoystick_c.h | 4 +-
src/sensor/SDL_sensor.c | 121 +++++---
src/sensor/SDL_sensor_c.h | 3 +
src/test/SDL_test_common.c | 30 +-
test/gamepadmap.c | 55 ++--
test/testautomation_joystick.c | 16 +-
test/testgamepad.c | 172 +++++------
test/testhotplug.c | 12 +-
test/testjoystick.c | 31 +-
test/testsensor.c | 35 ++-
27 files changed, 917 insertions(+), 797 deletions(-)
diff --git a/WhatsNew.txt b/WhatsNew.txt
index 21f82536fbf3..10625d97affb 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -12,6 +12,9 @@ General:
* The preprocessor symbol __IPHONEOS__ has been renamed __IOS__
* SDL_stdinc.h no longer includes stdio.h, stdlib.h, etc., it only provides the SDL C runtime functionality
* Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace SDL_CreateRGBSurface*(), and can also be used to create YUV surfaces
+* Added SDL_HasJoysticks(), SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() to directly query the list of available joysticks
+* Added SDL_HasGamepads(), SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() to directly query the list of available gamepads
+* Added SDL_HasSensors(), SDL_GetSensors(), SDL_GetSensorInstanceName(), SDL_GetSensorInstanceType(), and SDL_GetSensorInstanceNonPortableType() to directly query the list of available sensors
* SDL_GetTicks() now returns a 64-bit value and the tick values should be directly compared instead of using the SDL_TICKS_PASSED macro
* Added SDL_GetTicksNS() to return the number of nanoseconds since the SDL library initialized
* Added SDL_DelayNS() to specify a delay in nanoseconds, to the highest precision the system will support
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 82a2d26c8dcd..8d3e77c740c8 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -112,7 +112,11 @@ The following structures have been renamed:
SDL_gamecontroller.h has been renamed SDL_gamepad.h, and all APIs have been renamed to match.
-Removed SDL_GameControllerGetSensorDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_GAMEPADSENSORUPDATE events.
+The SDL_GAMEPADADDED event now provides the joystick instance ID in the `which` member of the cdevice event structure.
+
+The functions SDL_HasGamepads(), SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads.
+
+SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_GAMEPADSENSORUPDATE events.
The following enums have been renamed:
* SDL_GameControllerAxis => SDL_GamepadAxis
@@ -164,25 +168,27 @@ The following functions have been renamed:
* SDL_GameControllerHasSensor => SDL_GamepadHasSensor
* SDL_GameControllerIsSensorEnabled => SDL_IsGamepadSensorEnabled
* SDL_GameControllerMapping => SDL_GetGamepadMapping
-* SDL_GameControllerMappingForDeviceIndex => SDL_GetGamepadMappingForDeviceIndex
* SDL_GameControllerMappingForGUID => SDL_GetGamepadMappingForGUID
* SDL_GameControllerMappingForIndex => SDL_GetGamepadMappingForIndex
* SDL_GameControllerName => SDL_GetGamepadName
-* SDL_GameControllerNameForIndex => SDL_GetGamepadNameForIndex
* SDL_GameControllerNumMappings => SDL_GetNumGamepadMappings
* SDL_GameControllerOpen => SDL_OpenGamepad
* SDL_GameControllerPath => SDL_GetGamepadPath
-* SDL_GameControllerPathForIndex => SDL_GetGamepadPathForIndex
* SDL_GameControllerRumble => SDL_RumbleGamepad
* SDL_GameControllerRumbleTriggers => SDL_RumbleGamepadTriggers
* SDL_GameControllerSendEffect => SDL_SendGamepadEffect
* SDL_GameControllerSetLED => SDL_SetGamepadLED
* SDL_GameControllerSetPlayerIndex => SDL_SetGamepadPlayerIndex
* SDL_GameControllerSetSensorEnabled => SDL_SetGamepadSensorEnabled
-* SDL_GameControllerTypeForIndex => SDL_GetGamepadTypeForIndex
* SDL_GameControllerUpdate => SDL_UpdateGamepads
* SDL_IsGameController => SDL_IsGamepad
+The following functions have been removed:
+* SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName()
+* SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath()
+* SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType()
+* SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadInstanceMapping()
+
The following symbols have been renamed:
* SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID
* SDL_CONTROLLER_AXIS_LEFTX => SDL_GAMEPAD_AXIS_LEFTX
@@ -260,6 +266,36 @@ The following macros have been renamed:
## SDL_joystick.h
+SDL_JoystickID has changed from Sint32 to Uint32, with an invalid ID being 0.
+
+Rather than iterating over joysticks using device index, there is a new function SDL_GetJoysticks() to get the current list of joysticks, and new functions to get information about joysticks from their instance ID:
+```c
+{
+ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == 0) {
+ int i, num_joysticks;
+ SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
+ if (joysticks) {
+ for (i = 0; i < num_joysticks; ++i) {
+ SDL_JoystickID instance_id = joysticks[i];
+ const char *name = SDL_GetJoystickInstanceName(instance_id);
+ const char *path = SDL_GetJoystickInstancePath(instance_id);
+
+ SDL_Log("Joystick %" SDL_PRIu32 ": %s%s%s VID 0x%.4x, PID 0x%.4x\n",
+ instance_id, name ? name : "Unknown", path ? ", " : "", path ? path : "", SDL_GetJoystickInstanceVendor(instance_id), SDL_GetJoystickInstanceProduct(instance_id));
+ }
+ SDL_free(joysticks);
+ }
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ }
+}
+```
+
+The SDL_JOYDEVICEADDED event now provides the joystick instance ID in the `which` member of the jdevice event structure.
+
+The functions SDL_HasJoysticks(), SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() have been added to directly query the list of available joysticks.
+
+SDL_AttachVirtualJoystick() and SDL_AttachVirtualJoystickEx() now return the joystick instance ID instead of a device index, and return 0 if there was an error.
+
The following functions have been renamed:
* SDL_JoystickAttachVirtual => SDL_AttachVirtualJoystick
* SDL_JoystickAttachVirtualEx => SDL_AttachVirtualJoystickEx
@@ -273,13 +309,6 @@ The following functions have been renamed:
* SDL_JoystickGetAxis => SDL_GetJoystickAxis
* SDL_JoystickGetAxisInitialState => SDL_GetJoystickAxisInitialState
* SDL_JoystickGetButton => SDL_GetJoystickButton
-* SDL_JoystickGetDeviceGUID => SDL_GetJoystickDeviceGUID
-* SDL_JoystickGetDeviceInstanceID => SDL_GetJoystickDeviceInstanceID
-* SDL_JoystickGetDevicePlayerIndex => SDL_GetJoystickDevicePlayerIndex
-* SDL_JoystickGetDeviceProduct => SDL_GetJoystickDeviceProduct
-* SDL_JoystickGetDeviceProductVersion => SDL_GetJoystickDeviceProductVersion
-* SDL_JoystickGetDeviceType => SDL_GetJoystickDeviceType
-* SDL_JoystickGetDeviceVendor => SDL_GetJoystickDeviceVendor
* SDL_JoystickGetFirmwareVersion => SDL_GetJoystickFirmwareVersion
* SDL_JoystickGetGUID => SDL_GetJoystickGUID
* SDL_JoystickGetGUIDFromString => SDL_GetJoystickGUIDFromString
@@ -294,13 +323,11 @@ The following functions have been renamed:
* SDL_JoystickInstanceID => SDL_GetJoystickInstanceID
* SDL_JoystickIsVirtual => SDL_IsJoystickVirtual
* SDL_JoystickName => SDL_GetJoystickName
-* SDL_JoystickNameForIndex => SDL_GetJoystickNameForIndex
* SDL_JoystickNumAxes => SDL_GetNumJoystickAxes
* SDL_JoystickNumButtons => SDL_GetNumJoystickButtons
* SDL_JoystickNumHats => SDL_GetNumJoystickHats
* SDL_JoystickOpen => SDL_OpenJoystick
* SDL_JoystickPath => SDL_GetJoystickPath
-* SDL_JoystickPathForIndex => SDL_GetJoystickPathForIndex
* SDL_JoystickRumble => SDL_RumbleJoystick
* SDL_JoystickRumbleTriggers => SDL_RumbleJoystickTriggers
* SDL_JoystickSendEffect => SDL_SendJoystickEffect
@@ -310,11 +337,22 @@ The following functions have been renamed:
* SDL_JoystickSetVirtualButton => SDL_SetJoystickVirtualButton
* SDL_JoystickSetVirtualHat => SDL_SetJoystickVirtualHat
* SDL_JoystickUpdate => SDL_UpdateJoysticks
-* SDL_NumJoysticks => SDL_GetNumJoysticks
The following symbols have been renamed:
* SDL_JOYSTICK_TYPE_GAMECONTROLLER => SDL_JOYSTICK_TYPE_GAMEPAD
+The following functions have been removed:
+* SDL_NumJoysticks - replaced with SDL_HasJoysticks() and SDL_GetJoysticks()
+* SDL_JoystickGetDeviceGUID() - replaced with SDL_GetJoystickInstanceGUID()
+* SDL_JoystickGetDeviceInstanceID()
+* SDL_JoystickGetDevicePlayerIndex() - replaced with SDL_GetJoystickInstancePlayerIndex()
+* SDL_JoystickGetDeviceProduct() - replaced with SDL_GetJoystickInstanceProduct()
+* SDL_JoystickGetDeviceProductVersion() - replaced with SDL_GetJoystickInstanceProductVersion()
+* SDL_JoystickGetDeviceType() - replaced with SDL_GetJoystickInstanceType()
+* SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickInstanceVendor()
+* SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickInstanceName()
+* SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickInstancePath()
+
## SDL_keycode.h
The following symbols have been renamed:
@@ -609,18 +647,36 @@ SDL_RWFromFP(void *fp, SDL_bool autoclose)
## SDL_sensor.h
+SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0.
+
+Rather than iterating over sensors using device index, there is a new function SDL_GetSensors() to get the current list of sensors, and new functions to get information about sensors from their instance ID:
+```c
+{
+ if (SDL_InitSubSystem(SDL_INIT_SENSOR) == 0) {
+ int i, num_sensors;
+ SDL_SensorID *sensors = SDL_GetSensors(&num_sensors);
+ if (sensors) {
+ for (i = 0; i < num_sensors; ++i) {
+ SDL_Log("Sensor %" SDL_PRIu32 ": %s, type %d, platform type %d\n",
+ sensors[i],
+ SDL_GetSensorInstanceName(sensors[i]),
+ SDL_GetSensorInstanceType(sensors[i]),
+ SDL_GetSensorInstanceNonPortableType(sensors[i]));
+ }
+ SDL_free(sensors);
+ }
+ SDL_QuitSubSystem(SDL_INIT_SENSOR);
+ }
+}
+```
+
Removed SDL_SensorGetDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_SENSORUPDATE events.
The following functions have been renamed:
-* SDL_NumSensors => SDL_GetNumSensors
* SDL_SensorClose => SDL_CloseSensor
* SDL_SensorFromInstanceID => SDL_GetSensorFromInstanceID
* SDL_SensorGetData => SDL_GetSensorData
-* SDL_SensorGetDeviceInstanceID => SDL_GetSensorDeviceInstanceID
-* SDL_SensorGetDeviceName => SDL_GetSensorDeviceName
-* SDL_SensorGetDeviceNonPortableType => SDL_GetSensorDeviceNonPortableType
-* SDL_SensorGetDeviceType => SDL_GetSensorDeviceType
* SDL_SensorGetInstanceID => SDL_GetSensorInstanceID
* SDL_SensorGetName => SDL_GetSensorName
* SDL_SensorGetNonPortableType => SDL_GetSensorNonPortableType
@@ -628,6 +684,15 @@ The following functions have been renamed:
* SDL_SensorOpen => SDL_OpenSensor
* SDL_SensorUpdate => SDL_UpdateSensors
+The following functions have been removed:
+* SDL_LockSensors()
+* SDL_NumSensors - replaced with SDL_HasSensors() and SDL_GetSensors()
+* SDL_SensorGetDeviceInstanceID()
+* SDL_SensorGetDeviceName() - replaced with SDL_GetSensorInstanceName()
+* SDL_SensorGetDeviceNonPortableType() - replaced with SDL_GetSensorInstanceNonPortableType()
+* SDL_SensorGetDeviceType() - replaced with SDL_GetSensorInstanceType()
+* SDL_UnlockSensors()
+
## SDL_stdinc.h
The standard C headers like stdio.h and stdlib.h are no longer included, you should include them directly in your project if you use non-SDL C runtime functions.
diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index 94f1bd782451..44923e1ec618 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -397,7 +397,7 @@ typedef struct SDL_JoyDeviceEvent
{
Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
- SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
+ SDL_JoystickID which; /**< The joystick instance id */
} SDL_JoyDeviceEvent;
/**
@@ -450,7 +450,7 @@ typedef struct SDL_GamepadDeviceEvent
{
Uint32 type; /**< ::SDL_GAMEPADADDED, ::SDL_GAMEPADREMOVED, or ::SDL_GAMEPADDEVICEREMAPPED */
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
- SDL_JoystickID which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
+ SDL_JoystickID which; /**< The joystick instance id */
} SDL_GamepadDeviceEvent;
/**
diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h
index a22adb4bc8f3..ba84ada1b732 100644
--- a/include/SDL3/SDL_gamepad.h
+++ b/include/SDL3/SDL_gamepad.h
@@ -181,7 +181,7 @@ typedef struct SDL_GamepadBinding
* \sa SDL_GetGamepadMapping
* \sa SDL_GetGamepadMappingForGUID
*/
-extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char* mappingString);
+extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mappingString);
/**
* Load a set of Game Controller mappings from a seekable SDL data stream.
@@ -211,7 +211,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char* mappingString);
* \sa SDL_AddGamepadMappingsFromFile
* \sa SDL_GetGamepadMappingForGUID
*/
-extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops * rw, int freerw);
+extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *rw, int freerw);
/**
* Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
@@ -250,7 +250,7 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForIndex(int mapping_index);
*
* \since This function is available since SDL 3.0.0.
*
- * \sa SDL_GetJoystickDeviceGUID
+ * \sa SDL_GetJoystickInstanceGUID
* \sa SDL_GetJoystickGUID
*/
extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForGUID(SDL_JoystickGUID guid);
@@ -275,13 +275,32 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForGUID(SDL_JoystickGUID gui
extern DECLSPEC char * SDLCALL SDL_GetGamepadMapping(SDL_Gamepad *gamepad);
/**
- * Check if the given joystick is supported by the gamepad interface.
+ * Return whether there are gamepads connected
+ *
+ * \returns SDL_TRUE if there are gamepads connected, SDL_FALSE otherwise.
*
- * `joystick_index` is the same as the `device_index` passed to
- * SDL_OpenJoystick().
+ * \since This function is available since SDL 3.0.0.
*
- * \param joystick_index the device_index of a device, up to
- * SDL_GetNumJoysticks()
+ * \sa SDL_GetGamepads
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasGamepads(void);
+
+/**
+ * Get a list of currently connected gamepads.
+ *
+ * \param count a pointer filled in with the number of gamepads returned
+ * \returns a 0 terminated array of joystick instance IDs which should be freed with SDL_free(), or NULL on error; call SDL_GetError() for more details.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenGamepad
+ */
+extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetGamepads(int *count);
+
+/**
+ * Check if the given joystick is supported by the gamepad interface.
+ *
+ * \param instance_id the joystick instance ID
* \returns SDL_TRUE if the given joystick is supported by the gamepad
* interface, SDL_FALSE if it isn't or it's an invalid index.
*
@@ -290,88 +309,142 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMapping(SDL_Gamepad *gamepad);
* \sa SDL_GetGamepadNameForIndex
* \sa SDL_OpenGamepad
*/
-extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepad(int joystick_index);
+extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepad(SDL_JoystickID instance_id);
/**
- * Get the implementation dependent name for the gamepad.
- *
- * This function can be called before any gamepads are opened.
+ * Get the implementation dependent name of a gamepad.
*
- * `joystick_index` is the same as the `device_index` passed to
- * SDL_OpenJoystick().
+ * This can be called before any gamepads are opened.
*
- * \param joystick_index the device_index of a device, from zero to
- * SDL_GetNumJoysticks()-1
- * \returns the implementation-dependent name for the gamepad, or NULL
- * if there is no name or the index is invalid.
+ * \param instance_id the joystick instance ID
+ * \returns the name of the selected gamepad. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetGamepadName
* \sa SDL_OpenGamepad
- * \sa SDL_IsGamepad
*/
-extern DECLSPEC const char *SDLCALL SDL_GetGamepadNameForIndex(int joystick_index);
+extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstanceName(SDL_JoystickID instance_id);
/**
- * Get the implementation dependent path for the gamepad.
+ * Get the implementation dependent path of a gamepad.
*
- * This function can be called before any gamepads are opened.
- *
- * `joystick_index` is the same as the `device_index` passed to
- * SDL_OpenJoystick().
+ * This can be called before any gamepads are opened.
*
- * \param joystick_index the device_index of a device, from zero to
- * SDL_GetNumJoysticks()-1
- * \returns the implementation-dependent path for the gamepad, or NULL
- * if there is no path or the index is invalid.
+ * \param instance_id the joystick instance ID
+ * \returns the path of the selected gamepad. If no path can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetGamepadPath
+ * \sa SDL_OpenGamepad
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstancePath(SDL_JoystickID instance_id);
+
+/**
+ * Get the player index of a gamepad.
+ *
+ * This can be called before any gamepads are opened.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the player index of a gamepad, or -1 if it's not available
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetGamepadPlayerIndex
+ * \sa SDL_OpenGamepad
*/
-extern DECLSPEC const char *SDLCALL SDL_GetGamepadPathForIndex(int joystick_index);
+extern DECLSPEC int SDLCALL SDL_GetGamepadInstancePlayerIndex(SDL_JoystickID instance_id);
+
+/**
+ * Get the implementation-dependent GUID of a gamepad.
+ *
+ * This can be called before any gamepads are opened.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the GUID of the selected gamepad. If called on an invalid index,
+ * this function returns a zero GUID
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetGamepadGUID
+ * \sa SDL_GetGamepadGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetGamepadInstanceGUID(SDL_JoystickID instance_id);
+
+/**
+ * Get the USB vendor ID of a gamepad, if available.
+ *
+ * This can be called before any gamepads are opened. If the vendor ID isn't
+ * available this function returns 0.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the USB vendor ID of the selected gamepad. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceVendor(SDL_JoystickID instance_id);
+
+/**
+ * Get the USB product ID of a gamepad, if available.
+ *
+ * This can be called before any gamepads are opened. If the product ID isn't
+ * available this function returns 0.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the USB product ID of the selected gamepad. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProduct(SDL_JoystickID instance_id);
+
+/**
+ * Get the product version of a gamepad, if available.
+ *
+ * This can be called before any gamepads are opened. If the product version
+ * isn't available this function returns 0.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the product version of the selected gamepad. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProductVersion(SDL_JoystickID instance_id);
/**
* Get the type of a gamepad.
*
* This can be called before any gamepads are opened.
*
- * \param joystick_index the device_index of a device, from zero to
- * SDL_GetNumJoysticks()-1
+ * \param instance_id the joystick instance ID
* \returns the gamepad type.
*
* \since This function is available since SDL 3.0.0.
*/
-extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeForIndex(int joystick_index);
+extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadInstanceType(SDL_JoystickID instance_id);
/**
* Get the mapping of a gamepad.
*
* This can be called before any gamepads are opened.
*
- * \param joystick_index the device_index of a device, from zero to
- * SDL_GetNumJoysticks()-1
+ * \param instance_id the joystick instance ID
* \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
* no mapping is available.
*
* \since This function is available since SDL 3.0.0.
*/
-extern DECLSPEC char *SDLCALL SDL_GetGamepadMappingForDeviceIndex(int joystick_index);
+extern DECLSPEC char *SDLCALL SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id);
/**
* Open a gamepad for use.
*
- * `joystick_index` is the same as the `device_index` passed to
- * SDL_OpenJoystick().
- *
- * The index passed as an argument refers to the N'th gamepad on the
- * system. This index is not the value which will identify this gamepad in
- * future gamepad events. The joystick's instance id (SDL_JoystickID) will
- * be used there instead.
- *
- * \param joystick_index the device_index of a device, up to
- * SDL_GetNumJoysticks()
+ * \param instance_id the joystick instance ID
* \returns a gamepad identifier or NULL if an error occurred; call
* SDL_GetError() for more information.
*
@@ -381,27 +454,23 @@ extern DECLSPEC char *SDLCALL SDL_GetGamepadMappingForDeviceIndex(int joystick_i
* \sa SDL_GetGamepadNameForIndex
* \sa SDL_IsGamepad
*/
-extern DECLSPEC SDL_Gamepad *SDLCALL SDL_OpenGamepad(int joystick_index);
+extern DECLSPEC SDL_Gamepad *SDLCALL SDL_OpenGamepad(SDL_JoystickID instance_id);
/**
- * Get the SDL_Gamepad associated with an instance id.
+ * Get the SDL_Gamepad associated with a joystick instance ID.
*
- * \param joyid the instance id to get the SDL_Gamepad for
+ * \param instance_id the joystick instance ID of the gamepad
* \returns an SDL_Gamepad on success or NULL on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
-extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromInstanceID(SDL_JoystickID joyid);
+extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromInstanceID(SDL_JoystickID instance_id);
/**
* Get the SDL_Gamepad associated with a player index.
*
- * Please note that the player index is _not_ the device index, nor is it the
- * instance id!
- *
- * \param player_index the player index, which is not the device index or the
- * instance id!
+ * \param player_index the player index, which different from the instance ID
* \returns the SDL_Gamepad associated with a player index.
*
* \since This function is available since SDL 3.0.0.
@@ -442,14 +511,14 @@ extern DECLSPEC const char *SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad);
*
* \since This function is available since SDL 3.0.0.
*
- * \sa SDL_GetGamepadPathForIndex
+ * \sa SDL_GetGamepadInstancePath
*/
extern DECLSPEC const char *SDLCALL SDL_GetGamepadPath(SDL_Gamepad *gamepad);
/**
* Get the type of this currently opened gamepad
*
- * This is the same name as returned by SDL_GetGamepadTypeForIndex(), but
+ * This is the same name as returned by SDL_GetGamepadInstanceType(), but
* it takes a gamepad identifier instead of the (unstable) device index.
*
* \param gamepad the gamepad object to query.
@@ -559,7 +628,7 @@ extern DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamepad);
extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepadConnected(SDL_Gamepad *gamepad);
/**
- * Get the Joystick ID from a Game Controller.
+ * Get the underlying joystick from a gamepad
*
* This function will give you a SDL_Joystick object, which allows you to use
* the SDL_Joystick functions with a SDL_Gamepad object. This would be
@@ -573,7 +642,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepadConnected(SDL_Gamepad *gamepad);
*
* \param gamepad the gamepad object that you want to get a
* joystick from
- * \returns a SDL_Joystick object; call SDL_GetError() for more information.
+ * \returns an SDL_Joystick object; call SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*/
diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h
index f212e8c379d6..75d3ec418d65 100644
--- a/include/SDL3/SDL_joystick.h
+++ b/include/SDL3/SDL_joystick.h
@@ -24,9 +24,6 @@
*
* Include file for SDL joystick event handling
*
- * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_GetNumJoysticks(), with the exact joystick
- * behind a device_index changing as joysticks are plugged and unplugged.
- *
* The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
* then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
*
@@ -81,9 +78,9 @@ typedef SDL_GUID SDL_JoystickGUID;
* and is never reused for the lifetime of the application. If the joystick is
* disconnected and reconnected, it will get a new ID.
*
- * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ * The ID value starts at 1 and increments from there. The value 0 is an invalid ID.
*/
-typedef Sint32 SDL_JoystickID;
+typedef Uint32 SDL_JoystickID;
typedef enum
{
@@ -119,60 +116,52 @@ typedef enum
/* Function prototypes */
/**
- * Locking for multi-threaded access to the joystick API
- *
- * If you are using the joystick API or handling events from multiple threads
- * you should use these locking functions to protect access to the joysticks.
+ * Locking for atomic access to the joystick API
*
- * In particular, you are guaranteed that the joystick list won't change, so
- * the API functions that take a joystick index will be valid, and joystick
- * and game controller events will not be delivered.
- *
- * As of SDL 2.26.0, you can take the joystick lock around reinitializing the
- * joystick subsystem, to prevent other threads from seeing joysticks in an
- * uninitialized state. However, all open joysticks will be closed and SDL
- * functions called with them will fail.
+ * The SDL joystick functions are thread-safe, however you can lock the joysticks
+ * while processing to guarantee that the joystick list won't change and joystick
+ * and gamepad events will not be delivered.
*
* \since This function is available since SDL 3.0.0.
*/
extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock);
-
/**
- * Unlocking for multi-threaded access to the joystick API
+ * Unlocking for atomic access to the joystick API
*
- * If you are using the joystick API or handling events from multiple threads
- * you should use these locking functions to protect access to the joysticks.
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock);
+
+/**
+ * Return whether there are joysticks connected
*
- * In particular, you are guaranteed that the joystick list won't change, so
- * the API functions that take a joystick index will be valid, and joystick
- * and game controller events will not be delivered.
+ * \returns SDL_TRUE if there are joysticks connected, SDL_FALSE otherwise.
*
* \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetJoysticks
*/
-extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock);
+extern DECLSPEC SDL_bool SDLCALL SDL_HasJoysticks(void);
/**
- * Count the number of joysticks attached to the system.
+ * Get a list of currently connected joysticks.
*
- * \returns the
(Patch may be truncated, please check the link at the top of this post.)