Browse Source

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
Sam Lantinga 2 years ago
parent
commit
16092f58bb

+ 3 - 0
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

+ 85 - 20
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.

+ 2 - 2
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;
 
 /**

+ 128 - 59
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.
  */

+ 65 - 98
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 number of attached joysticks on success or a negative error
- *          code on failure; call SDL_GetError() for more information.
+ * \param count a pointer filled in with the number of joysticks 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_GetJoystickName
- * \sa SDL_GetJoystickPath
  * \sa SDL_OpenJoystick
  */
-extern DECLSPEC int SDLCALL SDL_GetNumJoysticks(void);
+extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetJoysticks(int *count);
 
 /**
  * Get the implementation dependent name of a joystick.
  *
  * This can be called before any joysticks are opened.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system)
+ * \param instance_id the joystick instance ID
  * \returns the name of the selected joystick. If no name can be found, this
  *          function returns NULL; call SDL_GetError() for more information.
  *
@@ -181,15 +170,14 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoysticks(void);
  * \sa SDL_GetJoystickName
  * \sa SDL_OpenJoystick
  */
-extern DECLSPEC const char *SDLCALL SDL_GetJoystickNameForIndex(int device_index);
+extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_JoystickID instance_id);
 
 /**
  * Get the implementation dependent path of a joystick.
  *
  * This can be called before any joysticks are opened.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system)
+ * \param instance_id the joystick instance ID
  * \returns the path of the selected joystick. If no path can be found, this
  *          function returns NULL; call SDL_GetError() for more information.
  *
@@ -198,24 +186,29 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickNameForIndex(int device_index
  * \sa SDL_GetJoystickPath
  * \sa SDL_OpenJoystick
  */
-extern DECLSPEC const char *SDLCALL SDL_GetJoystickPathForIndex(int device_index);
+extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstancePath(SDL_JoystickID instance_id);
 
 /**
- * Get the player index of a joystick, or -1 if it's not available This can be
- * called before any joysticks are opened.
+ * Get the player index of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param instance_id the joystick instance ID
+ * \returns the player index of a joystick, or -1 if it's not available
  *
  * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetJoystickPlayerIndex
+ * \sa SDL_OpenJoystick
  */
-extern DECLSPEC int SDLCALL SDL_GetJoystickDevicePlayerIndex(int device_index);
+extern DECLSPEC int SDLCALL SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID instance_id);
 
 /**
- * Get the implementation-dependent GUID for the joystick at a given device
- * index.
+ * Get the implementation-dependent GUID of a joystick.
  *
- * This function can be called before any joysticks are opened.
+ * This can be called before any joysticks are opened.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
+ * \param instance_id the joystick instance ID
  * \returns the GUID of the selected joystick. If called on an invalid index,
  *          this function returns a zero GUID
  *
@@ -224,7 +217,7 @@ extern DECLSPEC int SDLCALL SDL_GetJoystickDevicePlayerIndex(int device_index);
  * \sa SDL_GetJoystickGUID
  * \sa SDL_GetJoystickGUIDString
  */
-extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickDeviceGUID(int device_index);
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickInstanceGUID(SDL_JoystickID instance_id);
 
 /**
  * Get the USB vendor ID of a joystick, if available.
@@ -232,14 +225,13 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickDeviceGUID(int device_in
  * This can be called before any joysticks are opened. If the vendor ID isn't
  * available this function returns 0.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
+ * \param instance_id the joystick instance ID
  * \returns the USB vendor ID of the selected joystick. 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_GetJoystickDeviceVendor(int device_index);
+extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id);
 
 /**
  * Get the USB product ID of a joystick, if available.
@@ -247,14 +239,13 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickDeviceVendor(int device_index);
  * This can be called before any joysticks are opened. If the product ID isn't
  * available this function returns 0.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
+ * \param instance_id the joystick instance ID
  * \returns the USB product ID of the selected joystick. 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_GetJoystickDeviceProduct(int device_index);
+extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id);
 
 /**
  * Get the product version of a joystick, if available.
@@ -262,70 +253,47 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickDeviceProduct(int device_index);
  * This can be called before any joysticks are opened. If the product version
  * isn't available this function returns 0.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
+ * \param instance_id the joystick instance ID
  * \returns the product version of the selected joystick. 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_GetJoystickDeviceProductVersion(int device_index);
+extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProductVersion(SDL_JoystickID instance_id);
 
 /**
  * Get the type of a joystick, if available.
  *
  * This can be called before any joysticks are opened.
  *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
+ * \param instance_id the joystick instance ID
  * \returns the SDL_JoystickType of the selected joystick. If called on an
  *          invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN`
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickDeviceType(int device_index);
-
-/**
- * Get the instance ID of a joystick.
- *
- * This can be called before any joysticks are opened. If the index is out of
- * range, this function will return -1.
- *
- * \param device_index the index of the joystick to query (the N'th joystick
- *                     on the system
- * \returns the instance id of the selected joystick. If called on an invalid
- *          index, this function returns zero
- *
- * \since This function is available since SDL 3.0.0.
- */
-extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickDeviceInstanceID(int device_index);
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickInstanceType(SDL_JoystickID instance_id);
 
 /**
  * Open a joystick for use.
  *
- * The `device_index` argument refers to the N'th joystick presently
- * recognized by SDL on the system. It is **NOT** the same as the instance ID
- * used to identify the joystick in future events. See
- * SDL_GetJoystickInstanceID() for more details about instance IDs.
- *
  * The joystick subsystem must be initialized before a joystick can be opened
  * for use.
  *
- * \param device_index the index of the joystick to query
+ * \param instance_id the joystick instance ID
  * \returns a joystick identifier or NULL if an error occurred; call
  *          SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  *
  * \sa SDL_CloseJoystick
- * \sa SDL_GetJoystickInstanceID
  */
-extern DECLSPEC SDL_Joystick *SDLCALL SDL_OpenJoystick(int device_index);
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_OpenJoystick(SDL_JoystickID instance_id);
 
 /**
- * Get the SDL_Joystick associated with an instance id.
+ * Get the SDL_Joystick associated with an instance ID.
  *
- * \param instance_id the instance id to get the SDL_Joystick for
+ * \param instance_id the instance ID to get the SDL_Joystick for
  * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
  *          for more information.
  *
@@ -347,11 +315,11 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromPlayerIndex(int player_
 /**
  * Attach a new virtual joystick.
  *
- * \returns the joystick's device index, or -1 if an error occurred.
+ * \returns the joystick instance ID, or 0 if an error occurred; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC int SDLCALL SDL_AttachVirtualJoystick(SDL_JoystickType type,
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(SDL_JoystickType type,
                                                       int naxes,
                                                       int nbuttons,
                                                       int nhats);
@@ -398,32 +366,31 @@ typedef struct SDL_VirtualJoystickDesc
 /**
  * Attach a new virtual joystick with extended properties.
  *
- * \returns the joystick's device index, or -1 if an error occurred.
+ * \returns the joystick instance ID, or 0 if an error occurred; call SDL_GetError() for more information.
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC int SDLCALL SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc);
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc);
 
 /**
  * Detach a virtual joystick.
  *
- * \param device_index a value previously returned from
- *                     SDL_AttachVirtualJoystick()
+ * \param instance_id the joystick instance ID, previously returned from SDL_AttachVirtualJoystick()
  * \returns 0 on success, or -1 if an error occurred.
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC int SDLCALL SDL_DetachVirtualJoystick(int device_index);
+extern DECLSPEC int SDLCALL SDL_DetachVirtualJoystick(SDL_JoystickID instance_id);
 
 /**
- * Query whether or not the joystick at a given device index is virtual.
+ * Query whether or not a joystick is virtual.
  *
- * \param device_index a joystick device index.
+ * \param instance_id the joystick instance ID
  * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise.
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickVirtual(int device_index);
+extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_id);
 
 /**
  * Set values on an opened, virtual-joystick's axis.
@@ -492,7 +459,7 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, in
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetJoystickNameForIndex
+ * \sa SDL_GetJoystickInstanceName
  * \sa SDL_OpenJoystick
  */
 extern DECLSPEC const char *SDLCALL SDL_GetJoystickName(SDL_Joystick *joystick);
@@ -506,7 +473,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickName(SDL_Joystick *joystick);
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetJoystickPathForIndex
+ * \sa SDL_GetJoystickInstancePath
  */
 extern DECLSPEC const char *SDLCALL SDL_GetJoystickPath(SDL_Joystick *joystick);
 
