Dynamically update the serial number if it isn't available at first This happens for Xbox One controllers using newer firmware connected over NDIS (cherry picked from commit d1c72bb0bc54fba41ba89930a3ed98f8767be724)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index 7306abb..47300bc 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -97,6 +97,26 @@ static SDL_bool SDL_HIDAPI_combine_joycons = SDL_TRUE;
static SDL_bool initialized = SDL_FALSE;
static SDL_bool shutting_down = SDL_FALSE;
+static char *HIDAPI_ConvertString(const wchar_t *wide_string)
+{
+ char *string = NULL;
+
+ if (wide_string) {
+ string = SDL_iconv_string("UTF-8", "WCHAR_T", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
+ if (string == NULL) {
+ switch (sizeof(wchar_t)) {
+ case 2:
+ string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
+ break;
+ case 4:
+ string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
+ break;
+ }
+ }
+ }
+ return string;
+}
+
void HIDAPI_DumpPacket(const char *prefix, const Uint8 *data, int size)
{
int i;
@@ -565,16 +585,53 @@ void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id)
SDL_SetJoystickGUIDProduct(&device->guid, product_id);
}
+static void HIDAPI_UpdateJoystickSerial(SDL_HIDAPI_Device *device)
+{
+ int i;
+
+ for (i = 0; i < device->num_joysticks; ++i) {
+ SDL_Joystick *joystick = SDL_JoystickFromInstanceID(device->joysticks[i]);
+ if (joystick && device->serial) {
+ SDL_free(joystick->serial);
+ joystick->serial = SDL_strdup(device->serial);
+ }
+ }
+}
+
void HIDAPI_SetDeviceSerial(SDL_HIDAPI_Device *device, const char *serial)
{
if (serial && *serial && (!device->serial || SDL_strcmp(serial, device->serial) != 0)) {
SDL_free(device->serial);
device->serial = SDL_strdup(serial);
+ HIDAPI_UpdateJoystickSerial(device);
}
}
-SDL_bool
-HIDAPI_HasConnectedUSBDevice(const char *serial)
+static int wcstrcmp(const wchar_t *str1, const char *str2)
+{
+ int result;
+
+ while (1) {
+ result = (*str1 - *str2);
+ if (result != 0 || *str1 == 0) {
+ break;
+ }
+ ++str1;
+ ++str2;
+ }
+ return result;
+}
+
+static void HIDAPI_SetDeviceSerialW(SDL_HIDAPI_Device *device, const wchar_t *serial)
+{
+ if (serial && *serial && (!device->serial || wcstrcmp(serial, device->serial) != 0)) {
+ SDL_free(device->serial);
+ device->serial = HIDAPI_ConvertString(serial);
+ HIDAPI_UpdateJoystickSerial(device);
+ }
+}
+
+SDL_bool HIDAPI_HasConnectedUSBDevice(const char *serial)
{
SDL_HIDAPI_Device *device;
@@ -627,8 +684,7 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial)
}
}
-SDL_bool
-HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
+SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
{
int i, j;
SDL_JoystickID joystickID;
@@ -704,26 +760,6 @@ static int HIDAPI_JoystickGetCount(void)
return SDL_HIDAPI_numjoysticks;
}
-static char *HIDAPI_ConvertString(const wchar_t *wide_string)
-{
- char *string = NULL;
-
- if (wide_string) {
- string = SDL_iconv_string("UTF-8", "WCHAR_T", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
- if (string == NULL) {
- switch (sizeof(wchar_t)) {
- case 2:
- string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
- break;
- case 4:
- string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char *)wide_string, (SDL_wcslen(wide_string) + 1) * sizeof(wchar_t));
- break;
- }
- }
- }
- return string;
-}
-
static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_HIDAPI_Device **children)
{
SDL_HIDAPI_Device *device;
@@ -961,6 +997,9 @@ static void HIDAPI_UpdateDeviceList(void)
device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
if (device) {
device->seen = SDL_TRUE;
+
+ /* Check to see if the serial number is available now */
+ HIDAPI_SetDeviceSerialW(device, info->serial_number);
} else {
HIDAPI_AddDevice(info, 0, NULL);
}
@@ -1075,8 +1114,7 @@ HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
return result;
}
-SDL_bool
-HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
+SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
{
SDL_HIDAPI_Device *device;
SDL_bool supported = SDL_FALSE;
@@ -1310,7 +1348,7 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
return -1;
}
- if (!joystick->serial && device->serial) {
+ if (device->serial) {
joystick->serial = SDL_strdup(device->serial);
}