Dynamically update the serial number if it isn't available at first

This happens for Xbox One controllers using newer firmware connected over NDIS
This commit is contained in:
Sam Lantinga 2023-02-08 14:16:17 -08:00
parent c5c94a6be6
commit d1c72bb0bc

View file

@ -92,6 +92,26 @@ static SDL_bool SDL_HIDAPI_combine_joycons = SDL_TRUE;
static SDL_bool initialized = SDL_FALSE; static SDL_bool initialized = SDL_FALSE;
static SDL_bool shutting_down = 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) void HIDAPI_DumpPacket(const char *prefix, const Uint8 *data, int size)
{ {
int i; int i;
@ -561,16 +581,53 @@ void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id)
SDL_SetJoystickGUIDProduct(&device->guid, 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_GetJoystickFromInstanceID(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) void HIDAPI_SetDeviceSerial(SDL_HIDAPI_Device *device, const char *serial)
{ {
if (serial && *serial && (!device->serial || SDL_strcmp(serial, device->serial) != 0)) { if (serial && *serial && (!device->serial || SDL_strcmp(serial, device->serial) != 0)) {
SDL_free(device->serial); SDL_free(device->serial);
device->serial = SDL_strdup(serial); device->serial = SDL_strdup(serial);
HIDAPI_UpdateJoystickSerial(device);
} }
} }
SDL_bool static int wcstrcmp(const wchar_t *str1, const char *str2)
HIDAPI_HasConnectedUSBDevice(const char *serial) {
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; SDL_HIDAPI_Device *device;
@ -623,8 +680,7 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial)
} }
} }
SDL_bool SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
{ {
int i, j; int i, j;
SDL_JoystickID joystickID; SDL_JoystickID joystickID;
@ -700,26 +756,6 @@ static int HIDAPI_JoystickGetCount(void)
return SDL_HIDAPI_numjoysticks; 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) static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_HIDAPI_Device **children)
{ {
SDL_HIDAPI_Device *device; SDL_HIDAPI_Device *device;
@ -957,6 +993,9 @@ static void HIDAPI_UpdateDeviceList(void)
device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id); device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
if (device) { if (device) {
device->seen = SDL_TRUE; device->seen = SDL_TRUE;
/* Check to see if the serial number is available now */
HIDAPI_SetDeviceSerialW(device, info->serial_number);
} else { } else {
HIDAPI_AddDevice(info, 0, NULL); HIDAPI_AddDevice(info, 0, NULL);
} }
@ -1040,8 +1079,7 @@ static SDL_bool HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id,
return SDL_FALSE; return SDL_FALSE;
} }
SDL_bool SDL_bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type)
HIDAPI_IsDeviceTypePresent(SDL_GamepadType type)
{ {
SDL_HIDAPI_Device *device; SDL_HIDAPI_Device *device;
SDL_bool result = SDL_FALSE; SDL_bool result = SDL_FALSE;
@ -1071,8 +1109,7 @@ HIDAPI_IsDeviceTypePresent(SDL_GamepadType type)
return result; return result;
} }
SDL_bool SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
{ {
SDL_HIDAPI_Device *device; SDL_HIDAPI_Device *device;
SDL_bool supported = SDL_FALSE; SDL_bool supported = SDL_FALSE;
@ -1306,7 +1343,7 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index)
return -1; return -1;
} }
if (!joystick->serial && device->serial) { if (device->serial) {
joystick->serial = SDL_strdup(device->serial); joystick->serial = SDL_strdup(device->serial);
} }