@@ -546,7 +513,7 @@ extern DECLSPEC void SDLCALL SDL_SetJoystickPlayerIndex(SDL_Joystick *joystick,
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetJoystickDeviceGUID
+ * \sa SDL_GetJoystickInstanceGUID
  * \sa SDL_GetJoystickGUIDString
  */
 extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickGUID(SDL_Joystick *joystick);
@@ -634,7 +601,7 @@ extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickType(SDL_Joystick *joyst
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetJoystickDeviceGUID
+ * \sa SDL_GetJoystickInstanceGUID
  * \sa SDL_GetJoystickGUID
  * \sa SDL_GetJoystickGUIDFromString
  */
@@ -671,7 +638,7 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickGUIDFromString(const cha
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_GetJoystickDeviceGUID
+ * \sa SDL_GetJoystickInstanceGUID
  */
 extern DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16);
 

+ 0 - 19
include/SDL3/SDL_oldnames.h

@@ -160,15 +160,12 @@
 #define SDL_GameControllerHasSensor SDL_GamepadHasSensor
 #define SDL_GameControllerIsSensorEnabled SDL_IsGamepadSensorEnabled
 #define SDL_GameControllerMapping SDL_GetGamepadMapping
-#define SDL_GameControllerMappingForDeviceIndex SDL_GetGamepadMappingForDeviceIndex
 #define SDL_GameControllerMappingForGUID SDL_GetGamepadMappingForGUID
 #define SDL_GameControllerMappingForIndex SDL_GetGamepadMappingForIndex
 #define SDL_GameControllerName SDL_GetGamepadName
-#define SDL_GameControllerNameForIndex SDL_GetGamepadNameForIndex
 #define SDL_GameControllerNumMappings SDL_GetNumGamepadMappings
 #define SDL_GameControllerOpen SDL_OpenGamepad
 #define SDL_GameControllerPath SDL_GetGamepadPath
-#define SDL_GameControllerPathForIndex SDL_GetGamepadPathForIndex
 #define SDL_GameControllerRumble SDL_RumbleGamepad
 #define SDL_GameControllerRumbleTriggers SDL_RumbleGamepadTriggers
 #define SDL_GameControllerSendEffect SDL_SendGamepadEffect
@@ -176,7 +173,6 @@
 #define SDL_GameControllerSetPlayerIndex SDL_SetGamepadPlayerIndex
 #define SDL_GameControllerSetSensorEnabled SDL_SetGamepadSensorEnabled
 #define SDL_GameControllerType SDL_GamepadType
-#define SDL_GameControllerTypeForIndex SDL_GetGamepadTypeForIndex
 #define SDL_GameControllerUpdate SDL_UpdateGamepads
 #define SDL_INIT_GAMECONTROLLER SDL_INIT_GAMEPAD
 #define SDL_IsGameController SDL_IsGamepad
@@ -195,13 +191,6 @@
 #define SDL_JoystickGetAxis SDL_GetJoystickAxis
 #define SDL_JoystickGetAxisInitialState SDL_GetJoystickAxisInitialState
 #define SDL_JoystickGetButton SDL_GetJoystickButton
-#define SDL_JoystickGetDeviceGUID SDL_GetJoystickDeviceGUID
-#define SDL_JoystickGetDeviceInstanceID SDL_GetJoystickDeviceInstanceID
-#define SDL_JoystickGetDevicePlayerIndex SDL_GetJoystickDevicePlayerIndex
-#define SDL_JoystickGetDeviceProduct SDL_GetJoystickDeviceProduct
-#define SDL_JoystickGetDeviceProductVersion SDL_GetJoystickDeviceProductVersion
-#define SDL_JoystickGetDeviceType SDL_GetJoystickDeviceType
-#define SDL_JoystickGetDeviceVendor SDL_GetJoystickDeviceVendor
 #define SDL_JoystickGetFirmwareVersion SDL_GetJoystickFirmwareVersion
 #define SDL_JoystickGetGUID SDL_GetJoystickGUID
 #define SDL_JoystickGetGUIDFromString SDL_GetJoystickGUIDFromString
@@ -216,13 +205,11 @@
 #define SDL_JoystickInstanceID SDL_GetJoystickInstanceID
 #define SDL_JoystickIsVirtual SDL_IsJoystickVirtual
 #define SDL_JoystickName SDL_GetJoystickName
-#define SDL_JoystickNameForIndex SDL_GetJoystickNameForIndex
 #define SDL_JoystickNumAxes SDL_GetNumJoystickAxes
 #define SDL_JoystickNumButtons SDL_GetNumJoystickButtons
 #define SDL_JoystickNumHats SDL_GetNumJoystickHats
 #define SDL_JoystickOpen SDL_OpenJoystick
 #define SDL_JoystickPath SDL_GetJoystickPath
-#define SDL_JoystickPathForIndex SDL_GetJoystickPathForIndex
 #define SDL_JoystickRumble SDL_RumbleJoystick
 #define SDL_JoystickRumbleTriggers SDL_RumbleJoystickTriggers
 #define SDL_JoystickSendEffect SDL_SendJoystickEffect
@@ -557,7 +544,6 @@
 #define SDL_JoystickSetVirtualButton SDL_JoystickSetVirtualButton_renamed_SDL_SetJoystickVirtualButton
 #define SDL_JoystickSetVirtualHat SDL_JoystickSetVirtualHat_renamed_SDL_SetJoystickVirtualHat
 #define SDL_JoystickUpdate SDL_JoystickUpdate_renamed_SDL_UpdateJoysticks
-#define SDL_NumJoysticks SDL_NumJoysticks_renamed_SDL_GetNumJoysticks
 
 /* ##SDL_keycode.h */
 #define KMOD_ALT KMOD_ALT_renamed_SDL_KMOD_ALT
@@ -653,14 +639,9 @@
 #define RW_SEEK_SET RW_SEEK_SET_renamed_SDL_RW_SEEK_SET
 
 /* ##SDL_sensor.h */
-#define SDL_NumSensors SDL_NumSensors_renamed_SDL_GetNumSensors
 #define SDL_SensorClose SDL_SensorClose_renamed_SDL_CloseSensor
 #define SDL_SensorFromInstanceID SDL_SensorFromInstanceID_renamed_SDL_GetSensorFromInstanceID
 #define SDL_SensorGetData SDL_SensorGetData_renamed_SDL_GetSensorData
-#define SDL_SensorGetDeviceInstanceID SDL_SensorGetDeviceInstanceID_renamed_SDL_GetSensorDeviceInstanceID
-#define SDL_SensorGetDeviceName SDL_SensorGetDeviceName_renamed_SDL_GetSensorDeviceName
-#define SDL_SensorGetDeviceNonPortableType SDL_SensorGetDeviceNonPortableType_renamed_SDL_GetSensorDeviceNonPortableType
-#define SDL_SensorGetDeviceType SDL_SensorGetDeviceType_renamed_SDL_GetSensorDeviceType
 #define SDL_SensorGetInstanceID SDL_SensorGetInstanceID_renamed_SDL_GetSensorInstanceID
 #define SDL_SensorGetName SDL_SensorGetName_renamed_SDL_GetSensorName
 #define SDL_SensorGetNonPortableType SDL_SensorGetNonPortableType_renamed_SDL_GetSensorNonPortableType

+ 26 - 41
include/SDL3/SDL_sensor.h

@@ -55,9 +55,9 @@ typedef struct SDL_Sensor SDL_Sensor;
  * This is a unique ID for a sensor for the time it is connected to the system,
  * and is never reused for the lifetime of the application.
  *
- * 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_SensorID;
+typedef Uint32 SDL_SensorID;
 
 /* The different sensors defined by SDL
  *
@@ -95,7 +95,7 @@ typedef enum
  * -X ... +X : left ... right
  * -Y ... +Y : bottom ... top
  * -Z ... +Z : farther ... closer
- * 
+ *
  * The axis data is not changed when the phone is rotated.
  *
  * \sa SDL_GetDisplayOrientation()
@@ -120,7 +120,7 @@ typedef enum
  * -X ... +X : left ... right
  * -Y ... +Y : bottom ... top
  * -Z ... +Z : farther ... closer
- * 
+ *
  * The axis data is not changed when the phone or controller is rotated.
  *
  * \sa SDL_GetDisplayOrientation()
@@ -129,85 +129,70 @@ typedef enum
 /* Function prototypes */
 
 /**
- * Locking for multi-threaded access to the sensor API
- *
- * If you are using the sensor API or handling events from multiple threads
- * you should use these locking functions to protect access to the sensors.
+ * Return whether there are sensors connected
  *
- * In particular, you are guaranteed that the sensor list won't change, so the
- * API functions that take a sensor index will be valid, and sensor events
- * will not be delivered.
+ * \returns SDL_TRUE if there are sensors connected, SDL_FALSE otherwise.
  *
  * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetSensors
  */
-extern DECLSPEC void SDLCALL SDL_LockSensors(void);
-extern DECLSPEC void SDLCALL SDL_UnlockSensors(void);
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSensors(void);
 
 /**
- * Count the number of sensors attached to the system right now.
+ * Get a list of currently connected sensors.
  *
- * \returns the number of sensors detected.
+ * \param count a pointer filled in with the number of sensors returned
+ * \returns a 0 terminated array of sensor 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.
  */
-extern DECLSPEC int SDLCALL SDL_GetNumSensors(void);
+extern DECLSPEC SDL_SensorID *SDLCALL SDL_GetSensors(int *count);
 
 /**
  * Get the implementation dependent name of a sensor.
  *
- * \param device_index The sensor to obtain name from
- * \returns the sensor name, or NULL if `device_index` is out of range.
+ * \param instance_id the sensor instance ID
+ * \returns the sensor name, or NULL if `instance_id` is not valid
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC const char *SDLCALL SDL_GetSensorDeviceName(int device_index);
+extern DECLSPEC const char *SDLCALL SDL_GetSensorInstanceName(SDL_SensorID instance_id);
 
 /**
  * Get the type of a sensor.
  *
- * \param device_index The sensor to get the type from
- * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `device_index` is
- *          out of range.
+ * \param instance_id the sensor instance ID
+ * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `instance_id` is not valid
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorDeviceType(int device_index);
+extern DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorInstanceType(SDL_SensorID instance_id);
 
 /**
  * Get the platform dependent type of a sensor.
  *
- * \param device_index The sensor to check
- * \returns the sensor platform dependent type, or -1 if `device_index` is out
- *          of range.
- *
- * \since This function is available since SDL 3.0.0.
- */
-extern DECLSPEC int SDLCALL SDL_GetSensorDeviceNonPortableType(int device_index);
-
-/**
- * Get the instance ID of a sensor.
- *
- * \param device_index The sensor to get instance id from
- * \returns the sensor instance ID, or -1 if `device_index` is out of range.
+ * \param instance_id the sensor instance ID
+ * \returns the sensor platform dependent type, or -1 if `instance_id` is not valid
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_SensorID SDLCALL SDL_GetSensorDeviceInstanceID(int device_index);
+extern DECLSPEC int SDLCALL SDL_GetSensorInstanceNonPortableType(SDL_SensorID instance_id);
 
 /**
  * Open a sensor for use.
  *
- * \param device_index The sensor to open
+ * \param instance_id the sensor instance ID
  * \returns an SDL_Sensor sensor object, or NULL if an error occurred.
  *
  * \since This function is available since SDL 3.0.0.
  */
-extern DECLSPEC SDL_Sensor *SDLCALL SDL_OpenSensor(int device_index);
+extern DECLSPEC SDL_Sensor *SDLCALL SDL_OpenSensor(SDL_SensorID instance_id);
 
 /**
- * Return the SDL_Sensor associated with an instance id.
+ * Return the SDL_Sensor associated with an instance ID.
  *
- * \param instance_id The sensor from instance id
+ * \param instance_id the sensor instance ID
  * \returns an SDL_Sensor object.
  *
  * \since This function is available since SDL 3.0.0.

+ 26 - 21
src/dynapi/SDL_dynapi.sym

@@ -649,13 +649,6 @@ SDL3_0.0.0 {
     SDL_GetErrorMsg;
     SDL_ClearError;
     SDL_Error;
-    SDL_LockSensors;
-    SDL_UnlockSensors;
-    SDL_GetNumSensors;
-    SDL_GetSensorDeviceName;
-    SDL_GetSensorDeviceType;
-    SDL_GetSensorDeviceNonPortableType;
-    SDL_GetSensorDeviceInstanceID;
     SDL_OpenSensor;
     SDL_GetSensorFromInstanceID;
     SDL_GetSensorName;
@@ -696,16 +689,6 @@ SDL3_0.0.0 {
     SDL_ComposeCustomBlendMode;
     SDL_LockJoysticks;
     SDL_UnlockJoysticks;
-    SDL_GetNumJoysticks;
-    SDL_GetJoystickNameForIndex;
-    SDL_GetJoystickPathForIndex;
-    SDL_GetJoystickDevicePlayerIndex;
-    SDL_GetJoystickDeviceGUID;
-    SDL_GetJoystickDeviceVendor;
-    SDL_GetJoystickDeviceProduct;
-    SDL_GetJoystickDeviceProductVersion;
-    SDL_GetJoystickDeviceType;
-    SDL_GetJoystickDeviceInstanceID;
     SDL_OpenJoystick;
     SDL_GetJoystickFromInstanceID;
     SDL_GetJoystickFromPlayerIndex;
@@ -761,10 +744,6 @@ SDL3_0.0.0 {
     SDL_GetGamepadMappingForGUID;
     SDL_GetGamepadMapping;
     SDL_IsGamepad;
-    SDL_GetGamepadNameForIndex;
-    SDL_GetGamepadPathForIndex;
-    SDL_GetGamepadTypeForIndex;
-    SDL_GetGamepadMappingForDeviceIndex;
     SDL_OpenGamepad;
     SDL_GetGamepadFromInstanceID;
     SDL_GetGamepadFromPlayerIndex;
@@ -854,6 +833,32 @@ SDL3_0.0.0 {
     SDL_GetEventState;
     SDL_GetRenderDriver;
     SDL_RunApp;
+    SDL_GetSensors;
+    SDL_GetSensorInstanceName;
+    SDL_GetSensorInstanceType;
+    SDL_GetSensorInstanceNonPortableType;
+    SDL_GetJoysticks;
+    SDL_GetJoystickInstanceName;
+    SDL_GetJoystickInstancePath;
+    SDL_GetJoystickInstancePlayerIndex;
+    SDL_GetJoystickInstanceGUID;
+    SDL_GetJoystickInstanceVendor;
+    SDL_GetJoystickInstanceProduct;
+    SDL_GetJoystickInstanceProductVersion;
+    SDL_GetJoystickInstanceType;
+    SDL_GetGamepadInstanceName;
+    SDL_GetGamepadInstancePath;
+    SDL_GetGamepadInstanceType;
+    SDL_GetGamepadInstanceMapping;
+    SDL_HasJoysticks;
+    SDL_HasSensors;
+    SDL_HasGamepads;
+    SDL_GetGamepads;
+    SDL_GetGamepadInstancePlayerIndex;
+    SDL_GetGamepadInstanceGUID;
+    SDL_GetGamepadInstanceVendor;
+    SDL_GetGamepadInstanceProduct;
+    SDL_GetGamepadInstanceProductVersion;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 26 - 21
src/dynapi/SDL_dynapi_overrides.h

@@ -130,7 +130,6 @@
 #define SDL_GetGamepadMappingForGUID SDL_GetGamepadMappingForGUID_REAL
 #define SDL_GetGamepadMapping SDL_GetGamepadMapping_REAL
 #define SDL_IsGamepad SDL_IsGamepad_REAL
-#define SDL_GetGamepadNameForIndex SDL_GetGamepadNameForIndex_REAL
 #define SDL_OpenGamepad SDL_OpenGamepad_REAL
 #define SDL_GetGamepadName SDL_GetGamepadName_REAL
 #define SDL_IsGamepadConnected SDL_IsGamepadConnected_REAL
@@ -182,11 +181,8 @@
 #define SDL_AddHintCallback SDL_AddHintCallback_REAL
 #define SDL_DelHintCallback SDL_DelHintCallback_REAL
 #define SDL_ClearHints SDL_ClearHints_REAL
-#define SDL_GetNumJoysticks SDL_GetNumJoysticks_REAL
-#define SDL_GetJoystickNameForIndex SDL_GetJoystickNameForIndex_REAL
 #define SDL_OpenJoystick SDL_OpenJoystick_REAL
 #define SDL_GetJoystickName SDL_GetJoystickName_REAL
-#define SDL_GetJoystickDeviceGUID SDL_GetJoystickDeviceGUID_REAL
 #define SDL_GetJoystickGUID SDL_GetJoystickGUID_REAL
 #define SDL_GetJoystickGUIDString SDL_GetJoystickGUIDString_REAL
 #define SDL_GetJoystickGUIDFromString SDL_GetJoystickGUIDFromString_REAL
@@ -578,9 +574,6 @@
 #define SDL_CreateSurface SDL_CreateSurface_REAL
 #define SDL_CreateSurfaceFrom SDL_CreateSurfaceFrom_REAL
 #define SDL_GetHintBoolean SDL_GetHintBoolean_REAL
-#define SDL_GetJoystickDeviceVendor SDL_GetJoystickDeviceVendor_REAL
-#define SDL_GetJoystickDeviceProduct SDL_GetJoystickDeviceProduct_REAL
-#define SDL_GetJoystickDeviceProductVersion SDL_GetJoystickDeviceProductVersion_REAL
 #define SDL_GetJoystickVendor SDL_GetJoystickVendor_REAL
 #define SDL_GetJoystickProduct SDL_GetJoystickProduct_REAL
 #define SDL_GetJoystickProductVersion SDL_GetJoystickProductVersion_REAL
@@ -591,11 +584,9 @@
 #define SDL_GetNumGamepadMappings SDL_GetNumGamepadMappings_REAL
 #define SDL_GetGamepadMappingForIndex SDL_GetGamepadMappingForIndex_REAL
 #define SDL_GetJoystickAxisInitialState SDL_GetJoystickAxisInitialState_REAL
-#define SDL_GetJoystickDeviceType SDL_GetJoystickDeviceType_REAL
 #define SDL_GetJoystickType SDL_GetJoystickType_REAL
 #define SDL_MemoryBarrierReleaseFunction SDL_MemoryBarrierReleaseFunction_REAL
 #define SDL_MemoryBarrierAcquireFunction SDL_MemoryBarrierAcquireFunction_REAL
-#define SDL_GetJoystickDeviceInstanceID SDL_GetJoystickDeviceInstanceID_REAL
 #define SDL_utf8strlen SDL_utf8strlen_REAL
 #define SDL_LoadFile_RW SDL_LoadFile_RW_REAL
 #define SDL_wcscmp SDL_wcscmp_REAL
@@ -641,7 +632,6 @@
 #define SDL_WinRTGetDeviceFamily SDL_WinRTGetDeviceFamily_REAL
 #define SDL_log10 SDL_log10_REAL
 #define SDL_log10f SDL_log10f_REAL
-#define SDL_GetGamepadMappingForDeviceIndex SDL_GetGamepadMappingForDeviceIndex_REAL
 #define SDL_LinuxSetThreadPriority SDL_LinuxSetThreadPriority_REAL
 #define SDL_HasAVX512F SDL_HasAVX512F_REAL
 #define SDL_IsChromebook SDL_IsChromebook_REAL
@@ -652,11 +642,6 @@
 #define SDL_wcsdup SDL_wcsdup_REAL
 #define SDL_RumbleGamepad SDL_RumbleGamepad_REAL
 #define SDL_RumbleJoystick SDL_RumbleJoystick_REAL
-#define SDL_GetNumSensors SDL_GetNumSensors_REAL
-#define SDL_GetSensorDeviceName SDL_GetSensorDeviceName_REAL
-#define SDL_GetSensorDeviceType SDL_GetSensorDeviceType_REAL
-#define SDL_GetSensorDeviceNonPortableType SDL_GetSensorDeviceNonPortableType_REAL
-#define SDL_GetSensorDeviceInstanceID SDL_GetSensorDeviceInstanceID_REAL
 #define SDL_OpenSensor SDL_OpenSensor_REAL
 #define SDL_GetSensorFromInstanceID SDL_GetSensorFromInstanceID_REAL
 #define SDL_GetSensorName SDL_GetSensorName_REAL
@@ -670,7 +655,6 @@
 #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL
 #define SDL_SurfaceHasColorKey SDL_SurfaceHasColorKey_REAL
 #define SDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize_REAL
-#define SDL_GetJoystickDevicePlayerIndex SDL_GetJoystickDevicePlayerIndex_REAL
 #define SDL_GetJoystickPlayerIndex SDL_GetJoystickPlayerIndex_REAL
 #define SDL_GetGamepadPlayerIndex SDL_GetGamepadPlayerIndex_REAL
 #define SDL_RenderFlush SDL_RenderFlush_REAL
@@ -702,7 +686,6 @@
 #define SDL_strtokr SDL_strtokr_REAL
 #define SDL_wcsstr SDL_wcsstr_REAL
 #define SDL_wcsncmp SDL_wcsncmp_REAL
-#define SDL_GetGamepadTypeForIndex SDL_GetGamepadTypeForIndex_REAL
 #define SDL_GetGamepadType SDL_GetGamepadType_REAL
 #define SDL_GetGamepadFromPlayerIndex SDL_GetGamepadFromPlayerIndex_REAL
 #define SDL_SetGamepadPlayerIndex SDL_SetGamepadPlayerIndex_REAL
@@ -727,8 +710,6 @@
 #define SDL_SetJoystickVirtualButton SDL_SetJoystickVirtualButton_REAL
 #define SDL_SetJoystickVirtualHat SDL_SetJoystickVirtualHat_REAL
 #define SDL_GetErrorMsg SDL_GetErrorMsg_REAL
-#define SDL_LockSensors SDL_LockSensors_REAL
-#define SDL_UnlockSensors SDL_UnlockSensors_REAL
 #define SDL_Metal_GetLayer SDL_Metal_GetLayer_REAL
 #define SDL_Metal_GetDrawableSize SDL_Metal_GetDrawableSize_REAL
 #define SDL_trunc SDL_trunc_REAL
@@ -835,9 +816,7 @@
 #define SDL_GetRectAndLineIntersectionF SDL_GetRectAndLineIntersectionF_REAL
 #define SDL_GetRenderWindow SDL_GetRenderWindow_REAL
 #define SDL_bsearch SDL_bsearch_REAL
-#define SDL_GetGamepadPathForIndex SDL_GetGamepadPathForIndex_REAL
 #define SDL_GetGamepadPath SDL_GetGamepadPath_REAL
-#define SDL_GetJoystickPathForIndex SDL_GetJoystickPathForIndex_REAL
 #define SDL_GetJoystickPath SDL_GetJoystickPath_REAL
 #define SDL_AttachVirtualJoystickEx SDL_AttachVirtualJoystickEx_REAL
 #define SDL_GetGamepadFirmwareVersion SDL_GetGamepadFirmwareVersion_REAL
@@ -876,3 +855,29 @@
 #define SDL_GetEventState SDL_GetEventState_REAL
 #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL
 #define SDL_RunApp SDL_RunApp_REAL
+#define SDL_GetSensors SDL_GetSensors_REAL
+#define SDL_GetSensorInstanceName SDL_GetSensorInstanceName_REAL
+#define SDL_GetSensorInstanceType SDL_GetSensorInstanceType_REAL
+#define SDL_GetSensorInstanceNonPortableType SDL_GetSensorInstanceNonPortableType_REAL
+#define SDL_GetJoysticks SDL_GetJoysticks_REAL
+#define SDL_GetJoystickInstanceName SDL_GetJoystickInstanceName_REAL
+#define SDL_GetJoystickInstancePath SDL_GetJoystickInstancePath_REAL
+#define SDL_GetJoystickInstancePlayerIndex SDL_GetJoystickInstancePlayerIndex_REAL
+#define SDL_GetJoystickInstanceGUID SDL_GetJoystickInstanceGUID_REAL
+#define SDL_GetJoystickInstanceVendor SDL_GetJoystickInstanceVendor_REAL
+#define SDL_GetJoystickInstanceProduct SDL_GetJoystickInstanceProduct_REAL
+#define SDL_GetJoystickInstanceProductVersion SDL_GetJoystickInstanceProductVersion_REAL
+#define SDL_GetJoystickInstanceType SDL_GetJoystickInstanceType_REAL
+#define SDL_GetGamepadInstanceName SDL_GetGamepadInstanceName_REAL
+#define SDL_GetGamepadInstancePath SDL_GetGamepadInstancePath_REAL
+#define SDL_GetGamepadInstanceType SDL_GetGamepadInstanceType_REAL
+#define SDL_GetGamepadInstanceMapping SDL_GetGamepadInstanceMapping_REAL
+#define SDL_HasJoysticks SDL_HasJoysticks_REAL
+#define SDL_HasSensors SDL_HasSensors_REAL
+#define SDL_HasGamepads SDL_HasGamepads_REAL
+#define SDL_GetGamepads SDL_GetGamepads_REAL
+#define SDL_GetGamepadInstancePlayerIndex SDL_GetGamepadInstancePlayerIndex_REAL
+#define SDL_GetGamepadInstanceGUID SDL_GetGamepadInstanceGUID_REAL
+#define SDL_GetGamepadInstanceVendor SDL_GetGamepadInstanceVendor_REAL
+#define SDL_GetGamepadInstanceProduct SDL_GetGamepadInstanceProduct_REAL
+#define SDL_GetGamepadInstanceProductVersion SDL_GetGamepadInstanceProductVersion_REAL

+ 34 - 29
src/dynapi/SDL_dynapi_procs.h

@@ -156,9 +156,8 @@ SDL_DYNAPI_PROC(char*,SDL_GetPrefPath,(const char *a, const char *b),(a,b),retur
 SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return)
 SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForGUID,(SDL_JoystickGUID a),(a),return)
 SDL_DYNAPI_PROC(char*,SDL_GetGamepadMapping,(SDL_Gamepad *a),(a),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_IsGamepad,(int a),(a),return)
-SDL_DYNAPI_PROC(const char*,SDL_GetGamepadNameForIndex,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_OpenGamepad,(int a),(a),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_IsGamepad,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_OpenGamepad,(SDL_JoystickID a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetGamepadName,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsGamepadConnected,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetGamepadJoystick,(SDL_Gamepad *a),(a),return)
@@ -209,11 +208,8 @@ SDL_DYNAPI_PROC(const char*,SDL_GetHint,(const char *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),)
 SDL_DYNAPI_PROC(void,SDL_DelHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),)
 SDL_DYNAPI_PROC(void,SDL_ClearHints,(void),(),)
-SDL_DYNAPI_PROC(int,SDL_GetNumJoysticks,(void),(),return)
-SDL_DYNAPI_PROC(const char*,SDL_GetJoystickNameForIndex,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_Joystick*,SDL_OpenJoystick,(int a),(a),return)
+SDL_DYNAPI_PROC(SDL_Joystick*,SDL_OpenJoystick,(SDL_JoystickID a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetJoystickName,(SDL_Joystick *a),(a),return)
-SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickDeviceGUID,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickGUID,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDString,(SDL_JoystickGUID a, char *b, int c),(a,b,c),)
 SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickGUIDFromString,(const char *a),(a),return)
@@ -611,9 +607,6 @@ SDL_DYNAPI_PROC(void,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),)
 SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurface,(int a, int b, Uint32 c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurfaceFrom,(void *a, int b, int c, int d, Uint32 e),(a,b,c,d,e),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_GetHintBoolean,(const char *a, SDL_bool b),(a,b),return)
-SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickDeviceVendor,(int a),(a),return)
-SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickDeviceProduct,(int a),(a),return)
-SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickDeviceProductVersion,(int a),(a),return)
 SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickVendor,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProduct,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProductVersion,(SDL_Joystick *a),(a),return)
@@ -624,11 +617,9 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasNEON,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_GetNumGamepadMappings,(void),(),return)
 SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_GetJoystickAxisInitialState,(SDL_Joystick *a, int b, Sint16 *c),(a,b,c),return)
-SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickDeviceType,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickType,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_MemoryBarrierReleaseFunction,(void),(),)
 SDL_DYNAPI_PROC(void,SDL_MemoryBarrierAcquireFunction,(void),(),)
-SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetJoystickDeviceInstanceID,(int a),(a),return)
 SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return)
 SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, int c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_wcscmp,(const wchar_t *a, const wchar_t *b),(a,b),return)
@@ -678,7 +669,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return)
 #endif
 SDL_DYNAPI_PROC(double,SDL_log10,(double a),(a),return)
 SDL_DYNAPI_PROC(float,SDL_log10f,(float a),(a),return)
-SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForDeviceIndex,(int a),(a),return)
 #ifdef __LINUX__
 SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriority,(Sint64 a, int b),(a,b),return)
 #endif
@@ -693,12 +683,7 @@ SDL_DYNAPI_PROC(float,SDL_expf,(float a),(a),return)
 SDL_DYNAPI_PROC(wchar_t*,SDL_wcsdup,(const wchar_t *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RumbleGamepad,(SDL_Gamepad *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(int,SDL_RumbleJoystick,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return)
-SDL_DYNAPI_PROC(int,SDL_GetNumSensors,(void),(),return)
-SDL_DYNAPI_PROC(const char*,SDL_GetSensorDeviceName,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorDeviceType,(int a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_GetSensorDeviceNonPortableType,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_SensorID,SDL_GetSensorDeviceInstanceID,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_Sensor*,SDL_OpenSensor,(int a),(a),return)
+SDL_DYNAPI_PROC(SDL_Sensor*,SDL_OpenSensor,(SDL_SensorID a),(a),return)
 SDL_DYNAPI_PROC(SDL_Sensor*,SDL_GetSensorFromInstanceID,(SDL_SensorID a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetSensorName,(SDL_Sensor *a),(a),return)
 SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorType,(SDL_Sensor *a),(a),return)
@@ -721,7 +706,6 @@ SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a,
 SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d),(a,b,c,d),return)
 #endif
 
-SDL_DYNAPI_PROC(int,SDL_GetJoystickDevicePlayerIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GetJoystickPlayerIndex,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GetGamepadPlayerIndex,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return)
@@ -753,7 +737,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasARMSIMD,(void),(),return)
 SDL_DYNAPI_PROC(char*,SDL_strtokr,(char *a, const char *b, char **c),(a,b,c),return)
 SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
-SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadTypeForIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadType,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_GetGamepadFromPlayerIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_SetGamepadPlayerIndex,(SDL_Gamepad *a, int b),(a,b),)
@@ -775,15 +758,13 @@ SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
 #endif
 SDL_DYNAPI_PROC(int,SDL_isupper,(int a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_islower,(int a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return)
-SDL_DYNAPI_PROC(int,SDL_DetachVirtualJoystick,(int a),(a),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickVirtual,(int a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(int,SDL_DetachVirtualJoystick,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickVirtual,(SDL_JoystickID a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualAxis,(SDL_Joystick *a, int b, Sint16 c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualButton,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualHat,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return)
 SDL_DYNAPI_PROC(char*,SDL_GetErrorMsg,(char *a, int b),(a,b),return)
-SDL_DYNAPI_PROC(void,SDL_LockSensors,(void),(),)
-SDL_DYNAPI_PROC(void,SDL_UnlockSensors,(void),(),)
 SDL_DYNAPI_PROC(void*,SDL_Metal_GetLayer,(SDL_MetalView a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_Metal_GetDrawableSize,(SDL_Window *a, int *b, int *c),(a,b,c),)
 SDL_DYNAPI_PROC(double,SDL_trunc,(double a),(a),return)
@@ -902,11 +883,9 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectEnclosingPointsF,(const SDL_FPoint *a, int b
 SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectAndLineIntersectionF,(const SDL_FRect *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return)
 SDL_DYNAPI_PROC(SDL_Window*,SDL_GetRenderWindow,(SDL_Renderer *a),(a),return)
 SDL_DYNAPI_PROC(void*,SDL_bsearch,(const void *a, const void *b, size_t c, size_t d, int (SDLCALL *e)(const void *, const void *)),(a,b,c,d,e),return)
-SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPathForIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPath,(SDL_Gamepad *a),(a),return)
-SDL_DYNAPI_PROC(const char*,SDL_GetJoystickPathForIndex,(int a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetJoystickPath,(SDL_Joystick *a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return)
 SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadFirmwareVersion,(SDL_Gamepad *a),(a),return)
 SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickFirmwareVersion,(SDL_Joystick *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_GUIDToString,(SDL_GUID a, char *b, int c),(a,b,c),)
@@ -950,3 +929,29 @@ SDL_DYNAPI_PROC(void,SDL_DelayNS,(Uint64 a),(a),)
 SDL_DYNAPI_PROC(Uint8,SDL_GetEventState,(Uint32 a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetRenderDriver,(int a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RunApp,(int a, char* b[], SDL_main_func c, void *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_SensorID*,SDL_GetSensors,(int *a),(a),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetSensorInstanceName,(SDL_SensorID a),(a),return)
+SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorInstanceType,(SDL_SensorID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetSensorInstanceNonPortableType,(SDL_SensorID a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickID*,SDL_GetJoysticks,(int *a),(a),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetJoystickInstanceName,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetJoystickInstancePath,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetJoystickInstancePlayerIndex,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickInstanceGUID,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceVendor,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceProduct,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceProductVersion,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickInstanceType,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetGamepadInstanceName,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetGamepadInstancePath,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadInstanceType,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(char*,SDL_GetGamepadInstanceMapping,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasJoysticks,(void),(),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasSensors,(void),(),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasGamepads,(void),(),return)
+SDL_DYNAPI_PROC(SDL_JoystickID*,SDL_GetGamepads,(int *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetGamepadInstancePlayerIndex,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetGamepadInstanceGUID,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceVendor,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceProduct,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceProductVersion,(SDL_JoystickID a),(a),return)

+ 7 - 10
src/events/SDL_events.c

@@ -380,17 +380,17 @@ static void SDL_LogEvent(const SDL_Event *event)
         break;
 #undef PRINT_CBUTTON_EVENT
 
-#define PRINT_CONTROLLERDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->cdevice.timestamp, (int)event->cdevice.which)
+#define PRINT_GAMEPADDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->cdevice.timestamp, (int)event->cdevice.which)
         SDL_EVENT_CASE(SDL_GAMEPADADDED)
-        PRINT_CONTROLLERDEV_EVENT(event);
+        PRINT_GAMEPADDEV_EVENT(event);
         break;
         SDL_EVENT_CASE(SDL_GAMEPADREMOVED)
-        PRINT_CONTROLLERDEV_EVENT(event);
+        PRINT_GAMEPADDEV_EVENT(event);
         break;
         SDL_EVENT_CASE(SDL_GAMEPADDEVICEREMAPPED)
-        PRINT_CONTROLLERDEV_EVENT(event);
+        PRINT_GAMEPADDEV_EVENT(event);
         break;
-#undef PRINT_CONTROLLERDEV_EVENT
+#undef PRINT_GAMEPADDEV_EVENT
 
 #define PRINT_CTOUCHPAD_EVENT(event)                                                                                     \
     (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d touchpad=%d finger=%d x=%f y=%f pressure=%f)", \
@@ -998,15 +998,12 @@ static SDL_bool SDL_events_need_polling()
     SDL_bool need_polling = SDL_FALSE;
 
 #if !SDL_JOYSTICK_DISABLED
-    need_polling =
-        SDL_WasInit(SDL_INIT_JOYSTICK) &&
-        SDL_update_joysticks &&
-        (SDL_GetNumJoysticks() > 0);
+    need_polling = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks && SDL_HasJoysticks();
 #endif
 
 #if !SDL_SENSOR_DISABLED
     need_polling = need_polling ||
-                   (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && (SDL_GetNumSensors() > 0));
+                   (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_HasSensors());
 #endif
 
     return need_polling;

+ 96 - 61
src/joystick/SDL_gamepad.c

@@ -1443,7 +1443,7 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char *
     return SDL_PrivateAddMappingForGUID(guid, mapping, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT);
 }
 
-static GamepadMapping_t *SDL_PrivateGetGamepadMapping(int device_index)
+static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id)
 {
     const char *name;
     SDL_JoystickGUID guid;
@@ -1451,19 +1451,14 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(int device_index)
 
     SDL_AssertJoysticksLocked();
 
-    if ((device_index < 0) || (device_index >= SDL_GetNumJoysticks())) {
-        SDL_SetError("There are %d joysticks available", SDL_GetNumJoysticks());
-        return NULL;
-    }
-
-    name = SDL_GetJoystickNameForIndex(device_index);
-    guid = SDL_GetJoystickDeviceGUID(device_index);
+    name = SDL_GetJoystickInstanceName(instance_id);
+    guid = SDL_GetJoystickInstanceGUID(instance_id);
     mapping = SDL_PrivateGetGamepadMappingForNameAndGUID(name, guid);
     if (mapping == NULL) {
         SDL_GamepadMapping raw_map;
 
         SDL_zero(raw_map);
-        if (SDL_PrivateJoystickGetAutoGamepadMapping(device_index, &raw_map)) {
+        if (SDL_PrivateJoystickGetAutoGamepadMapping(instance_id, &raw_map)) {
             mapping = SDL_PrivateGenerateAutomaticGamepadMapping(name, guid, &raw_map);
         }
     }
@@ -1896,37 +1891,78 @@ int SDL_InitGamepadMappings(void)
 int SDL_InitGamepads(void)
 {
     int i;
+    SDL_JoystickID *joysticks;
 
-    /* watch for joy events and fire gamepad ones if needed */
+    /* Watch for joystick events and fire gamepad ones if needed */
     SDL_AddEventWatch(SDL_GamepadEventWatcher, NULL);
 
     /* Send added events for gamepads currently attached */
-    for (i = 0; i < SDL_GetNumJoysticks(); ++i) {
-        if (SDL_IsGamepad(i)) {
-            SDL_Event deviceevent;
-            deviceevent.type = SDL_GAMEPADADDED;
-            deviceevent.common.timestamp = 0;
-            deviceevent.cdevice.which = i;
-            SDL_PushEvent(&deviceevent);
+    joysticks = SDL_GetJoysticks(NULL);
+    if (joysticks) {
+        for (i = 0; joysticks[i]; ++i) {
+            if (SDL_IsGamepad(joysticks[i])) {
+                SDL_Event deviceevent;
+                deviceevent.type = SDL_GAMEPADADDED;
+                deviceevent.common.timestamp = 0;
+                deviceevent.cdevice.which = joysticks[i];
+                SDL_PushEvent(&deviceevent);
+            }
         }
+        SDL_free(joysticks);
     }
 
     return 0;
 }
 
-/*
- * Get the implementation dependent name of a gamepad
- */
-const char *SDL_GetGamepadNameForIndex(int joystick_index)
+SDL_bool SDL_HasGamepads(void)
+{
+    SDL_bool retval = SDL_FALSE;
+    SDL_JoystickID *joysticks = SDL_GetJoysticks(NULL);
+    if (joysticks) {
+        int i;
+        for (i = 0; joysticks[i]; ++i) {
+            if (SDL_IsGamepad(joysticks[i])) {
+                retval = SDL_TRUE;
+                break;
+            }
+        }
+        SDL_free(joysticks);
+    }
+    return retval;
+}
+
+SDL_JoystickID *SDL_GetGamepads(int *count)
+{
+    int num_joysticks = 0;
+    int num_gamepads = 0;
+    SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
+    if (joysticks) {
+        int i;
+        for (i = num_joysticks - 1; i >= 0; --i) {
+            if (SDL_IsGamepad(joysticks[i])) {
+                ++num_gamepads;
+            } else {
+                SDL_memmove(&joysticks[i], &joysticks[i+1], (num_gamepads + 1) * sizeof(joysticks[i]));
+            }
+        }
+        SDL_free(joysticks);
+    }
+    if (count) {
+        *count = num_gamepads;
+    }
+    return joysticks;
+}
+
+const char *SDL_GetGamepadInstanceName(SDL_JoystickID instance_id)
 {
     const char *retval = NULL;
 
     SDL_LockJoysticks();
     {
-        GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(joystick_index);
+        GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id);
         if (mapping != NULL) {
             if (SDL_strcmp(mapping->name, "*") == 0) {
-                retval = SDL_GetJoystickNameForIndex(joystick_index);
+                retval = SDL_GetJoystickInstanceName(instance_id);
             } else {
                 retval = mapping->name;
             }
@@ -1937,50 +1973,53 @@ const char *SDL_GetGamepadNameForIndex(int joystick_index)
     return retval;
 }
 
-/*
- * Get the implementation dependent path of a gamepad
- */
-const char *SDL_GetGamepadPathForIndex(int joystick_index)
+const char *SDL_GetGamepadInstancePath(SDL_JoystickID instance_id)
 {
-    const char *retval = NULL;
+    return SDL_GetJoystickInstancePath(instance_id);
+}
 
-    SDL_LockJoysticks();
-    {
-        GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(joystick_index);
-        if (mapping != NULL) {
-            retval = SDL_GetJoystickPathForIndex(joystick_index);
-        }
-    }
-    SDL_UnlockJoysticks();
+int SDL_GetGamepadInstancePlayerIndex(SDL_JoystickID instance_id)
+{
+    return SDL_GetJoystickInstancePlayerIndex(instance_id);
+}
 
-    return retval;
+SDL_JoystickGUID SDL_GetGamepadInstanceGUID(SDL_JoystickID instance_id)
+{
+    return SDL_GetJoystickInstanceGUID(instance_id);
 }
 
-/**
- *  Get the type of a gamepad.
- */
-SDL_GamepadType SDL_GetGamepadTypeForIndex(int joystick_index)
+Uint16 SDL_GetGamepadInstanceVendor(SDL_JoystickID instance_id)
 {
-    return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickDeviceGUID(joystick_index), SDL_GetJoystickNameForIndex(joystick_index));
+    return SDL_GetJoystickInstanceVendor(instance_id);
 }
 
-/**
- *  Get the mapping of a gamepad.
- *  This can be called before any gamepads are opened.
- *  If no mapping can be found, this function returns NULL.
- */
-char *SDL_GetGamepadMappingForDeviceIndex(int joystick_index)
+Uint16 SDL_GetGamepadInstanceProduct(SDL_JoystickID instance_id)
+{
+    return SDL_GetJoystickInstanceProduct(instance_id);
+}
+
+Uint16 SDL_GetGamepadInstanceProductVersion(SDL_JoystickID instance_id)
+{
+    return SDL_GetJoystickInstanceProductVersion(instance_id);
+}
+
+SDL_GamepadType SDL_GetGamepadInstanceType(SDL_JoystickID instance_id)
+{
+    return SDL_GetGamepadTypeFromGUID(SDL_GetJoystickInstanceGUID(instance_id), SDL_GetJoystickInstanceName(instance_id));
+}
+
+char *SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id)
 {
     char *retval = NULL;
 
     SDL_LockJoysticks();
     {
-        GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(joystick_index);
+        GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id);
         if (mapping != NULL) {
             SDL_JoystickGUID guid;
             char pchGUID[33];
             size_t needed;
-            guid = SDL_GetJoystickDeviceGUID(joystick_index);
+            guid = SDL_GetJoystickInstanceGUID(instance_id);
             SDL_GetJoystickGUIDString(guid, pchGUID, sizeof(pchGUID));
             /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */
             needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1;
@@ -2019,13 +2058,13 @@ SDL_bool SDL_IsGamepadNameAndGUID(const char *name, SDL_JoystickGUID guid)
 /*
  * Return 1 if the joystick at this device index is a supported gamepad
  */
-SDL_bool SDL_IsGamepad(int joystick_index)
+SDL_bool SDL_IsGamepad(SDL_JoystickID instance_id)
 {
     SDL_bool retval;
 
     SDL_LockJoysticks();
     {
-        if (SDL_PrivateGetGamepadMapping(joystick_index) != NULL) {
+        if (SDL_PrivateGetGamepadMapping(instance_id) != NULL) {
             retval = SDL_TRUE;
         } else {
             retval = SDL_FALSE;
@@ -2129,15 +2168,12 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid)
 }
 
 /*
- * Open a gamepad for use - the index passed as an argument refers to
- * the N'th gamepad on the system.  This index is the value which will
- * identify this gamepad in future gamepad events.
+ * Open a gamepad for use
  *
  * This function returns a gamepad identifier, or NULL if an error occurred.
  */
-SDL_Gamepad *SDL_OpenGamepad(int joystick_index)
+SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
 {
-    SDL_JoystickID instance_id;
     SDL_Gamepad *gamepad;
     SDL_Gamepad *gamepadlist;
     GamepadMapping_t *pSupportedGamepad = NULL;
@@ -2146,7 +2182,6 @@ SDL_Gamepad *SDL_OpenGamepad(int joystick_index)
 
     gamepadlist = SDL_gamepads;
     /* If the gamepad is already open, return it */
-    instance_id = SDL_GetJoystickDeviceInstanceID(joystick_index);
     while (gamepadlist != NULL) {
         if (instance_id == gamepadlist->joystick->instance_id) {
             gamepad = gamepadlist;
@@ -2158,9 +2193,9 @@ SDL_Gamepad *SDL_OpenGamepad(int joystick_index)
     }
 
     /* Find a gamepad mapping */
-    pSupportedGamepad = SDL_PrivateGetGamepadMapping(joystick_index);
+    pSupportedGamepad = SDL_PrivateGetGamepadMapping(instance_id);
     if (pSupportedGamepad == NULL) {
-        SDL_SetError("Couldn't find mapping for device (%d)", joystick_index);
+        SDL_SetError("Couldn't find mapping for device (%" SDL_PRIu32 ")", instance_id);
         SDL_UnlockJoysticks();
         return NULL;
     }
@@ -2174,7 +2209,7 @@ SDL_Gamepad *SDL_OpenGamepad(int joystick_index)
     }
     gamepad->magic = &gamepad_magic;
 
-    gamepad->joystick = SDL_OpenJoystick(joystick_index);
+    gamepad->joystick = SDL_OpenJoystick(instance_id);
     if (gamepad->joystick == NULL) {
         SDL_free(gamepad);
         SDL_UnlockJoysticks();

+ 111 - 178
src/joystick/SDL_joystick.c

@@ -113,7 +113,7 @@ static int SDL_joysticks_locked;
 static SDL_bool SDL_joysticks_initialized;
 static SDL_bool SDL_joysticks_quitting = SDL_FALSE;
 static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
-static SDL_atomic_t SDL_next_joystick_instance_id SDL_GUARDED_BY(SDL_joystick_lock);
+static SDL_atomic_t SDL_last_joystick_instance_id SDL_GUARDED_BY(SDL_joystick_lock);
 static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0;
 static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
 static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
@@ -169,29 +169,30 @@ void SDL_AssertJoysticksLocked(void)
 }
 
 /*
- * Get the driver and device index for an API device index
+ * Get the driver and device index for a joystick instance ID
  * This should be called while the joystick lock is held, to prevent another thread from updating the list
  */
-static SDL_bool SDL_GetDriverAndJoystickIndex(int device_index, SDL_JoystickDriver **driver, int *driver_index)
+static SDL_bool SDL_GetDriverAndJoystickIndex(SDL_JoystickID instance_id, SDL_JoystickDriver **driver, int *driver_index)
 {
-    int i, num_joysticks, total_joysticks = 0;
+    int i, num_joysticks, device_index;
 
     SDL_AssertJoysticksLocked();
 
-    if (device_index >= 0) {
+    if (instance_id > 0) {
         for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
             num_joysticks = SDL_joystick_drivers[i]->GetCount();
-            if (device_index < num_joysticks) {
-                *driver = SDL_joystick_drivers[i];
-                *driver_index = device_index;
-                return SDL_TRUE;
+            for (device_index = 0; device_index < num_joysticks; ++device_index) {
+                SDL_JoystickID joystick_id = SDL_joystick_drivers[i]->GetDeviceInstanceID(device_index);
+                if (joystick_id == instance_id) {
+                    *driver = SDL_joystick_drivers[i];
+                    *driver_index = device_index;
+                    return SDL_TRUE;
+                }
             }
-            device_index -= num_joysticks;
-            total_joysticks += num_joysticks;
         }
     }
 
-    SDL_SetError("There are %d joysticks available", total_joysticks);
+    SDL_SetError("Joystick %" SDL_PRIu32 " not found", instance_id);
     return SDL_FALSE;
 }
 
@@ -271,8 +272,7 @@ static SDL_bool SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID
     }
 
     /* Update the driver with the new index */
-    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         driver->SetDevicePlayerIndex(device_index, player_index);
     }
 
@@ -332,18 +332,57 @@ int SDL_InitJoysticks(void)
     return status;
 }
 
-/*
- * Count the number of joysticks attached to the system
- */
-int SDL_GetNumJoysticks(void)
+SDL_bool SDL_HasJoysticks(void)
 {
-    int i, total_joysticks = 0;
+    int i;
+    SDL_bool retval = SDL_FALSE;
     SDL_LockJoysticks();
     for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
-        total_joysticks += SDL_joystick_drivers[i]->GetCount();
+        if (SDL_joystick_drivers[i]->GetCount() > 0) {
+            retval = SDL_TRUE;
+            break;
+        }
     }
     SDL_UnlockJoysticks();
-    return total_joysticks;
+    return retval;
+}
+
+SDL_JoystickID *SDL_GetJoysticks(int *count)
+{
+    int i, num_joysticks, device_index;
+    int joystick_index = 0, total_joysticks = 0;
+    SDL_JoystickID *joysticks;
+
+    SDL_LockJoysticks();
+    {
+        for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
+            total_joysticks += SDL_joystick_drivers[i]->GetCount();
+        }
+
+        if (count) {
+            *count = total_joysticks;
+        }
+
+        joysticks = (SDL_JoystickID *)SDL_malloc((total_joysticks + 1) * sizeof(*joysticks));
+        if (joysticks) {
+            for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
+                num_joysticks = SDL_joystick_drivers[i]->GetCount();
+                for (device_index = 0; device_index < num_joysticks; ++device_index) {
+                    SDL_assert(joystick_index < total_joysticks);
+                    joysticks[joystick_index] = SDL_joystick_drivers[i]->GetDeviceInstanceID(device_index);
+                    SDL_assert(joysticks[joystick_index] > 0);
+                    ++joystick_index;
+                }
+            }
+            SDL_assert(joystick_index == total_joysticks);
+            joysticks[joystick_index] = 0;
+        } else {
+            SDL_OutOfMemory();
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return joysticks;
 }
 
 /*
@@ -352,19 +391,20 @@ int SDL_GetNumJoysticks(void)
  */
 SDL_JoystickID SDL_GetNextJoystickInstanceID()
 {
-    return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
+    return SDL_AtomicIncRef(&SDL_last_joystick_instance_id) + 1;
 }
 
 /*
  * Get the implementation dependent name of a joystick
  */
-const char *SDL_GetJoystickNameForIndex(int device_index)
+const char *SDL_GetJoystickInstanceName(SDL_JoystickID instance_id)
 {
     SDL_JoystickDriver *driver;
+    int device_index;
     const char *name = NULL;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         name = driver->GetDeviceName(device_index);
     }
     SDL_UnlockJoysticks();
@@ -376,13 +416,14 @@ const char *SDL_GetJoystickNameForIndex(int device_index)
 /*
  * Get the implementation dependent path of a joystick
  */
-const char *SDL_GetJoystickPathForIndex(int device_index)
+const char *SDL_GetJoystickInstancePath(SDL_JoystickID instance_id)
 {
     SDL_JoystickDriver *driver;
+    int device_index;
     const char *path = NULL;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         path = driver->GetDevicePath(device_index);
     }
     SDL_UnlockJoysticks();
@@ -397,12 +438,12 @@ const char *SDL_GetJoystickPathForIndex(int device_index)
 /*
  *  Get the player index of a joystick, or -1 if it's not available
  */
-int SDL_GetJoystickDevicePlayerIndex(int device_index)
+int SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID instance_id)
 {
     int player_index;
 
     SDL_LockJoysticks();
-    player_index = SDL_GetPlayerIndexForJoystickID(SDL_GetJoystickDeviceInstanceID(device_index));
+    player_index = SDL_GetPlayerIndexForJoystickID(instance_id);
     SDL_UnlockJoysticks();
 
     return player_index;
@@ -457,10 +498,10 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick)
  *
  * This function returns a joystick identifier, or NULL if an error occurred.
  */
-SDL_Joystick *SDL_OpenJoystick(int device_index)
+SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
 {
     SDL_JoystickDriver *driver;
-    SDL_JoystickID instance_id;
+    int device_index;
     SDL_Joystick *joystick;
     SDL_Joystick *joysticklist;
     const char *joystickname = NULL;
@@ -469,16 +510,15 @@ SDL_Joystick *SDL_OpenJoystick(int device_index)
 
     SDL_LockJoysticks();
 
-    if (!SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (!SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         SDL_UnlockJoysticks();
         return NULL;
     }
 
     joysticklist = SDL_joysticks;
     /* If the joystick is already open, return it
-     * it is important that we have a single joystick * for each instance id
+     * it is important that we have a single joystick for each instance id
      */
-    instance_id = driver->GetDeviceInstanceID(device_index);
     while (joysticklist) {
         if (instance_id == joysticklist->instance_id) {
             joystick = joysticklist;
@@ -550,7 +590,7 @@ SDL_Joystick *SDL_OpenJoystick(int device_index)
         }
     }
 
-    joystick->is_game_controller = SDL_IsGamepad(device_index);
+    joystick->is_gamepad = SDL_IsGamepad(instance_id);
 
     /* Add joystick to list */
     ++joystick->ref_count;
@@ -570,7 +610,7 @@ SDL_Joystick *SDL_OpenJoystick(int device_index)
     return joystick;
 }
 
-int SDL_AttachVirtualJoystick(SDL_JoystickType type, int naxes, int nbuttons, int nhats)
+SDL_JoystickID SDL_AttachVirtualJoystick(SDL_JoystickType type, int naxes, int nbuttons, int nhats)
 {
     SDL_VirtualJoystickDesc desc;
 
@@ -583,10 +623,10 @@ int SDL_AttachVirtualJoystick(SDL_JoystickType type, int naxes, int nbuttons, in
     return SDL_AttachVirtualJoystickEx(&desc);
 }
 
-int SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc)
+SDL_JoystickID SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc)
 {
 #if SDL_JOYSTICK_VIRTUAL
-    int retval;
+    SDL_JoystickID retval;
 
     SDL_LockJoysticks();
     retval = SDL_JoystickAttachVirtualInner(desc);
@@ -597,36 +637,29 @@ int SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc)
 #endif
 }
 
-int SDL_DetachVirtualJoystick(int device_index)
+int SDL_DetachVirtualJoystick(SDL_JoystickID instance_id)
 {
 #if SDL_JOYSTICK_VIRTUAL
-    SDL_JoystickDriver *driver;
+    int retval;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
-        if (driver == &SDL_VIRTUAL_JoystickDriver) {
-            const int retval = SDL_JoystickDetachVirtualInner(device_index);
-            SDL_UnlockJoysticks();
-            return retval;
-        }
-    }
+    retval = SDL_JoystickDetachVirtualInner(instance_id);
     SDL_UnlockJoysticks();
-
-    return SDL_SetError("Virtual joystick not found at provided index");
+    return retval;
 #else
     return SDL_SetError("SDL not built with virtual-joystick support");
 #endif
 }
 
-SDL_bool SDL_IsJoystickVirtual(int device_index)
+SDL_bool SDL_IsJoystickVirtual(SDL_JoystickID instance_id)
 {
 #if SDL_JOYSTICK_VIRTUAL
     SDL_JoystickDriver *driver;
-    int driver_device_index;
+    int device_index;
     SDL_bool is_virtual = SDL_FALSE;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         if (driver == &SDL_VIRTUAL_JoystickDriver) {
             is_virtual = SDL_TRUE;
         }
@@ -705,13 +738,14 @@ SDL_bool SDL_IsJoystickValid(SDL_Joystick *joystick)
     return (joystick && joystick->magic == &joystick_magic);
 }
 
-SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *out)
+SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance_id, SDL_GamepadMapping *out)
 {
     SDL_JoystickDriver *driver;
+    int device_index;
     SDL_bool is_ok = SDL_FALSE;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         is_ok = driver->GetGamepadMapping(device_index, out);
     }
     SDL_UnlockJoysticks();
