From dec7875a6e23212021e4d9080330a42832dfe02a Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Tue, 15 Jun 2021 01:40:19 +0000
Subject: [PATCH] update SDL soruce to 2.0.14
---
source/src/joystick/SDL_joystick.c | 806 +++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 690 insertions(+), 116 deletions(-)
diff --git a/source/src/joystick/SDL_joystick.c b/source/src/joystick/SDL_joystick.c
index 95aac9c..32eb7c2 100644
--- a/source/src/joystick/SDL_joystick.c
+++ b/source/src/joystick/SDL_joystick.c
@@ -26,7 +26,6 @@
#include "SDL_atomic.h"
#include "SDL_events.h"
#include "SDL_sysjoystick.h"
-#include "SDL_assert.h"
#include "SDL_hints.h"
#if !SDL_EVENTS_DISABLED
@@ -46,7 +45,20 @@
#include <tlhelp32.h>
#endif
+#if SDL_JOYSTICK_VIRTUAL
+#include "./virtual/SDL_virtualjoystick_c.h"
+#endif
+
static SDL_JoystickDriver *SDL_joystick_drivers[] = {
+#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
+ &SDL_HIDAPI_JoystickDriver,
+#endif
+#ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */
+ &SDL_RAWINPUT_JoystickDriver,
+#endif
+#if defined(SDL_JOYSTICK_WGI)
+ &SDL_WGI_JoystickDriver,
+#endif
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
&SDL_WINDOWS_JoystickDriver,
#endif
@@ -56,7 +68,7 @@
#ifdef SDL_JOYSTICK_IOKIT
&SDL_DARWIN_JoystickDriver,
#endif
-#if defined(__IPHONEOS__) || defined(__TVOS__)
+#if (defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)) && !defined(SDL_JOYSTICK_DISABLED)
&SDL_IOS_JoystickDriver,
#endif
#ifdef SDL_JOYSTICK_ANDROID
@@ -71,8 +83,8 @@
#ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
&SDL_BSD_JoystickDriver,
#endif
-#ifdef SDL_JOYSTICK_HIDAPI
- &SDL_HIDAPI_JoystickDriver,
+#ifdef SDL_JOYSTICK_VIRTUAL
+ &SDL_VIRTUAL_JoystickDriver,
#endif
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
&SDL_DUMMY_JoystickDriver
@@ -279,23 +291,6 @@
}
/*
- * Perform any needed fixups for joystick names
- */
-static const char *
-SDL_FixupJoystickName(const char *name)
-{
- if (name) {
- const char *skip_prefix = "NVIDIA Corporation ";
-
- if (SDL_strncmp(name, skip_prefix, SDL_strlen(skip_prefix)) == 0) {
- name += SDL_strlen(skip_prefix);
- }
- }
- return name;
-}
-
-
-/*
* Get the implementation dependent name of a joystick
*/
const char *
@@ -306,7 +301,7 @@
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
- name = SDL_FixupJoystickName(driver->GetDeviceName(device_index));
+ name = driver->GetDeviceName(device_index);
}
SDL_UnlockJoysticks();
@@ -472,12 +467,96 @@
return joystick;
}
+int
+SDL_JoystickAttachVirtual(SDL_JoystickType type,
+ int naxes, int nbuttons, int nhats)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ return SDL_JoystickAttachVirtualInner(type, naxes, nbuttons, nhats);
+#else
+ return SDL_SetError("SDL not built with virtual-joystick support");
+#endif
+}
+
+int
+SDL_JoystickDetachVirtual(int device_index)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ SDL_JoystickDriver *driver;
+
+ SDL_LockJoysticks();
+ if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+ if (driver == &SDL_VIRTUAL_JoystickDriver) {
+ const int result = SDL_JoystickDetachVirtualInner(device_index);
+ SDL_UnlockJoysticks();
+ return result;
+ }
+ }
+ SDL_UnlockJoysticks();
+
+ return SDL_SetError("Virtual joystick not found at provided index");
+#else
+ return SDL_SetError("SDL not built with virtual-joystick support");
+#endif
+}
+
+SDL_bool
+SDL_JoystickIsVirtual(int device_index)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ SDL_JoystickDriver *driver;
+ int driver_device_index;
+ SDL_bool is_virtual = SDL_FALSE;
+
+ SDL_LockJoysticks();
+ if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
+ if (driver == &SDL_VIRTUAL_JoystickDriver) {
+ is_virtual = SDL_TRUE;
+ }
+ }
+ SDL_UnlockJoysticks();
+
+ return is_virtual;
+#else
+ return SDL_FALSE;
+#endif
+}
+
+int
+SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ return SDL_JoystickSetVirtualAxisInner(joystick, axis, value);
+#else
+ return SDL_SetError("SDL not built with virtual-joystick support");
+#endif
+}
+
+int
+SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ return SDL_JoystickSetVirtualButtonInner(joystick, button, value);
+#else
+ return SDL_SetError("SDL not built with virtual-joystick support");
+#endif
+}
+
+int
+SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value)
+{
+#if SDL_JOYSTICK_VIRTUAL
+ return SDL_JoystickSetVirtualHatInner(joystick, hat, value);
+#else
+ return SDL_SetError("SDL not built with virtual-joystick support");
+#endif
+}
/*
* Checks to make sure the joystick is valid.
*/
SDL_bool
-SDL_PrivateJoystickValid(SDL_Joystick * joystick)
+SDL_PrivateJoystickValid(SDL_Joystick *joystick)
{
SDL_bool valid;
@@ -491,11 +570,26 @@
return valid;
}
+SDL_bool
+SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping * out)
+{
+ SDL_JoystickDriver *driver;
+ SDL_bool is_ok = SDL_FALSE;
+
+ SDL_LockJoysticks();
+ if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
+ is_ok = driver->GetGamepadMapping(device_index, out);
+ }
+ SDL_UnlockJoysticks();
+
+ return is_ok;
+}
+
/*
* Get the number of multi-dimensional axis controls on a joystick
*/
int
-SDL_JoystickNumAxes(SDL_Joystick * joystick)
+SDL_JoystickNumAxes(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
@@ -507,7 +601,7 @@
* Get the number of hats on a joystick
*/
int
-SDL_JoystickNumHats(SDL_Joystick * joystick)
+SDL_JoystickNumHats(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
@@ -519,7 +613,7 @@
* Get the number of trackballs on a joystick
*/
int
-SDL_JoystickNumBalls(SDL_Joystick * joystick)
+SDL_JoystickNumBalls(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
@@ -531,7 +625,7 @@
* Get the number of buttons on a joystick
*/
int
-SDL_JoystickNumButtons(SDL_Joystick * joystick)
+SDL_JoystickNumButtons(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
@@ -543,7 +637,7 @@
* Get the current state of an axis control on a joystick
*/
Sint16
-SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
+SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis)
{
Sint16 state;
@@ -563,7 +657,7 @@
* Get the initial state of an axis control on a joystick
*/
SDL_bool
-SDL_JoystickGetAxisInitialState(SDL_Joystick * joystick, int axis, Sint16 *state)
+SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return SDL_FALSE;
@@ -582,7 +676,7 @@
* Get the current state of a hat on a joystick
*/
Uint8
-SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
+SDL_JoystickGetHat(SDL_Joystick *joystick, int hat)
{
Uint8 state;
@@ -602,7 +696,7 @@
* Get the ball axis change since the last poll
*/
int
-SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
+SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy)
{
int retval;
@@ -630,7 +724,7 @@
* Get the current state of a button on a joystick
*/
Uint8
-SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
+SDL_JoystickGetButton(SDL_Joystick *joystick, int button)
{
Uint8 state;
@@ -651,7 +745,7 @@
* \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
*/
SDL_bool
-SDL_JoystickGetAttached(SDL_Joystick * joystick)
+SDL_JoystickGetAttached(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return SDL_FALSE;
@@ -664,7 +758,7 @@
* Get the instance id for this opened joystick
*/
SDL_JoystickID
-SDL_JoystickInstanceID(SDL_Joystick * joystick)
+SDL_JoystickInstanceID(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
@@ -715,20 +809,20 @@
* Get the friendly name of this joystick
*/
const char *
-SDL_JoystickName(SDL_Joystick * joystick)
+SDL_JoystickName(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return NULL;
}
- return SDL_FixupJoystickName(joystick->name);
+ return joystick->name;
}
/**
* Get the player index of an opened joystick, or -1 if it's not available
*/
int
-SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)
+SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick)
{
int player_index;
@@ -747,7 +841,7 @@
* Set the player index of an opened joystick
*/
void
-SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
+SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return;
@@ -759,7 +853,7 @@
}
int
-SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
+SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{
int result;
@@ -793,14 +887,97 @@
return result;
}
+int
+SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms)
+{
+ int result;
+
+ if (!SDL_PrivateJoystickValid(joystick)) {
+ return -1;
+ }
+
+ SDL_LockJoysticks();
+ if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) {
+ /* Just update the expiration */
+ result = 0;
+ } else {
+ result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
+ }
+
+ /* Save the rumble value regardless of success, so we don't spam the driver */
+ joystick->left_trigger_rumble = left_rumble;
+ joystick->right_trigger_rumble = right_rumble;
+
+ if ((left_rumble || right_rumble) && duration_ms) {
+ joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
+ if (!joystick->trigger_rumble_expiration) {
+ joystick->trigger_rumble_expiration = 1;
+ }
+ } else {
+ joystick->trigger_rumble_expiration = 0;
+ }
+ SDL_UnlockJoysticks();
+
+ return result;
+}
+
+SDL_bool
+SDL_JoystickHasLED(SDL_Joystick *joystick)
+{
+ SDL_bool result;
+
+ if (!SDL_PrivateJoystickValid(joystick)) {
+ return SDL_FALSE;
+ }
+
+ SDL_LockJoysticks();
+
+ result = joystick->driver->HasLED(joystick);
+
+ SDL_UnlockJoysticks();
+
+ return result;
+}
+
+int
+SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+ int result;
+
+ if (!SDL_PrivateJoystickValid(joystick)) {
+ return -1;
+ }
+
+ SDL_LockJoysticks();
+
+ if (red == joystick->led_red &&
+ green == joystick->led_green &&
+ blue == joystick->led_blue) {
+ /* Avoid spamming the driver */
+ result = 0;
+ } else {
+ result = joystick->driver->SetLED(joystick, red, green, blue);
+ }
+
+ /* Save the LED value regardless of success, so we don't spam the driver */
+ joystick->led_red = red;
+ joystick->led_green = green;
+ joystick->led_blue = blue;
+
+ SDL_UnlockJoysticks();
+
+ return result;
+}
+
/*
* Close a joystick previously opened with SDL_JoystickOpen()
*/
void
-SDL_JoystickClose(SDL_Joystick * joystick)
+SDL_JoystickClose(SDL_Joystick *joystick)
{
SDL_Joystick *joysticklist;
SDL_Joystick *joysticklistprev;
+ int i;
if (!SDL_PrivateJoystickValid(joystick)) {
return;
@@ -821,6 +998,9 @@
if (joystick->rumble_expiration) {
SDL_JoystickRumble(joystick, 0, 0, 0);
+ }
+ if (joystick->trigger_rumble_expiration) {
+ SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
}
joystick->driver->Close(joystick);
@@ -843,12 +1023,19 @@
}
SDL_free(joystick->name);
+ SDL_free(joystick->serial);
/* Free the data associated with this joystick */
SDL_free(joystick->axes);
SDL_free(joystick->hats);
SDL_free(joystick->balls);
SDL_free(joystick->buttons);
+ for (i = 0; i < joystick->ntouchpads; i++) {
+ SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i];
+ SDL_free(touchpad->fingers);
+ }
+ SDL_free(joystick->touchpads);
+ SDL_free(joystick->sensors);
SDL_free(joystick);
SDL_UnlockJoysticks();
@@ -918,6 +1105,43 @@
/* These are global for SDL_sysjoystick.c and SDL_events.c */
+void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
+{
+ int ntouchpads = joystick->ntouchpads + 1;
+ SDL_JoystickTouchpadInfo *touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo)));
+ if (touchpads) {
+ SDL_JoystickTouchpadInfo *touchpad = &touchpads[ntouchpads - 1];
+ SDL_JoystickTouchpadFingerInfo *fingers = (SDL_JoystickTouchpadFingerInfo *)SDL_calloc(nfingers, sizeof(SDL_JoystickTouchpadFingerInfo));
+
+ if (fingers) {
+ touchpad->nfingers = nfingers;
+ touchpad->fingers = fingers;
+ } else {
+ /* Out of memory, this touchpad won't be active */
+ touchpad->nfingers = 0;
+ touchpad->fingers = NULL;
+ }
+
+ joystick->ntouchpads = ntouchpads;
+ joystick->touchpads = touchpads;
+ }
+}
+
+void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type)
+{
+ int nsensors = joystick->nsensors + 1;
+ SDL_JoystickSensorInfo *sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo)));
+ if (sensors) {
+ SDL_JoystickSensorInfo *sensor = &sensors[nsensors - 1];
+
+ SDL_zerop(sensor);
+ sensor->type = type;
+
+ joystick->nsensors = nsensors;
+ joystick->sensors = sensors;
+ }
+}
+
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
{
SDL_JoystickDriver *driver;
@@ -959,7 +1183,7 @@
* to have the right value for which, because the number of controllers in
* the system is now one less.
*/
-static void UpdateEventsForDeviceRemoval()
+static void UpdateEventsForDeviceRemoval(int device_index)
{
int i, num_events;
SDL_Event *events;
@@ -977,21 +1201,78 @@
num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
for (i = 0; i < num_events; ++i) {
- --events[i].jdevice.which;
+ if (events[i].cdevice.which < device_index) {
+ /* No change for index values lower than the removed device */
+ }
+ else if (events[i].cdevice.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 */
+ --events[i].cdevice.which;
+ }
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
SDL_small_free(events, isstack);
}
+static void
+SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
+{
+ int i, j;
+
+ /* Tell the app that everything is centered/unpressed... */
+ for (i = 0; i < joystick->naxes; i++) {
+ if (joystick->axes[i].has_initial_value) {
+ SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
+ }
+ }
+
+ for (i = 0; i < joystick->nbuttons; i++) {
+ SDL_PrivateJoystickButton(joystick, i, SDL_RELEASED);
+ }
+
+ for (i = 0; i < joystick->nhats; i++) {
+ SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
+ }
+
+ for (i = 0; i < joystick->ntouchpads; i++) {
+ SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i];
+
+ for (j = 0; j < touchpad->nfingers; ++j) {
+ SDL_PrivateJoystickTouchpad(joystick, i, j, SDL_RELEASED, 0.0f, 0.0f, 0.0f);
+ }
+ }
+
+}
+
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
{
- SDL_Joystick *joystick;
+ SDL_Joystick *joystick = NULL;
int player_index;
-
+ int device_index;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
+#endif
+ /* Find this joystick... */
+ device_index = 0;
+ for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
+ if (joystick->instance_id == device_instance) {
+ SDL_PrivateJoystickForceRecentering(joystick);
+ joystick->attached = SDL_FALSE;
+ break;
+ }
+
+ ++device_index;
+ }
+
+#if !SDL_EVENTS_DISABLED
+ SDL_zero(event);
event.type = SDL_JOYDEVICEREMOVED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
@@ -999,17 +1280,8 @@
SDL_PushEvent(&event);
}
- UpdateEventsForDeviceRemoval();
+ UpdateEventsForDeviceRemoval(device_index);
#endif /* !SDL_EVENTS_DISABLED */
-
- /* Mark this joystick as no longer attached */
- for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
- if (joystick->instance_id == device_instance) {
- joystick->attached = SDL_FALSE;
- joystick->force_recentering = SDL_TRUE;
- break;
- }
- }
SDL_LockJoysticks();
player_index = SDL_GetPlayerIndexForJoystickID(device_instance);
@@ -1020,7 +1292,7 @@
}
int
-SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
+SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
{
int posted;
SDL_JoystickAxisInfo *info;
@@ -1032,16 +1304,15 @@
info = &joystick->axes[axis];
if (!info->has_initial_value ||
- (!info->has_second_value && (info->initial_value == -32768 || info->initial_value == 32767) && SDL_abs(value) < (SDL_JOYSTICK_AXIS_MAX / 4))) {
+ (!info->has_second_value && (info->initial_value <= -32767 || info->initial_value == 32767) && SDL_abs(value) < (SDL_JOYSTICK_AXIS_MAX / 4))) {
info->initial_value = value;
info->value = value;
info->zero = value;
info->has_initial_value = SDL_TRUE;
+ } else if (value == info->value) {
+ return 0;
} else {
info->has_second_value = SDL_TRUE;
- }
- if (value == info->value) {
- return 0;
}
if (!info->sent_initial_value) {
/* Make sure we don't send motion until there's real activity on this axis */
@@ -1050,7 +1321,7 @@
return 0;
}
info->sent_initial_value = SDL_TRUE;
- info->value = value; /* Just so we pass the check above */
+ info->value = ~value; /* Just so we pass the check above */
SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
}
@@ -1083,7 +1354,7 @@
}
int
-SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
+SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
{
int posted;
@@ -1123,7 +1394,7 @@
}
int
-SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
+SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball,
Sint16 xrel, Sint16 yrel)
{
int posted;
@@ -1159,7 +1430,7 @@
}
int
-SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
+SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
{
int posted;
#if !SDL_EVENTS_DISABLED
@@ -1260,23 +1531,14 @@
SDL_UnlockJoysticks();
}
- if (joystick->force_recentering) {
- /* Tell the app that everything is centered/unpressed... */
- for (i = 0; i < joystick->naxes; i++) {
- if (joystick->axes[i].has_initial_value) {
- SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
- }
+ if (joystick->trigger_rumble_expiration) {
+ SDL_LockJoysticks();
+ /* Double check now that the lock is held */
+ if (joystick->trigger_rumble_expiration &&
+ SDL_TICKS_PASSED(SDL_GetTicks(), joystick->trigger_rumble_expiration)) {
+ SDL_JoystickRumbleTriggers(joystick, 0, 0, 0);
}
-
- for (i = 0; i < joystick->nbuttons; i++) {
- SDL_PrivateJoystickButton(joystick, i, 0);
- }
-
- for (i = 0; i < joystick->nhats; i++) {
- SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
- }
-
- joystick->force_recentering = SDL_FALSE;
+ SDL_UnlockJoysticks();
}
}
@@ -1369,23 +1631,123 @@
}
}
-const char *
-SDL_GetCustomJoystickManufacturer(const char *manufacturer)
+static int
+PrefixMatch(const char *a, const char *b)
{
- if (manufacturer) {
- if (SDL_strcmp(manufacturer, "Performance Designed Products") == 0) {
- return "PDP";
- } else if (SDL_strcmp(manufacturer, "HORI CO.,LTD") == 0) {
- return "HORI";
+ int matchlen = 0;
+ while (*a && *b) {
+ if (SDL_tolower(*a++) == SDL_tolower(*b++)) {
+ ++matchlen;
+ } else {
+ break;
}
}
- return manufacturer;
+ return matchlen;
}
-const char *
-SDL_GetCustomJoystickName(Uint16 vendor, Uint16 product)
+char *
+SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name)
{
- return GuessControllerName(vendor, product);
+ static struct {
+ const char *prefix;
+ const char *replacement;
+ } replacements[] = {
+ { "NVIDIA Corporation ", "" },
+ { "Performance Designed Products", "PDP" },
+ { "HORI CO.,LTD.", "HORI" },
+ { "HORI CO.,LTD", "HORI" },
+ };
+ const char *custom_name;
+ char *name;
+ size_t i, len;
+
+ custom_name = GuessControllerName(vendor, product);
+ if (custom_name) {
+ return SDL_strdup(custom_name);
+ }
+
+ if (!vendor_name) {
+ vendor_name = "";
+ }
+ if (!product_name) {
+ product_name = "";
+ }
+
+ while (*vendor_name == ' ') {
+ ++vendor_name;
+ }
+ while (*product_name == ' ') {
+ ++product_name;
+ }
+
+ if (*vendor_name && *product_name) {
+ len = (SDL_strlen(vendor_name) + 1 + SDL_strlen(product_name) + 1);
+ name = (char *)SDL_malloc(len);
+ if (!name) {
+ return NULL;
+ }
+ SDL_snprintf(name, len, "%s %s", vendor_name, product_name);
+ } else if (*product_name) {
+ name = SDL_strdup(product_name);
+ } else if (vendor || product) {
+ len = (6 + 1 + 6 + 1);
+ name = (char *)SDL_malloc(len);
+ if (!name) {
+ return NULL;
+ }
+ SDL_snprintf(name, len, "0x%.4x/0x%.4x", vendor, product);
+ } else {
+ name = SDL_strdup("Controller");
+ }
+
+ /* Trim trailing whitespace */
+ for (len = SDL_strlen(name); (len > 0 && name[len - 1] == ' '); --len) {
+ /* continue */
+ }
+ name[len] = '\0';
+
+ /* Compress duplicate spaces */
+ for (i = 0; i < (len - 1); ) {
+ if (name[i] == ' ' && name[i+1] == ' ') {
+ SDL_memmove(&name[i], &name[i+1], (len - i));
+ --len;
+ } else {
+ ++i;
+ }
+ }
+
+ /* Remove duplicate manufacturer or product in the name */
+ for (i = 1; i < (len - 1); ++i) {
+ int matchlen = PrefixMatch(name, &name[i]);
+ if (matchlen > 0 && name[matchlen-1] == ' ') {
+ SDL_memmove(name, name+matchlen, len-matchlen+1);
+ len -= matchlen;
+ break;
+ } else if (matchlen > 0 && name[matchlen] == ' ') {
+ SDL_memmove(name, name+matchlen+1, len-matchlen);
+ len -= (matchlen + 1);
+ break;
+ }
+ }
+
+ /* Perform any manufacturer replacements */
+ for (i = 0; i < SDL_arraysize(replacements); ++i) {
+ size_t prefixlen = SDL_strlen(replacements[i].prefix);
+ if (SDL_strncasecmp(name, replacements[i].prefix, prefixlen) == 0) {
+ size_t replacementlen = SDL_strlen(replacements[i].replacement);
+ SDL_memcpy(name, replacements[i].replacement, replacementlen);
+ SDL_memmove(name+replacementlen, name+prefixlen, (len-prefixlen+1));
+ break;
+ }
+ }
+
+ return name;
+}
+
+SDL_GameControllerType
+SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product)
+{
+ return SDL_GetJoystickGameControllerType(NULL, vendor, product, -1, 0, 0, 0);
}
SDL_GameControllerType
@@ -1483,11 +1845,14 @@
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
if (vendor == 0x0000 && product == 0x0000) {
/* Some devices are only identifiable by their name */
- if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
- SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
- SDL_strcmp(name, "Wireless Gamepad") == 0) {
+ if (name &&
+ (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
+ SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
+ SDL_strcmp(name, "Wireless Gamepad") == 0)) {
/* HORI or PowerA Switch Pro Controller clone */
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
+ } else if (name && SDL_strcmp(name, "Virtual Joystick") == 0) {
+ type = SDL_CONTROLLER_TYPE_VIRTUAL;
} else {
type = SDL_CONTROLLER_TYPE_UNKNOWN;
}
@@ -1509,6 +1874,9 @@
case k_eControllerType_PS4Controller:
type = SDL_CONTROLLER_TYPE_PS4;
break;
+ case k_eControllerType_PS5Controller:
+ type = SDL_CONTROLLER_TYPE_PS5;
+ break;
case k_eControllerType_SwitchProController:
case k_eControllerType_SwitchInputOnlyController:
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
@@ -1523,16 +1891,63 @@
}
SDL_bool
-SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product)
+SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
{
- EControllerType eType = GuessControllerType(vendor, product);
+ if (vendor_id == USB_VENDOR_MICROSOFT) {
+ if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
+ product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 ||
+ product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+SDL_bool
+SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id)
+{
+ if (vendor_id == USB_VENDOR_MICROSOFT) {
+ if (product_id == USB_PRODUCT_XBOX_ONE_SERIES_X ||
+ product_id == USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+SDL_bool
+SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id)
+{
+ EControllerType eType = GuessControllerType(vendor_id, product_id);
+ return (eType == k_eControllerType_PS4Controller);
+}
+
+SDL_bool
+SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id)
+{
+ EControllerType eType = GuessControllerType(vendor_id, product_id);
+ return (eType == k_eControllerType_PS5Controller);
+}
+
+SDL_bool
+SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id)
+{
+ EControllerType eType = GuessControllerType(vendor_id, product_id);
+ return (eType == k_eControllerType_SwitchProController ||
+ eType == k_eControllerType_SwitchInputOnlyController);
+}
+
+SDL_bool
+SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id)
+{
+ EControllerType eType = GuessControllerType(vendor_id, product_id);
return (eType == k_eControllerType_SwitchInputOnlyController);
}
SDL_bool
-SDL_IsJoystickSteamController(Uint16 vendor, Uint16 product)
+SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id)
{
- EControllerType eType = GuessControllerType(vendor, product);
+ EControllerType eType = GuessControllerType(vendor_id, product_id);
return (eType == k_eControllerType_SteamController ||
eType == k_eControllerType_SteamControllerV2);
}
@@ -1544,9 +1959,27 @@
}
SDL_bool
+SDL_IsJoystickWGI(SDL_JoystickGUID guid)
+{
+ return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_bool
SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid)
{
return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_bool
+SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid)
+{
+ return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_bool
+SDL_IsJoystickVirtual(SDL_JoystickGUID guid)
+{
+ return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE;
}
static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
@@ -1558,6 +1991,7 @@
MAKE_VIDPID(0x046d, 0xc299), /* Logitech G25 */
MAKE_VIDPID(0x046d, 0xc29a), /* Logitech Driving Force GT */
MAKE_VIDPID(0x046d, 0xc29b), /* Logitech G27 */
+ MAKE_VIDPID(0x046d, 0xc24f), /* Logitech G29 */
MAKE_VIDPID(0x046d, 0xc261), /* Logitech G920 (initial mode) */
MAKE_VIDPID(0x046d, 0xc262), /* Logitech G920 (active mode) */
MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */
@@ -1640,6 +2074,14 @@
}
}
+ if (SDL_IsJoystickWGI(guid)) {
+ return (SDL_JoystickType)guid.data[15];
+ }
+
+ if (SDL_IsJoystickVirtual(guid)) {
+ return (SDL_JoystickType)guid.data[15];
+ }
+
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
vidpid = MAKE_VIDPID(vendor, product);
@@ -1701,29 +2143,29 @@
https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
*/
static Uint32 joystick_blacklist[] = {
- /* Microsoft Microsoft Wireless Optical Desktop® 2.10 */
+ /* Microsoft Microsoft Wireless Optical Desktop 2.10 */
/* Microsoft Wireless Desktop - Comfort Edition */
MAKE_VIDPID(0x045e, 0x009d),
- /* Microsoft Microsoft® Digital Media Pro Keyboard */
+ /* Microsoft Microsoft Digital Media Pro Keyboard */
/* Microsoft Corp. Digital Media Pro Keyboard */
MAKE_VIDPID(0x045e, 0x00b0),
- /* Microsoft Microsoft® Digital Media Keyboard */
+ /* Microsoft Microsoft Digital Media Keyboard */
/* Microsoft Corp. Digital Media Keyboard 1.0A */
MAKE_VIDPID(0x045e, 0x00b4),
- /* Microsoft Microsoft® Digital Media Keyboard 3000 */
+ /* Microsoft Microsoft Digital Media Keyboard 3000 */
MAKE_VIDPID(0x045e, 0x0730),
- /* Microsoft Microsoft® 2.4GHz Transceiver v6.0 */
- /* Microsoft Microsoft® 2.4GHz Transceiver v8.0 */
+ /* Microsoft Microsoft 2.4GHz Transceiver v6.0 */
+ /* Microsoft Microsoft 2.4GHz Transceiver v8.0 */
/* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
/* Microsoft Wireless Mobile Mouse 1000 */
/* Microsoft Wireless Desktop 3000 */
MAKE_VIDPID(0x045e, 0x0745),
- /* Microsoft® SideWinder(TM) 2.4GHz Transceiver */
+ /* Microsoft SideWinder(TM) 2.4GHz Transceiver */
MAKE_VIDPID(0x045e, 0x0748),
/* Microsoft Corp. Wired Keyboard 600 */
@@ -1735,16 +2177,16 @@
/* Microsoft Corp. Arc Touch Mouse Transceiver */
MAKE_VIDPID(0x045e, 0x0773),
- /* Microsoft® 2.4GHz Transceiver v9.0 */
- /* Microsoft® Nano Transceiver v2.1 */
+ /* Microsoft 2.4GHz Transceiver v9.0 */
+ /* Microsoft Nano Transceiver v2.1 */
/* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
MAKE_VIDPID(0x045e, 0x07a5),
- /* Microsoft® Nano Transceiver v1.0 */
+ /* Microsoft Nano Transceiver v1.0 */
/* Microsoft Wireless Keyboard 800 */
MAKE_VIDPID(0x045e, 0x07b2),
- /* Microsoft® Nano Transceiver v2.0 */
+ /* Microsoft Nano Transceiver v2.0 */
MAKE_VIDPID(0x045e, 0x0800),
MAKE_VIDPID(0x046d, 0xc30a), /* Logitech, Inc. iTouch Composite keboard */
@@ -1801,6 +2243,7 @@
Uint32 id;
Uint16 vendor;
Uint16 product;
+ SDL_GameControllerType type;
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
@@ -1812,7 +2255,8 @@
}
}
- if (SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) {
+ type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
+ if ((type == SDL_CONTROLLER_TYPE_PS4 || type == SDL_CONTROLLER_TYPE_PS5) && SDL_IsPS4RemapperRunning()) {
return SDL_TRUE;
}
@@ -1913,7 +2357,7 @@
return device_index;
}
-SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
+SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
SDL_JoystickGUID emptyGUID;
@@ -1923,7 +2367,7 @@
return joystick->guid;
}
-Uint16 SDL_JoystickGetVendor(SDL_Joystick * joystick)
+Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick)
{
Uint16 vendor;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
@@ -1932,7 +2376,7 @@
return vendor;
}
-Uint16 SDL_JoystickGetProduct(SDL_Joystick * joystick)
+Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick)
{
Uint16 product;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
@@ -1941,7 +2385,7 @@
return product;
}
-Uint16 SDL_JoystickGetProductVersion(SDL_Joystick * joystick)
+Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick)
{
Uint16 version;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
@@ -1950,7 +2394,15 @@
return version;
}
-SDL_JoystickType SDL_JoystickGetType(SDL_Joystick * joystick)
+const char *SDL_JoystickGetSerial(SDL_Joystick *joystick)
+{
+ if (!SDL_PrivateJoystickValid(joystick)) {
+ return NULL;
+ }
+ return joystick->serial;
+}
+
+SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick)
{
SDL_JoystickType type;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
@@ -2032,13 +2484,13 @@
}
/* update the power level for this joystick */
-void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel)
+void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
{
joystick->epowerlevel = ePowerLevel;
}
/* return its power level */
-SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick * joystick)
+SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
return SDL_JOYSTICK_POWER_UNKNOWN;
@@ -2046,4 +2498,126 @@
return joystick->epowerlevel;
}
+int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure)
+{
+ SDL_JoystickTouchpadInfo *touchpad_info;
+ SDL_JoystickTouchpadFingerInfo *finger_info;
+ int posted;
+#if !SDL_EVENTS_DISABLED
+ Uint32 event_type;
+#endif
+
+ if (touchpad < 0 || touchpad >= joystick->ntouchpads) {
+ return 0;
+ }
+
+ touchpad_info = &joystick->touchpads[touchpad];
+ if (finger < 0 || finger >= touchpad_info->nfingers) {
+ return 0;
+ }
+
+ finger_info = &touchpad_info->fingers[finger];
+
+ if (!state) {
+ if (x == 0.0f && y == 0.0f) {
+ x = finger_info->x;
+ y = finger_info->y;
+ }
+ pressure = 0.0f;
+ }
+
+ if (x < 0.0f) {
+ x = 0.0f;
+ } else if (x > 1.0f) {
+ x = 1.0f;
+ }
+ if (y < 0.0f) {
+ y = 0.0f;
+ } else if (y > 1.0f) {
+ y = 1.0f;
+ }
+ if (pressure < 0.0f) {
+ pressure = 0.0f;
+ } else if (pressure > 1.0f) {
+ pressure = 1.0f;
+ }
+
+ if (state == finger_info->state) {
+ if (!state ||
+ (x == finger_info->x && y == finger_info->y && pressure == finger_info->pressure)) {
+ return 0;
+ }
+ }
+
+#if !SDL_EVENTS_DISABLED
+ if (state == finger_info->state) {
+ event_type = SDL_CONTROLLERTOUCHPADMOTION;
+ } else if (state) {
+ event_type = SDL_CONTROLLERTOUCHPADDOWN;
+ } else {
+ event_type = SDL_CONTROLLERTOUCHPADUP;
+ }
+#endif
+
+ /* Update internal joystick state */
+ finger_info->state = state;
+ finger_info->x = x;
+ finger_info->y = y;
+ finger_info->pressure = pressure;
+
+ /* Post the event, if desired */
+ posted = 0;
+#if !SDL_EVENTS_DISABLED
+ if (SDL_GetEventState(event_type) == SDL_ENABLE) {
+ SDL_Event event;
+ event.type = event_type;
+ event.ctouchpad.which = joystick->instance_id;
+ event.ctouchpad.touchpad = touchpad;
+ event.ctouchpad.finger = finger;
+ event.ctouchpad.x = x;
+ event.ctouchpad.y = y;
+ event.ctouchpad.pressure = pressure;
+ posted = SDL_PushEvent(&event) == 1;
+ }
+#endif /* !SDL_EVENTS_DISABLED */
+ return posted;
+}
+
+int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values)
+{
+ int i;
+ int posted = 0;
+
+ for (i = 0; i < joystick->nsensors; ++i) {
+ SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
+
+ if (sensor->type == type) {
+ if (sensor->enabled) {
+ num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
+ if (SDL_memcmp(data, sensor->data, num_values*sizeof(*data)) != 0) {
+
+ /* Update internal sensor state */
+ SDL_memcpy(sensor->data, data, num_values*sizeof(*data));
+
+ /* Post the event, if desired */
+#if !SDL_EVENTS_DISABLED
+ if (SDL_GetEventState(SDL_CONTROLLERSENSORUPDATE) == SDL_ENABLE) {
+ SDL_Event event;
+ event.type = SDL_CONTROLLERSENSORUPDATE;
+ event.csensor.which = joystick->instance_id;
+ event.csensor.sensor = type;
+ num_values = SDL_min(num_values, SDL_arraysize(event.csensor.data));
+ SDL_memset(event.csensor.data, 0, sizeof(event.csensor.data));
+ SDL_memcpy(event.csensor.data, data, num_values*sizeof(*data));
+ posted = SDL_PushEvent(&event) == 1;
+ }
+#endif /* !SDL_EVENTS_DISABLED */
+ }
+ }
+ break;
+ }
+ }
+ return posted;
+}
+
/* vi: set ts=4 sw=4 expandtab: */
--
Gitblit v1.9.3