@@ -1341,15 +1375,11 @@ void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, f
     }
 }
 
-void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
+void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
 {
     SDL_JoystickDriver *driver;
-    int driver_device_index;
+    int device_index;
     int player_index = -1;
-    int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
-    if (device_index < 0) {
-        return;
-    }
 
     SDL_AssertJoysticksLocked();
 
@@ -1357,14 +1387,14 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
         return;
     }
 
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
-        player_index = driver->GetDevicePlayerIndex(driver_device_index);
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
+        player_index = driver->GetDevicePlayerIndex(device_index);
     }
-    if (player_index < 0 && SDL_IsGamepad(device_index)) {
+    if (player_index < 0 && SDL_IsGamepad(instance_id)) {
         player_index = SDL_FindFreePlayerIndex();
     }
     if (player_index >= 0) {
-        SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
+        SDL_SetJoystickIDForPlayerIndex(player_index, instance_id);
     }
 
 #if !SDL_EVENTS_DISABLED
@@ -1375,73 +1405,13 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
         event.common.timestamp = 0;
 
         if (SDL_GetEventState(event.type) == SDL_ENABLE) {
-            event.jdevice.which = device_index;
+            event.jdevice.which = instance_id;
             SDL_PushEvent(&event);
         }
     }
 #endif /* !SDL_EVENTS_DISABLED */
 }
 
-/*
- * If there is an existing add event in the queue, it needs to be modified
- * to have the right value for which, because the number of controllers in
- * the system is now one less.
- */
-static void UpdateEventsForDeviceRemoval(int device_index, Uint32 type)
-{
-    int i, num_events;
-    SDL_Event *events;
-    SDL_bool isstack;
-
-    num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type);
-    if (num_events <= 0) {
-        return;
-    }
-
-    events = SDL_small_alloc(SDL_Event, num_events, &isstack);
-    if (events == NULL) {
-        return;
-    }
-
-    num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, type, type);
-    for (i = 0; i < num_events; ++i) {
-        Sint32 which = -1;
-        switch (type) {
-        case SDL_JOYDEVICEADDED:
-            which = events[i].jdevice.which;
-            break;
-        case SDL_GAMEPADADDED:
-            which = events[i].cdevice.which;
-            break;
-        default:
-            break;
-        }
-        if (which < device_index) {
-            /* No change for index values lower than the removed device */
-        } else if (which == device_index) {
-            /* Drop this event entirely */
-            SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
-            --num_events;
-            --i;
-        } else {
-            /* Fix up the device index if greater than the removed device */
-            switch (type) {
-            case SDL_JOYDEVICEADDED:
-                --events[i].jdevice.which;
-                break;
-            case SDL_GAMEPADADDED:
-                --events[i].cdevice.which;
-                break;
-            default:
-                break;
-            }
-        }
-    }
-    SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
-
-    SDL_small_free(events, isstack);
-}
-
 void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
 {
     int i, j;
@@ -1473,11 +1443,10 @@ void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
     }
 }
 
-void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
+void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id)
 {
     SDL_Joystick *joystick = NULL;
     int player_index;
-    int device_index;
 #if !SDL_EVENTS_DISABLED
     SDL_Event event;
 #endif
@@ -1485,15 +1454,12 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
     SDL_AssertJoysticksLocked();
 
     /* Find this joystick... */
-    device_index = 0;
     for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
-        if (joystick->instance_id == device_instance) {
+        if (joystick->instance_id == instance_id) {
             SDL_PrivateJoystickForceRecentering(joystick);
             joystick->attached = SDL_FALSE;
             break;
         }
-
-        ++device_index;
     }
 
 #if !SDL_EVENTS_DISABLED
@@ -1501,15 +1467,12 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
     event.common.timestamp = 0;
 
     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
-        event.jdevice.which = device_instance;
+        event.jdevice.which = instance_id;
         SDL_PushEvent(&event);
     }
-
-    UpdateEventsForDeviceRemoval(device_index, SDL_JOYDEVICEADDED);
-    UpdateEventsForDeviceRemoval(device_index, SDL_GAMEPADADDED);
 #endif /* !SDL_EVENTS_DISABLED */
 
-    player_index = SDL_GetPlayerIndexForJoystickID(device_instance);
+    player_index = SDL_GetPlayerIndexForJoystickID(instance_id);
     if (player_index >= 0) {
         SDL_joystick_players[player_index] = -1;
     }
@@ -2684,13 +2647,14 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
 }
 
 /* return the guid for this index */
-SDL_JoystickGUID SDL_GetJoystickDeviceGUID(int device_index)
+SDL_JoystickGUID SDL_GetJoystickInstanceGUID(SDL_JoystickID instance_id)
 {
     SDL_JoystickDriver *driver;
+    int device_index;
     SDL_JoystickGUID guid;
 
     SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
         guid = driver->GetDeviceGUID(device_index);
     } else {
         SDL_zero(guid);
@@ -2700,78 +2664,47 @@ SDL_JoystickGUID SDL_GetJoystickDeviceGUID(int device_index)
     return guid;
 }
 
-Uint16 SDL_GetJoystickDeviceVendor(int device_index)
+Uint16 SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id)
 {
     Uint16 vendor;
-    SDL_JoystickGUID guid = SDL_GetJoystickDeviceGUID(device_index);
+    SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
 
     SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
     return vendor;
 }
 
-Uint16 SDL_GetJoystickDeviceProduct(int device_index)
+Uint16 SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id)
 {
     Uint16 product;
-    SDL_JoystickGUID guid = SDL_GetJoystickDeviceGUID(device_index);
+    SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
 
     SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
     return product;
 }
 
-Uint16 SDL_GetJoystickDeviceProductVersion(int device_index)
+Uint16 SDL_GetJoystickInstanceProductVersion(SDL_JoystickID instance_id)
 {
     Uint16 version;
-    SDL_JoystickGUID guid = SDL_GetJoystickDeviceGUID(device_index);
+    SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
 
     SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version, NULL);
     return version;
 }
 
-SDL_JoystickType SDL_GetJoystickDeviceType(int device_index)
+SDL_JoystickType SDL_GetJoystickInstanceType(SDL_JoystickID instance_id)
 {
     SDL_JoystickType type;
-    SDL_JoystickGUID guid = SDL_GetJoystickDeviceGUID(device_index);
+    SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID(instance_id);
 
     type = SDL_GetJoystickGUIDType(guid);
     if (type == SDL_JOYSTICK_TYPE_UNKNOWN) {
-        if (SDL_IsGamepad(device_index)) {
+        if (SDL_IsGamepad(instance_id)) {
             type = SDL_JOYSTICK_TYPE_GAMEPAD;
         }
     }
     return type;
 }
 
-SDL_JoystickID SDL_GetJoystickDeviceInstanceID(int device_index)
-{
-    SDL_JoystickDriver *driver;
-    SDL_JoystickID instance_id = -1;
-
-    SDL_LockJoysticks();
-    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
-        instance_id = driver->GetDeviceInstanceID(device_index);
-    }
-    SDL_UnlockJoysticks();
-
-    return instance_id;
-}
-
-int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
-{
-    int i, num_joysticks, device_index = -1;
-
-    SDL_LockJoysticks();
-    num_joysticks = SDL_GetNumJoysticks();
-    for (i = 0; i < num_joysticks; ++i) {
-        if (SDL_GetJoystickDeviceInstanceID(i) == instance_id) {
-            device_index = i;
-            break;
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return device_index;
-}
-
 SDL_JoystickGUID SDL_GetJoystickGUID(SDL_Joystick *joystick)
 {
     SDL_JoystickGUID retval;
@@ -2857,7 +2790,7 @@ SDL_JoystickType SDL_GetJoystickType(SDL_Joystick *joystick)
         {
             CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_TYPE_UNKNOWN);
 
-            if (joystick->is_game_controller) {
+            if (joystick->is_gamepad) {
                 type = SDL_JOYSTICK_TYPE_GAMEPAD;
             }
         }

+ 3 - 6
src/joystick/SDL_joystick_c.h

@@ -52,9 +52,6 @@ extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_l
 /* Function to get the next available joystick instance ID */
 extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void);
 
-/* Function to return the device index for a joystick ID, or -1 if not found */
-extern int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id);
-
 /* Function to standardize the name for a controller
    This should be freed with SDL_free() when no longer needed
  */
@@ -134,8 +131,8 @@ extern SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid
 /* Internal event queueing functions */
 extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers);
 extern void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, float rate);
-extern void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance);
-extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
+extern void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id);
+extern void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id);
 extern void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick);
 extern int SDL_SendJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick,
                                    Uint8 axis, Sint16 value);
@@ -198,7 +195,7 @@ typedef struct SDL_GamepadMapping
 } SDL_GamepadMapping;
 
 /* Function to get autodetected gamepad controller mapping from the driver */
-extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(int device_index,
+extern SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(SDL_JoystickID instance_id,
                                                          SDL_GamepadMapping *out);
 
 /* Ends C function definitions when using C++ */

+ 1 - 1
src/joystick/SDL_sysjoystick.h

@@ -109,7 +109,7 @@ struct SDL_Joystick
     Uint64 led_expiration _guarded;
 
     SDL_bool attached _guarded;
-    SDL_bool is_game_controller _guarded;
+    SDL_bool is_gamepad _guarded;
     SDL_bool delayed_guide_button _guarded;      /* SDL_TRUE if this device has the guide button event delayed */
     SDL_JoystickPowerLevel epowerlevel _guarded; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
 

+ 10 - 10
src/joystick/hidapi/SDL_hidapi_gamecube.c

@@ -141,10 +141,10 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
     }
     device->context = ctx;
 
-    ctx->joysticks[0] = -1;
-    ctx->joysticks[1] = -1;
-    ctx->joysticks[2] = -1;
-    ctx->joysticks[3] = -1;
+    ctx->joysticks[0] = 0;
+    ctx->joysticks[1] = 0;
+    ctx->joysticks[2] = 0;
+    ctx->joysticks[3] = 0;
     ctx->rumble[0] = rumbleMagic;
     ctx->useRumbleBrake = SDL_FALSE;
 
@@ -186,14 +186,14 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
                 ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) != 0 && !ctx->wireless[i];
 
                 if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
-                    if (ctx->joysticks[i] == -1) {
+                    if (ctx->joysticks[i] == 0) {
                         ResetAxisRange(ctx, i);
                         HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
                     }
                 } else {
-                    if (ctx->joysticks[i] != -1) {
+                    if (ctx->joysticks[i] != 0) {
                         HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
-                        ctx->joysticks[i] = -1;
+                        ctx->joysticks[i] = 0;
                     }
                     continue;
                 }
@@ -315,7 +315,7 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device
         ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) != 0 && !ctx->wireless[i];
 
         if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
-            if (ctx->joysticks[i] == -1) {
+            if (ctx->joysticks[i] == 0) {
                 ResetAxisRange(ctx, i);
                 HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
             }
@@ -326,9 +326,9 @@ static void HIDAPI_DriverGameCube_HandleNintendoPacket(SDL_HIDAPI_Device *device
                 continue;
             }
         } else {
-            if (ctx->joysticks[i] != -1) {
+            if (ctx->joysticks[i] != 0) {
                 HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
-                ctx->joysticks[i] = -1;
+                ctx->joysticks[i] = 0;
             }
             continue;
         }

+ 21 - 15
src/joystick/virtual/SDL_virtualjoystick.c

@@ -30,6 +30,20 @@
 
 static joystick_hwdata *g_VJoys SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
 
+static joystick_hwdata *VIRTUAL_HWDataForInstance(SDL_JoystickID instance_id)
+{
+    joystick_hwdata *vjoy;
+
+    SDL_AssertJoysticksLocked();
+
+    for (vjoy = g_VJoys; vjoy; vjoy = vjoy->next) {
+        if (instance_id == vjoy->instance_id) {
+            return vjoy;
+        }
+    }
+    return NULL;
+}
+
 static joystick_hwdata *VIRTUAL_HWDataForIndex(int device_index)
 {
     joystick_hwdata *vjoy;
@@ -91,10 +105,9 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
     SDL_free(hwdata);
 }
 
-int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
+SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
 {
     joystick_hwdata *hwdata = NULL;
-    int device_index = -1;
     const char *name = NULL;
     int axis_triggerleft = -1;
     int axis_triggerright = -1;
@@ -238,19 +251,15 @@ int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
     }
     SDL_PrivateJoystickAdded(hwdata->instance_id);
 
-    /* Return the new virtual-device's index */
-    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(hwdata->instance_id);
-    return device_index;
+    return hwdata->instance_id;
 }
 
-int SDL_JoystickDetachVirtualInner(int device_index)
+int SDL_JoystickDetachVirtualInner(SDL_JoystickID instance_id)
 {
-    SDL_JoystickID instance_id;
-    joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index);
+    joystick_hwdata *hwdata = VIRTUAL_HWDataForInstance(instance_id);
     if (hwdata == NULL) {
         return SDL_SetError("Virtual joystick data not found");
     }
-    instance_id = hwdata->instance_id;
     VIRTUAL_FreeHWData(hwdata);
     SDL_PrivateJoystickRemoved(instance_id);
     return 0;
@@ -260,7 +269,7 @@ int SDL_SetJoystickVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 val
 {
     joystick_hwdata *hwdata;
 
-    SDL_LockJoysticks();
+    SDL_AssertJoysticksLocked();
 
     if (joystick == NULL || !joystick->hwdata) {
         SDL_UnlockJoysticks();
@@ -275,7 +284,6 @@ int SDL_SetJoystickVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 val
 
     hwdata->axes[axis] = value;
 
-    SDL_UnlockJoysticks();
     return 0;
 }
 
@@ -283,7 +291,7 @@ int SDL_SetJoystickVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8
 {
     joystick_hwdata *hwdata;
 
-    SDL_LockJoysticks();
+    SDL_AssertJoysticksLocked();
 
     if (joystick == NULL || !joystick->hwdata) {
         SDL_UnlockJoysticks();
@@ -298,7 +306,6 @@ int SDL_SetJoystickVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8
 
     hwdata->buttons[button] = value;
 
-    SDL_UnlockJoysticks();
     return 0;
 }
 
@@ -306,7 +313,7 @@ int SDL_SetJoystickVirtualHatInner(SDL_Joystick *joystick, int hat, Uint8 value)
 {
     joystick_hwdata *hwdata;
 
-    SDL_LockJoysticks();
+    SDL_AssertJoysticksLocked();
 
     if (joystick == NULL || !joystick->hwdata) {
         SDL_UnlockJoysticks();
@@ -321,7 +328,6 @@ int SDL_SetJoystickVirtualHatInner(SDL_Joystick *joystick, int hat, Uint8 value)
 
     hwdata->hats[hat] = value;
 
-    SDL_UnlockJoysticks();
     return 0;
 }
 

+ 2 - 2
src/joystick/virtual/SDL_virtualjoystick_c.h

@@ -44,8 +44,8 @@ typedef struct joystick_hwdata
     struct joystick_hwdata *next;
 } joystick_hwdata;
 
-int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc);
-int SDL_JoystickDetachVirtualInner(int device_index);
+SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc);
+int SDL_JoystickDetachVirtualInner(SDL_JoystickID instance_id);
 
 int SDL_SetJoystickVirtualAxisInner(SDL_Joystick *joystick, int axis, Sint16 value);
 int SDL_SetJoystickVirtualButtonInner(SDL_Joystick *joystick, int button, Uint8 value);

+ 74 - 47
src/sensor/SDL_sensor.c

@@ -50,7 +50,7 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = {
 };
 static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */
 static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL;
-static SDL_atomic_t SDL_next_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock);
+static SDL_atomic_t SDL_last_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock);
 static SDL_bool SDL_updating_sensor SDL_GUARDED_BY(SDL_sensor_lock) = SDL_FALSE;
 
 void SDL_LockSensors(void) SDL_ACQUIRE(SDL_sensor_lock)
@@ -87,18 +87,57 @@ int SDL_InitSensors(void)
     return status;
 }
 
-/*
- * Count the number of sensors attached to the system
- */
-int SDL_GetNumSensors(void)
+SDL_bool SDL_HasSensors(void)
 {
-    int i, total_sensors = 0;
+    int i;
+    SDL_bool retval = SDL_FALSE;
     SDL_LockSensors();
     for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
-        total_sensors += SDL_sensor_drivers[i]->GetCount();
+        if (SDL_sensor_drivers[i]->GetCount() > 0) {
+            retval = SDL_TRUE;
+            break;
+        }
+    }
+    SDL_UnlockSensors();
+    return retval;
+}
+
+SDL_SensorID *SDL_GetSensors(int *count)
+{
+    int i, num_sensors, device_index;
+    int sensor_index = 0, total_sensors = 0;
+    SDL_SensorID *sensors;
+
+    SDL_LockSensors();
+    {
+        for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
+            total_sensors += SDL_sensor_drivers[i]->GetCount();
+        }
+
+        if (count) {
+            *count = total_sensors;
+        }
+
+        sensors = (SDL_SensorID *)SDL_malloc((total_sensors + 1) * sizeof(*sensors));
+        if (sensors) {
+            for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
+                num_sensors = SDL_sensor_drivers[i]->GetCount();
+                for (device_index = 0; device_index < num_sensors; ++device_index) {
+                    SDL_assert(sensor_index < total_sensors);
+                    sensors[sensor_index] = SDL_sensor_drivers[i]->GetDeviceInstanceID(device_index);
+                    SDL_assert(sensors[sensor_index] > 0);
+                    ++sensor_index;
+                }
+            }
+            SDL_assert(sensor_index == total_sensors);
+            sensors[sensor_index] = 0;
+        } else {
+            SDL_OutOfMemory();
+        }
     }
     SDL_UnlockSensors();
-    return total_sensors;
+
+    return sensors;
 }
 
 /*
@@ -107,44 +146,45 @@ int SDL_GetNumSensors(void)
  */
 SDL_SensorID SDL_GetNextSensorInstanceID()
 {
-    return SDL_AtomicIncRef(&SDL_next_sensor_instance_id);
+    return SDL_AtomicIncRef(&SDL_last_sensor_instance_id) + 1;
 }
 
 /*
- * Get the driver and device index for an API device index
+ * Get the driver and device index for a sensor instance ID
  * This should be called while the sensor lock is held, to prevent another thread from updating the list
  */
-static SDL_bool SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver **driver, int *driver_index)
+static SDL_bool SDL_GetDriverAndSensorIndex(SDL_SensorID instance_id, SDL_SensorDriver **driver, int *driver_index)
 {
-    int i, num_sensors, total_sensors = 0;
+    int i, num_sensors, device_index;
 
-    if (device_index >= 0) {
+    if (instance_id > 0) {
         for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
             num_sensors = SDL_sensor_drivers[i]->GetCount();
-            if (device_index < num_sensors) {
-                *driver = SDL_sensor_drivers[i];
-                *driver_index = device_index;
-                return SDL_TRUE;
+            for (device_index = 0; device_index < num_sensors; ++device_index) {
+                SDL_SensorID sensor_id = SDL_sensor_drivers[i]->GetDeviceInstanceID(device_index);
+                if (sensor_id == instance_id) {
+                    *driver = SDL_sensor_drivers[i];
+                    *driver_index = device_index;
+                    return SDL_TRUE;
+                }
             }
-            device_index -= num_sensors;
-            total_sensors += num_sensors;
         }
     }
-
-    SDL_SetError("There are %d sensors available", total_sensors);
+    SDL_SetError("Sensor %" SDL_PRIs32 " not found", instance_id);
     return SDL_FALSE;
 }
 
 /*
  * Get the implementation dependent name of a sensor
  */
-const char *SDL_GetSensorDeviceName(int device_index)
+const char *SDL_GetSensorInstanceName(SDL_SensorID instance_id)
 {
     SDL_SensorDriver *driver;
+    int device_index;
     const char *name = NULL;
 
     SDL_LockSensors();
-    if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) {
         name = driver->GetDeviceName(device_index);
     }
     SDL_UnlockSensors();
@@ -153,13 +193,14 @@ const char *SDL_GetSensorDeviceName(int device_index)
     return name;
 }
 
-SDL_SensorType SDL_GetSensorDeviceType(int device_index)
+SDL_SensorType SDL_GetSensorInstanceType(SDL_SensorID instance_id)
 {
     SDL_SensorDriver *driver;
+    int device_index;
     SDL_SensorType type = SDL_SENSOR_INVALID;
 
     SDL_LockSensors();
-    if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) {
         type = driver->GetDeviceType(device_index);
     }
     SDL_UnlockSensors();
@@ -167,13 +208,14 @@ SDL_SensorType SDL_GetSensorDeviceType(int device_index)
     return type;
 }
 
-int SDL_GetSensorDeviceNonPortableType(int device_index)
+int SDL_GetSensorInstanceNonPortableType(SDL_SensorID instance_id)
 {
     SDL_SensorDriver *driver;
+    int device_index;
     int type = -1;
 
     SDL_LockSensors();
-    if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
+    if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) {
         type = driver->GetDeviceNonPortableType(device_index);
     }
     SDL_UnlockSensors();
@@ -181,20 +223,6 @@ int SDL_GetSensorDeviceNonPortableType(int device_index)
     return type;
 }
 
-SDL_SensorID SDL_GetSensorDeviceInstanceID(int device_index)
-{
-    SDL_SensorDriver *driver;
-    SDL_SensorID instance_id = -1;
-
-    SDL_LockSensors();
-    if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
-        instance_id = driver->GetDeviceInstanceID(device_index);
-    }
-    SDL_UnlockSensors();
-
-    return instance_id;
-}
-
 /*
  * Open a sensor for use - the index passed as an argument refers to
  * the N'th sensor on the system.  This index is the value which will
@@ -202,17 +230,17 @@ SDL_SensorID SDL_GetSensorDeviceInstanceID(int device_index)
  *
  * This function returns a sensor identifier, or NULL if an error occurred.
  */
-SDL_Sensor *SDL_OpenSensor(int device_index)
+SDL_Sensor *SDL_OpenSensor(SDL_SensorID instance_id)
 {
     SDL_SensorDriver *driver;
-    SDL_SensorID instance_id;
+    int device_index;
     SDL_Sensor *sensor;
     SDL_Sensor *sensorlist;
     const char *sensorname = NULL;
 
     SDL_LockSensors();
 
-    if (!SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
+    if (!SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) {
         SDL_UnlockSensors();
         return NULL;
     }
@@ -221,7 +249,6 @@ SDL_Sensor *SDL_OpenSensor(int device_index)
     /* If the sensor is already open, return it
      * it is important that we have a single sensor * for each instance id
      */
-    instance_id = driver->GetDeviceInstanceID(device_index);
     while (sensorlist) {
         if (instance_id == sensorlist->instance_id) {
             sensor = sensorlist;
@@ -263,10 +290,10 @@ SDL_Sensor *SDL_OpenSensor(int device_index)
     sensor->next = SDL_sensors;
     SDL_sensors = sensor;
 
-    SDL_UnlockSensors();
-
     driver->Update(sensor);
 
+    SDL_UnlockSensors();
+
     return sensor;
 }
 

+ 3 - 0
src/sensor/SDL_sensor_c.h

@@ -34,6 +34,9 @@ extern SDL_SensorID SDL_GetNextSensorInstanceID(void);
 extern int SDL_InitSensors(void);
 extern void SDL_QuitSensors(void);
 
+extern void SDL_LockSensors(void);
+extern void SDL_UnlockSensors(void);
+
 /* Internal event queueing functions */
 extern int SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_timestamp, float *data, int num_values);
 

+ 15 - 15
src/test/SDL_test_common.c

@@ -1376,7 +1376,7 @@ static const char *DisplayOrientationName(int orientation)
     }
 }
 
-static const char *ControllerAxisName(const SDL_GamepadAxis axis)
+static const char *GamepadAxisName(const SDL_GamepadAxis axis)
 {
     switch (axis) {
 #define AXIS_CASE(ax)              \
@@ -1395,7 +1395,7 @@ static const char *ControllerAxisName(const SDL_GamepadAxis axis)
     }
 }
 
-static const char *ControllerButtonName(const SDL_GamepadButton button)
+static const char *GamepadButtonName(const SDL_GamepadButton button)
 {
     switch (button) {
 #define BUTTON_CASE(btn)              \
@@ -1548,11 +1548,11 @@ static void SDLTest_PrintEvent(SDL_Event *event)
                 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID);
         break;
     case SDL_JOYDEVICEADDED:
-        SDL_Log("SDL EVENT: Joystick index %" SDL_PRIs32 " attached",
+        SDL_Log("SDL EVENT: Joystick index %" SDL_PRIu32 " attached",
                 event->jdevice.which);
         break;
     case SDL_JOYDEVICEREMOVED:
-        SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 " removed",
+        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " removed",
                 event->jdevice.which);
         break;
     case SDL_JOYHATMOTION:
@@ -1587,41 +1587,41 @@ static void SDLTest_PrintEvent(SDL_Event *event)
             position = "LEFTUP";
             break;
         }
-        SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": hat %d moved to %s",
+        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": hat %d moved to %s",
                 event->jhat.which, event->jhat.hat, position);
     } break;
     case SDL_JOYBUTTONDOWN:
-        SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": button %d pressed",
+        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": button %d pressed",
                 event->jbutton.which, event->jbutton.button);
         break;
     case SDL_JOYBUTTONUP:
-        SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": button %d released",
+        SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": button %d released",
                 event->jbutton.which, event->jbutton.button);
         break;
     case SDL_GAMEPADADDED:
-        SDL_Log("SDL EVENT: Controller index %" SDL_PRIs32 " attached",
+        SDL_Log("SDL EVENT: Gamepad index %" SDL_PRIu32 " attached",
                 event->cdevice.which);
         break;
     case SDL_GAMEPADREMOVED:
-        SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " removed",
+        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " removed",
                 event->cdevice.which);
         break;
     case SDL_GAMEPADAXISMOTION:
-        SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " axis %d ('%s') value: %d",
+        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " axis %d ('%s') value: %d",
                 event->caxis.which,
                 event->caxis.axis,
-                ControllerAxisName((SDL_GamepadAxis)event->caxis.axis),
+                GamepadAxisName((SDL_GamepadAxis)event->caxis.axis),
                 event->caxis.value);
         break;
     case SDL_GAMEPADBUTTONDOWN:
-        SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 "button %d ('%s') down",
+        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 "button %d ('%s') down",
                 event->cbutton.which, event->cbutton.button,
-                ControllerButtonName((SDL_GamepadButton)event->cbutton.button));
+                GamepadButtonName((SDL_GamepadButton)event->cbutton.button));
         break;
     case SDL_GAMEPADBUTTONUP:
-        SDL_Log("SDL EVENT: Controller %" SDL_PRIs32 " button %d ('%s') up",
+        SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " button %d ('%s') up",
                 event->cbutton.which, event->cbutton.button,
-                ControllerButtonName((SDL_GamepadButton)event->cbutton.button));
+                GamepadButtonName((SDL_GamepadButton)event->cbutton.button));
         break;
     case SDL_CLIPBOARDUPDATE:
         SDL_Log("SDL EVENT: Clipboard updated");

+ 33 - 22
test/gamepadmap.c

@@ -704,8 +704,10 @@ int main(int argc, char *argv[])
 {
     const char *name;
     int i;
+    SDL_JoystickID *joysticks;
+    int num_joysticks = 0;
     int joystick_index;
-    SDL_Joystick *joystick;
+    SDL_Joystick *joystick = NULL;
 
     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
 
@@ -737,7 +739,7 @@ int main(int argc, char *argv[])
         return 2;
     }
 
-    while (!done && SDL_GetNumJoysticks() == 0) {
+    while (!done && !SDL_HasJoysticks()) {
         SDL_Event event;
 
         while (SDL_PollEvent(&event) > 0) {
@@ -758,25 +760,30 @@ int main(int argc, char *argv[])
     }
 
     /* Print information about the joysticks */
-    SDL_Log("There are %d joysticks attached\n", SDL_GetNumJoysticks());
-    for (i = 0; i < SDL_GetNumJoysticks(); ++i) {
-        name = SDL_GetJoystickNameForIndex(i);
-        SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
-        joystick = SDL_OpenJoystick(i);
-        if (joystick == NULL) {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_OpenJoystick(%d) failed: %s\n", i,
-                         SDL_GetError());
-        } else {
-            char guid[64];
-            SDL_GetJoystickGUIDString(SDL_GetJoystickGUID(joystick),
-                                      guid, sizeof(guid));
-            SDL_Log("       axes: %d\n", SDL_GetNumJoystickAxes(joystick));
-            SDL_Log("       hats: %d\n", SDL_GetNumJoystickHats(joystick));
-            SDL_Log("    buttons: %d\n", SDL_GetNumJoystickButtons(joystick));
-            SDL_Log("instance id: %" SDL_PRIu32 "\n", SDL_GetJoystickInstanceID(joystick));
-            SDL_Log("       guid: %s\n", guid);
-            SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_GetJoystickVendor(joystick), SDL_GetJoystickProduct(joystick));
-            SDL_CloseJoystick(joystick);
+    joysticks = SDL_GetJoysticks(&num_joysticks);
+    if (joysticks) {
+        SDL_Log("There are %d joysticks attached\n", num_joysticks);
+        for (i = 0; joysticks[i]; ++i) {
+            SDL_JoystickID instance_id = joysticks[i];
+
+            name = SDL_GetJoystickInstanceName(instance_id);
+            SDL_Log("Joystick %" SDL_PRIu32 ": %s\n", instance_id, name ? name : "Unknown Joystick");
+            joystick = SDL_OpenJoystick(instance_id);
+            if (joystick == NULL) {
+                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_OpenJoystick(%" SDL_PRIu32 ") failed: %s\n", instance_id,
+                             SDL_GetError());
+            } else {
+                char guid[64];
+                SDL_GetJoystickGUIDString(SDL_GetJoystickGUID(joystick),
+                                          guid, sizeof(guid));
+                SDL_Log("       axes: %d\n", SDL_GetNumJoystickAxes(joystick));
+                SDL_Log("       hats: %d\n", SDL_GetNumJoystickHats(joystick));
+                SDL_Log("    buttons: %d\n", SDL_GetNumJoystickButtons(joystick));
+                SDL_Log("instance id: %" SDL_PRIu32 "\n", instance_id);
+                SDL_Log("       guid: %s\n", guid);
+                SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_GetJoystickVendor(joystick), SDL_GetJoystickProduct(joystick));
+                SDL_CloseJoystick(joystick);
+            }
         }
     }
 
@@ -787,7 +794,9 @@ int main(int argc, char *argv[])
             break;
         }
     }
-    joystick = SDL_OpenJoystick(joystick_index);
+    if (joysticks && joystick_index < num_joysticks) {
+        joystick = SDL_OpenJoystick(joysticks[joystick_index]);
+    }
     if (joystick == NULL) {
         SDL_Log("Couldn't open joystick %d: %s\n", joystick_index, SDL_GetError());
     } else {
@@ -795,6 +804,8 @@ int main(int argc, char *argv[])
         SDL_CloseJoystick(joystick);
     }
 
+    SDL_free(joysticks);
+
     SDL_DestroyWindow(window);
 
     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);

+ 8 - 8
test/testautomation_joystick.c

@@ -20,7 +20,7 @@ TestVirtualJoystick(void *arg)
 {
     SDL_VirtualJoystickDesc desc;
     SDL_Joystick *joystick = NULL;
-    int device_index;
+    SDL_JoystickID device_id;
 
     SDLTest_AssertCheck(SDL_InitSubSystem(SDL_INIT_GAMEPAD) == 0, "SDL_InitSubSystem(SDL_INIT_GAMEPAD)");
 
@@ -32,11 +32,11 @@ TestVirtualJoystick(void *arg)
     desc.vendor_id = USB_VENDOR_NVIDIA;
     desc.product_id = USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V104;
     desc.name = "Virtual NVIDIA SHIELD Controller";
-    device_index = SDL_AttachVirtualJoystickEx(&desc);
-    SDLTest_AssertCheck(device_index >= 0, "SDL_AttachVirtualJoystickEx()");
-    SDLTest_AssertCheck(SDL_IsJoystickVirtual(device_index), "SDL_IsJoystickVirtual()");
-    if (device_index >= 0) {
-        joystick = SDL_OpenJoystick(device_index);
+    device_id = SDL_AttachVirtualJoystickEx(&desc);
+    SDLTest_AssertCheck(device_id > 0, "SDL_AttachVirtualJoystickEx()");
+    SDLTest_AssertCheck(SDL_IsJoystickVirtual(device_id), "SDL_IsJoystickVirtual()");
+    if (device_id > 0) {
+        joystick = SDL_OpenJoystick(device_id);
         SDLTest_AssertCheck(joystick != NULL, "SDL_OpenJoystick()");
         if (joystick) {
             SDLTest_AssertCheck(SDL_strcmp(SDL_GetJoystickName(joystick), desc.name) == 0, "SDL_GetJoystickName()");
@@ -59,9 +59,9 @@ TestVirtualJoystick(void *arg)
 
             SDL_CloseJoystick(joystick);
         }
-        SDLTest_AssertCheck(SDL_DetachVirtualJoystick(device_index) == 0, "SDL_DetachVirtualJoystick()");
+        SDLTest_AssertCheck(SDL_DetachVirtualJoystick(device_id) == 0, "SDL_DetachVirtualJoystick()");
     }
-    SDLTest_AssertCheck(!SDL_IsJoystickVirtual(device_index), "!SDL_IsJoystickVirtual()");
+    SDLTest_AssertCheck(!SDL_IsJoystickVirtual(device_id), "!SDL_IsJoystickVirtual()");
 
     SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
 

+ 89 - 83
test/testgamepad.c

@@ -165,9 +165,8 @@ static int FindGamepad(SDL_JoystickID gamepad_id)
     return -1;
 }
 
-static void AddGamepad(int device_index, SDL_bool verbose)
+static void AddGamepad(SDL_JoystickID gamepad_id, SDL_bool verbose)
 {
-    SDL_JoystickID gamepad_id = SDL_GetJoystickDeviceInstanceID(device_index);
     SDL_Gamepad **new_gamepads;
     SDL_Gamepad *new_gamepad;
     Uint16 firmware_version;
@@ -181,18 +180,12 @@ static void AddGamepad(int device_index, SDL_bool verbose)
     };
     unsigned int i;
 
-    gamepad_id = SDL_GetJoystickDeviceInstanceID(device_index);
-    if (gamepad_id < 0) {
-        SDL_Log("Couldn't get gamepad ID: %s\n", SDL_GetError());
-        return;
-    }
-
     if (FindGamepad(gamepad_id) >= 0) {
         /* We already have this gamepad */
         return;
     }
 
-    new_gamepad = SDL_OpenGamepad(device_index);
+    new_gamepad = SDL_OpenGamepad(gamepad_id);
     if (new_gamepad == NULL) {
         SDL_Log("Couldn't open gamepad: %s\n", SDL_GetError());
         return;
@@ -388,7 +381,7 @@ static int SDLCALL VirtualGamepadSetLED(void *userdata, Uint8 red, Uint8 green,
 static void OpenVirtualGamepad()
 {
     SDL_VirtualJoystickDesc desc;
-    int virtual_index;
+    SDL_JoystickID virtual_id;
 
     SDL_zero(desc);
     desc.version = SDL_VIRTUAL_JOYSTICK_DESC_VERSION;
@@ -400,11 +393,11 @@ static void OpenVirtualGamepad()
     desc.RumbleTriggers = VirtualGamepadRumbleTriggers;
     desc.SetLED = VirtualGamepadSetLED;
 
-    virtual_index = SDL_AttachVirtualJoystickEx(&desc);
-    if (virtual_index < 0) {
-        SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError());
+    virtual_id = SDL_AttachVirtualJoystickEx(&desc);
+    if (virtual_id == 0) {
+        SDL_Log("Couldn't attach virtual device: %s\n", SDL_GetError());
     } else {
-        virtual_joystick = SDL_OpenJoystick(virtual_index);
+        virtual_joystick = SDL_OpenJoystick(virtual_id);
         if (virtual_joystick == NULL) {
             SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError());
         }
@@ -414,11 +407,15 @@ static void OpenVirtualGamepad()
 static void CloseVirtualGamepad()
 {
     int i;
-
-    for (i = SDL_GetNumJoysticks(); i--;) {
-        if (SDL_IsJoystickVirtual(i)) {
-            SDL_DetachVirtualJoystick(i);
+    SDL_JoystickID *joysticks = SDL_GetJoysticks(NULL);
+    if (joysticks) {
+        for (i = 0; joysticks[i]; ++i) {
+            SDL_JoystickID instance_id = joysticks[i];
+            if (SDL_IsJoystickVirtual(instance_id)) {
+                SDL_DetachVirtualJoystick(instance_id);
+            }
         }
+        SDL_free(joysticks);
     }
 
     if (virtual_joystick) {
@@ -566,19 +563,19 @@ void loop(void *arg)
     while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1) {
         switch (event.type) {
         case SDL_GAMEPADADDED:
-            SDL_Log("Gamepad device %d added.\n", (int)SDL_GetJoystickDeviceInstanceID(event.cdevice.which));
+            SDL_Log("Gamepad device %" SDL_PRIu32 " added.\n", event.cdevice.which);
             AddGamepad(event.cdevice.which, SDL_TRUE);
             break;
 
         case SDL_GAMEPADREMOVED:
-            SDL_Log("Gamepad device %d removed.\n", (int)event.cdevice.which);
+            SDL_Log("Gamepad device %" SDL_PRIu32 " removed.\n", event.cdevice.which);
             DelGamepad(event.cdevice.which);
             break;
 
         case SDL_GAMEPADTOUCHPADDOWN:
         case SDL_GAMEPADTOUCHPADMOTION:
         case SDL_GAMEPADTOUCHPADUP:
-            SDL_Log("Gamepad %" SDL_PRIs32 " touchpad %" SDL_PRIs32 " finger %" SDL_PRIs32 " %s %.2f, %.2f, %.2f\n",
+            SDL_Log("Gamepad %" SDL_PRIu32 " touchpad %" SDL_PRIs32 " finger %" SDL_PRIs32 " %s %.2f, %.2f, %.2f\n",
                     event.ctouchpad.which,
                     event.ctouchpad.touchpad,
                     event.ctouchpad.finger,
@@ -591,7 +588,7 @@ void loop(void *arg)
 #define VERBOSE_SENSORS
 #ifdef VERBOSE_SENSORS
         case SDL_GAMEPADSENSORUPDATE:
-            SDL_Log("Gamepad %" SDL_PRIs32 " sensor %s: %.2f, %.2f, %.2f (%" SDL_PRIu64 ")\n",
+            SDL_Log("Gamepad %" SDL_PRIu32 " sensor %s: %.2f, %.2f, %.2f (%" SDL_PRIu64 ")\n",
                     event.csensor.which,
                     GetSensorName((SDL_SensorType)event.csensor.sensor),
                     event.csensor.data[0],
@@ -607,7 +604,7 @@ void loop(void *arg)
             if (event.caxis.value <= (-SDL_JOYSTICK_AXIS_MAX / 2) || event.caxis.value >= (SDL_JOYSTICK_AXIS_MAX / 2)) {
                 SetGamepad(event.caxis.which);
             }
-            SDL_Log("Gamepad %" SDL_PRIs32 " axis %s changed to %d\n", event.caxis.which, SDL_GetGamepadStringForAxis((SDL_GamepadAxis)event.caxis.axis), event.caxis.value);
+            SDL_Log("Gamepad %" SDL_PRIu32 " axis %s changed to %d\n", event.caxis.which, SDL_GetGamepadStringForAxis((SDL_GamepadAxis)event.caxis.axis), event.caxis.value);
             break;
 #endif /* VERBOSE_AXES */
 
@@ -616,7 +613,7 @@ void loop(void *arg)
             if (event.type == SDL_GAMEPADBUTTONDOWN) {
                 SetGamepad(event.cbutton.which);
             }
-            SDL_Log("Gamepad %" SDL_PRIs32 " button %s %s\n", event.cbutton.which, SDL_GetGamepadStringForButton((SDL_GamepadButton)event.cbutton.button), event.cbutton.state ? "pressed" : "released");
+            SDL_Log("Gamepad %" SDL_PRIu32 " button %s %s\n", event.cbutton.which, SDL_GetGamepadStringForButton((SDL_GamepadButton)event.cbutton.button), event.cbutton.state ? "pressed" : "released");
 
             /* Cycle PS5 trigger effects when the microphone button is pressed */
             if (event.type == SDL_GAMEPADBUTTONDOWN &&
@@ -627,7 +624,7 @@ void loop(void *arg)
             break;
 
         case SDL_JOYBATTERYUPDATED:
-            SDL_Log("Gamepad %" SDL_PRIs32 " battery state changed to %s\n", event.jbattery.which, power_level_strings[event.jbattery.level + 1]);
+            SDL_Log("Gamepad %" SDL_PRIu32 " battery state changed to %s\n", event.jbattery.which, power_level_strings[event.jbattery.level + 1]);
             break;
 
         case SDL_MOUSEBUTTONDOWN:
@@ -786,6 +783,8 @@ void loop(void *arg)
 int main(int argc, char *argv[])
 {
     int i;
+    SDL_JoystickID *joysticks;
+    int joystick_count = 0;
     int gamepad_count = 0;
     int gamepad_index = 0;
     char guid[64];
@@ -822,67 +821,74 @@ int main(int argc, char *argv[])
         SDL_Log("\n");
     }
 
-    /* Print information about the gamepad */
-    for (i = 0; i < SDL_GetNumJoysticks(); ++i) {
-        const char *name;
-        const char *path;
-        const char *description;
-
-        SDL_GetJoystickGUIDString(SDL_GetJoystickDeviceGUID(i),
-                                  guid, sizeof(guid));
-
-        if (SDL_IsGamepad(i)) {
-            gamepad_count++;
-            name = SDL_GetGamepadNameForIndex(i);
-            path = SDL_GetGamepadPathForIndex(i);
-            switch (SDL_GetGamepadTypeForIndex(i)) {
-            case SDL_GAMEPAD_TYPE_AMAZON_LUNA:
-                description = "Amazon Luna Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_GOOGLE_STADIA:
-                description = "Google Stadia Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
-            case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
-            case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
-                description = "Nintendo Switch Joy-Con";
-                break;
-            case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
-                description = "Nintendo Switch Pro Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_PS3:
-                description = "PS3 Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_PS4:
-                description = "PS4 Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_PS5:
-                description = "PS5 Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_XBOX360:
-                description = "XBox 360 Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_XBOXONE:
-                description = "XBox One Controller";
-                break;
-            case SDL_GAMEPAD_TYPE_VIRTUAL:
-                description = "Virtual Gamepad";
-                break;
-            default:
-                description = "Gamepad";
-                break;
+    /* Print information about the gamepads */
+    joysticks = SDL_GetJoysticks(&joystick_count);
+    if (joysticks) {
+        for (i = 0; joysticks[i]; ++i) {
+            SDL_JoystickID instance_id = joysticks[i];
+            const char *name;
+            const char *path;
+            const char *description;
+
+            SDL_GetJoystickGUIDString(SDL_GetJoystickInstanceGUID(instance_id),
+                                      guid, sizeof(guid));
+
+            if (SDL_IsGamepad(instance_id)) {
+                gamepad_count++;
+                name = SDL_GetGamepadInstanceName(instance_id);
+                path = SDL_GetGamepadInstancePath(instance_id);
+                switch (SDL_GetGamepadInstanceType(instance_id)) {
+                case SDL_GAMEPAD_TYPE_AMAZON_LUNA:
+                    description = "Amazon Luna Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_GOOGLE_STADIA:
+                    description = "Google Stadia Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
+                case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
+                case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
+                    description = "Nintendo Switch Joy-Con";
+                    break;
+                case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
+                    description = "Nintendo Switch Pro Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_PS3:
+                    description = "PS3 Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_PS4:
+                    description = "PS4 Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_PS5:
+                    description = "PS5 Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_XBOX360:
+                    description = "XBox 360 Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_XBOXONE:
+                    description = "XBox One Controller";
+                    break;
+                case SDL_GAMEPAD_TYPE_VIRTUAL:
+                    description = "Virtual Gamepad";
+                    break;
+                default:
+                    description = "Gamepad";
+                    break;
+                }
+                AddGamepad(instance_id, SDL_FALSE);
+            } else {
+                name = SDL_GetJoystickInstanceName(instance_id);
+                path = SDL_GetJoystickInstancePath(instance_id);
+                description = "Joystick";
             }
-            AddGamepad(i, SDL_FALSE);
-        } else {
-            name = SDL_GetJoystickNameForIndex(i);
-            path = SDL_GetJoystickPathForIndex(i);
-            description = "Joystick";
+            SDL_Log("%s %d: %s%s%s (guid %s, VID 0x%.4x, PID 0x%.4x, player index = %d)\n",
+                    description, i, name ? name : "Unknown", path ? ", " : "", path ? path : "", guid,
+                    SDL_GetJoystickInstanceVendor(instance_id),
+                    SDL_GetJoystickInstanceProduct(instance_id),
+                    SDL_GetJoystickInstancePlayerIndex(instance_id));
         }
-        SDL_Log("%s %d: %s%s%s (guid %s, VID 0x%.4x, PID 0x%.4x, player index = %d)\n",
-                description, i, name ? name : "Unknown", path ? ", " : "", path ? path : "", guid,
-                SDL_GetJoystickDeviceVendor(i), SDL_GetJoystickDeviceProduct(i), SDL_GetJoystickDevicePlayerIndex(i));
+        SDL_free(joysticks);
     }
-    SDL_Log("There are %d gamepad(s) attached (%d joystick(s))\n", gamepad_count, SDL_GetNumJoysticks());
+    SDL_Log("There are %d gamepad(s) attached (%d joystick(s))\n", gamepad_count, joystick_count);
 
     /* Create a window to display gamepad state */
     window = SDL_CreateWindow("Gamepad Test", SDL_WINDOWPOS_CENTERED,

+ 7 - 5
test/testhotplug.c

@@ -19,9 +19,10 @@
 
 int main(int argc, char *argv[])
 {
+    int num_joysticks = 0;
     SDL_Joystick *joystick = NULL;
     SDL_Haptic *haptic = NULL;
-    SDL_JoystickID instance = -1;
+    SDL_JoystickID instance = 0;
     SDL_bool keepGoing = SDL_TRUE;
     int i;
     SDL_bool enable_haptic = SDL_TRUE;
@@ -52,7 +53,8 @@ int main(int argc, char *argv[])
     //SDL_CreateWindow("Dummy", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 128, 128, 0);
     */
 
-    SDL_Log("There are %d joysticks at startup\n", SDL_GetNumJoysticks());
+    SDL_free(SDL_GetJoysticks(&num_joysticks));
+    SDL_Log("There are %d joysticks at startup\n", num_joysticks);
     if (enable_haptic) {
         SDL_Log("There are %d haptic devices at startup\n", SDL_NumHaptics());
     }
@@ -69,8 +71,8 @@ int main(int argc, char *argv[])
                     SDL_Log("Only one joystick supported by this test\n");
                 } else {
                     joystick = SDL_OpenJoystick(event.jdevice.which);
-                    instance = SDL_GetJoystickInstanceID(joystick);
-                    SDL_Log("Joy Added  : %" SDL_PRIs32 " : %s\n", event.jdevice.which, SDL_GetJoystickName(joystick));
+                    instance = event.jdevice.which;
+                    SDL_Log("Joy Added  : %" SDL_PRIu32 " : %s\n", event.jdevice.which, SDL_GetJoystickName(joystick));
                     if (enable_haptic) {
                         if (SDL_JoystickIsHaptic(joystick)) {
                             haptic = SDL_HapticOpenFromJoystick(joystick);
@@ -93,7 +95,7 @@ int main(int argc, char *argv[])
             case SDL_JOYDEVICEREMOVED:
                 if (instance == event.jdevice.which) {
                     SDL_Log("Joy Removed: %" SDL_PRIs32 "\n", event.jdevice.which);
-                    instance = -1;
+                    instance = 0;
                     if (enable_haptic && haptic) {
                         SDL_HapticClose(haptic);
                         haptic = NULL;

+ 23 - 8
test/testjoystick.c

@@ -83,7 +83,7 @@ PrintJoystick(SDL_Joystick *joy)
     SDL_Log("          axes: %d\n", SDL_GetNumJoystickAxes(joy));
     SDL_Log("          hats: %d\n", SDL_GetNumJoystickHats(joy));
     SDL_Log("       buttons: %d\n", SDL_GetNumJoystickButtons(joy));
-    SDL_Log("   instance id: %" SDL_PRIs32 "\n", SDL_GetJoystickInstanceID(joy));
+    SDL_Log("   instance id: %" SDL_PRIu32 "\n", SDL_GetJoystickInstanceID(joy));
     SDL_Log("          guid: %s\n", guid);
     SDL_Log("       VID/PID: 0x%.4x/0x%.4x\n", SDL_GetJoystickVendor(joy), SDL_GetJoystickProduct(joy));
 }
@@ -112,7 +112,7 @@ void loop(void *arg)
         switch (event.type) {
 
         case SDL_JOYDEVICEADDED:
-            SDL_Log("Joystick device %d added.\n", (int)event.jdevice.which);
+            SDL_Log("Joystick device %" SDL_PRIu32 " added.\n", event.jdevice.which);
             if (joystick == NULL) {
                 joystick = SDL_OpenJoystick(event.jdevice.which);
                 if (joystick) {
@@ -124,20 +124,35 @@ void loop(void *arg)
             break;
 
         case SDL_JOYDEVICEREMOVED:
-            SDL_Log("Joystick device %d removed.\n", (int)event.jdevice.which);
+            SDL_Log("Joystick device %" SDL_PRIu32 " removed.\n", event.jdevice.which);
             if (event.jdevice.which == SDL_GetJoystickInstanceID(joystick)) {
+                SDL_JoystickID *joysticks;
+
                 SDL_CloseJoystick(joystick);
-                joystick = SDL_OpenJoystick(0);
+                joystick = NULL;
+
+                joysticks = SDL_GetJoysticks(NULL);
+                if (joysticks) {
+                    if (joysticks[0]) {
+                        joystick = SDL_OpenJoystick(joysticks[0]);
+                        if (joystick) {
+                            PrintJoystick(joystick);
+                        } else {
+                            SDL_Log("Couldn't open joystick: %s\n", SDL_GetError());
+                        }
+                    }
+                    SDL_free(joysticks);
+                }
             }
             break;
 
         case SDL_JOYAXISMOTION:
-            SDL_Log("Joystick %" SDL_PRIs32 " axis %d value: %d\n",
+            SDL_Log("Joystick %" SDL_PRIu32 " axis %d value: %d\n",
                     event.jaxis.which,
                     event.jaxis.axis, event.jaxis.value);
             break;
         case SDL_JOYHATMOTION:
-            SDL_Log("Joystick %" SDL_PRIs32 " hat %d value:",
+            SDL_Log("Joystick %" SDL_PRIu32 " hat %d value:",
                     event.jhat.which, event.jhat.hat);
             if (event.jhat.value == SDL_HAT_CENTERED) {
                 SDL_Log(" centered");
@@ -157,7 +172,7 @@ void loop(void *arg)
             SDL_Log("\n");
             break;
         case SDL_JOYBUTTONDOWN:
-            SDL_Log("Joystick %" SDL_PRIs32 " button %d down\n",
+            SDL_Log("Joystick %" SDL_PRIu32 " button %d down\n",
                     event.jbutton.which, event.jbutton.button);
             /* First button triggers a 0.5 second full strength rumble */
             if (event.jbutton.button == 0) {
@@ -165,7 +180,7 @@ void loop(void *arg)
             }
             break;
         case SDL_JOYBUTTONUP:
-            SDL_Log("Joystick %" SDL_PRIs32 " button %d up\n",
+            SDL_Log("Joystick %" SDL_PRIu32 " button %d up\n",
                     event.jbutton.which, event.jbutton.button);
             break;
         case SDL_KEYDOWN:

+ 19 - 16
test/testsensor.c

@@ -57,8 +57,8 @@ static void HandleSensorEvent(SDL_SensorEvent *event)
 
 int main(int argc, char **argv)
 {
-    int i;
-    int num_sensors, num_opened;
+    SDL_SensorID *sensors;
+    int i, num_sensors, num_opened;
 
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_SENSOR) < 0) {
@@ -66,25 +66,28 @@ int main(int argc, char **argv)
         return 1;
     }
 
-    num_sensors = SDL_GetNumSensors();
+    sensors = SDL_GetSensors(&num_sensors);
     num_opened = 0;
 
     SDL_Log("There are %d sensors available\n", num_sensors);
-    for (i = 0; i < num_sensors; ++i) {
-        SDL_Log("Sensor %" SDL_PRIs32 ": %s, type %s, platform type %d\n",
-                SDL_GetSensorDeviceInstanceID(i),
-                SDL_GetSensorDeviceName(i),
-                GetSensorTypeString(SDL_GetSensorDeviceType(i)),
-                SDL_GetSensorDeviceNonPortableType(i));
-
-        if (SDL_GetSensorDeviceType(i) != SDL_SENSOR_UNKNOWN) {
-            SDL_Sensor *sensor = SDL_OpenSensor(i);
-            if (sensor == NULL) {
-                SDL_Log("Couldn't open sensor %" SDL_PRIs32 ": %s\n", SDL_GetSensorDeviceInstanceID(i), SDL_GetError());
-            } else {
-                ++num_opened;
+    if (sensors) {
+        for (i = 0; i < num_sensors; ++i) {
+            SDL_Log("Sensor %" SDL_PRIu32 ": %s, type %s, platform type %d\n",
+                    sensors[i],
+                    SDL_GetSensorInstanceName(sensors[i]),
+                    GetSensorTypeString(SDL_GetSensorInstanceType(sensors[i])),
+                    SDL_GetSensorInstanceNonPortableType(sensors[i]));
+
+            if (SDL_GetSensorInstanceType(sensors[i]) != SDL_SENSOR_UNKNOWN) {
+                SDL_Sensor *sensor = SDL_OpenSensor(sensors[i]);
+                if (sensor == NULL) {
+                    SDL_Log("Couldn't open sensor %" SDL_PRIu32 ": %s\n", sensors[i], SDL_GetError());
+                } else {
+                    ++num_opened;
+                }
             }
         }
+        SDL_free(sensors);
     }
     SDL_Log("Opened %d sensors\n", num_opened);