From c1e087394020a8cb9d2a04a1eabbcc23a6a5b20d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 22 Aug 2022 16:46:55 -0700 Subject: [PATCH] Added the CRC of the joystick name to the GUID This will make it possible to have mappings for different controllers that have the same VID/PID. This happens frequently with some generic controller boards that have been reused in many products. Fixes https://github.com/libsdl-org/SDL/issues/6004 --- src/joystick/SDL_gamecontroller.c | 14 +++- src/joystick/SDL_joystick.c | 66 +++++++++++++------ src/joystick/SDL_joystick_c.h | 2 +- src/joystick/SDL_sysjoystick.h | 3 +- src/joystick/android/SDL_sysjoystick.c | 10 +-- src/joystick/bsd/SDL_bsdjoystick.c | 14 ++-- src/joystick/darwin/SDL_iokitjoystick.c | 4 +- src/joystick/emscripten/SDL_sysjoystick.c | 10 ++- src/joystick/haiku/SDL_haikujoystick.cc | 14 ++-- src/joystick/hidapi/SDL_hidapijoystick.c | 41 ++++++------ src/joystick/iphoneos/SDL_mfijoystick.m | 2 +- src/joystick/linux/SDL_sysjoystick.c | 2 +- src/joystick/os2/SDL_os2joystick.c | 16 +++-- src/joystick/ps2/SDL_sysjoystick.c | 12 ++-- src/joystick/psp/SDL_sysjoystick.c | 10 ++- src/joystick/virtual/SDL_virtualjoystick.c | 2 +- src/joystick/vita/SDL_sysjoystick.c | 14 ++-- src/joystick/windows/SDL_dinputjoystick.c | 4 +- src/joystick/windows/SDL_rawinputjoystick.c | 40 +++++------ .../windows/SDL_windows_gaming_input.c | 2 +- src/joystick/windows/SDL_xinputjoystick.c | 14 ++-- 21 files changed, 179 insertions(+), 117 deletions(-) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 87d1cbf52..46bbac486 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -538,7 +538,7 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string)); - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); if ((vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) || (vendor == USB_VENDOR_SHENZHEN && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) { @@ -664,9 +664,17 @@ static ControllerMapping_t *SDL_CreateMappingForWGIController(SDL_JoystickGUID g static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID guid, SDL_bool exact_match) { ControllerMapping_t *mapping = s_pSupportedControllers; + SDL_JoystickGUID zero_crc_guid; + + SDL_memcpy(&zero_crc_guid, &guid, sizeof(guid)); + zero_crc_guid.data[3] = 0; + zero_crc_guid.data[4] = 0; + zero_crc_guid.data[5] = 0; + zero_crc_guid.data[6] = 0; while (mapping) { - if (SDL_memcmp(&guid, &mapping->guid, sizeof(guid)) == 0) { + if (SDL_memcmp(&guid, &mapping->guid, sizeof(guid)) == 0 || + SDL_memcmp(&zero_crc_guid, &mapping->guid, sizeof(guid)) == 0) { return mapping; } mapping = mapping->next; @@ -1836,7 +1844,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) return SDL_FALSE; } - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version, NULL); if (SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", SDL_FALSE)) { /* We shouldn't ignore Steam's virtual gamepad since it's using the hints to filter out the real controllers so it can remap input for the virtual controller */ diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 26b017bb9..ac0af330e 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1768,19 +1768,23 @@ SDL_JoystickEventState(int state) #endif /* SDL_EVENTS_DISABLED */ } -void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version) +void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16) { Uint16 *guid16 = (Uint16 *)guid.data; + Uint16 bus = SDL_SwapLE16(guid16[0]); - /* If the GUID fits the form of BUS 0000 VENDOR 0000 PRODUCT 0000, return the data */ - if (/* guid16[0] is device bus type */ - guid16[1] == 0x0000 && - /* guid16[2] is vendor ID */ - guid16[3] == 0x0000 && - /* guid16[4] is product ID */ - guid16[5] == 0x0000 - /* guid16[6] is product version */ - ) { + if (bus < ' ' && guid16[3] == 0x0000 && guid16[5] == 0x0000) { + /* This GUID fits the standard form: + * 16-bit bus + * 16-bit CRC16 of the joystick name (can be zero) + * 16-bit vendor ID + * 16-bit zero + * 16-bit product ID + * 16-bit zero + * 16-bit version + * 8-bit driver identifier ('h' for HIDAPI, 'x' for XInput, etc.) + * 8-bit driver-dependent type info + */ if (vendor) { *vendor = SDL_SwapLE16(guid16[2]); } @@ -1790,6 +1794,27 @@ void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *prod if (version) { *version = SDL_SwapLE16(guid16[6]); } + if (crc16) { + *crc16 = SDL_SwapLE16(guid16[1]); + } + } else if (bus < ' ') { + /* This GUID fits the unknown VID/PID form: + * 16-bit bus + * 16-bit CRC16 of the joystick name (can be zero) + * 11 characters of the joystick name, null terminated + */ + if (vendor) { + *vendor = 0; + } + if (product) { + *product = 0; + } + if (version) { + *version = 0; + } + if (crc16) { + *crc16 = SDL_SwapLE16(guid16[1]); + } } else { if (vendor) { *vendor = 0; @@ -1800,6 +1825,9 @@ void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *prod if (version) { *version = 0; } + if (crc16) { + *crc16 = 0; + } } } @@ -2045,7 +2073,7 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam SDL_GameControllerType type; Uint16 vendor, product; - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); type = SDL_GetJoystickGameControllerTypeFromVIDPID(vendor, product, name, SDL_TRUE); if (type == SDL_CONTROLLER_TYPE_UNKNOWN) { if (SDL_IsJoystickXInput(guid)) { @@ -2379,7 +2407,7 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_JoystickGUID guid) return (SDL_JoystickType)guid.data[15]; } - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); vidpid = MAKE_VIDPID(vendor, product); if (SDL_IsJoystickProductWheel(vidpid)) { @@ -2567,7 +2595,7 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid) Uint16 product; SDL_GameControllerType type; - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL); /* Check the joystick blacklist */ id = MAKE_VIDPID(vendor, product); @@ -2618,7 +2646,7 @@ Uint16 SDL_JoystickGetDeviceVendor(int device_index) Uint16 vendor; SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index); - SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); return vendor; } @@ -2627,7 +2655,7 @@ Uint16 SDL_JoystickGetDeviceProduct(int device_index) Uint16 product; SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index); - SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); return product; } @@ -2636,7 +2664,7 @@ Uint16 SDL_JoystickGetDeviceProductVersion(int device_index) Uint16 version; SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index); - SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version); + SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version, NULL); return version; } @@ -2700,7 +2728,7 @@ Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick) Uint16 vendor; SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); - SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL); + SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL); return vendor; } @@ -2709,7 +2737,7 @@ Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick) Uint16 product; SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); - SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL); + SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL); return product; } @@ -2718,7 +2746,7 @@ Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick) Uint16 version; SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); - SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version); + SDL_GetJoystickGUIDInfo(guid, NULL, NULL, &version, NULL); return version; } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index db630c817..94a8fe1b7 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -55,7 +55,7 @@ extern SDL_bool SDL_GetDriverAndJoystickIndex(int device_index, struct _SDL_Joys extern int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id); /* Function to extract information from an SDL joystick GUID */ -extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version); +extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16); /* Function to standardize the name for a controller This should be freed with SDL_free() when no longer needed diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index d5c8c0e21..79a3720f7 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -125,9 +125,10 @@ struct _SDL_Joystick }; /* Device bus definitions */ -#define SDL_HARDWARE_BUS_VIRTUAL 0x00 +#define SDL_HARDWARE_BUS_UNKNOWN 0x00 #define SDL_HARDWARE_BUS_USB 0x03 #define SDL_HARDWARE_BUS_BLUETOOTH 0x05 +#define SDL_HARDWARE_BUS_VIRTUAL 0xFF /* Joystick capability flags for GetCapabilities() */ #define SDL_JOYCAP_LED 0x01 diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 104724afd..581e6e6a9 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -360,7 +360,7 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo /* We only need 16 bits for each of these; space them out to fill 128. */ /* Byteswap so devices get same GUID on little/big endian platforms. */ *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, desc, SDL_strlen(desc))); if (vendor_id && product_id) { *guid16++ = SDL_SwapLE16(vendor_id); @@ -368,12 +368,8 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo *guid16++ = SDL_SwapLE16(product_id); *guid16++ = 0; } else { - Uint32 crc = 0; - SDL_crc32(crc, desc, SDL_strlen(desc)); - SDL_memcpy(guid16, desc, SDL_min(2*sizeof(*guid16), SDL_strlen(desc))); - guid16 += 2; - *(Uint32 *)guid16 = SDL_SwapLE32(crc); - guid16 += 2; + SDL_strlcpy((char*)guid16, name, 4*sizeof(Uint16)); + guid16 += 4; } *guid16++ = SDL_SwapLE16(button_mask); diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index d7b4d4730..55538c740 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -700,13 +700,17 @@ BSD_JoystickQuit(void) } static SDL_JoystickGUID -BSD_JoystickGetDeviceGUID( int device_index ) +BSD_JoystickGetDeviceGUID(int device_index) { + /* the GUID is just the name for now */ + const char *name = BSD_JoystickGetDeviceName(device_index); SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ - const char *name = BSD_JoystickGetDeviceName( device_index ); - SDL_zero( guid ); - SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + Uint16 *guid16 = (Uint16 *)guid.data; + + SDL_zero(guid); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 6b6945ea0..befbfda33 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -504,7 +504,7 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) if (vendor && product) { *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, pDevice->product, SDL_strlen(pDevice->product))); *guid16++ = SDL_SwapLE16((Uint16)vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16((Uint16)product); @@ -513,7 +513,7 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) *guid16++ = 0; } else { *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, pDevice->product, SDL_strlen(pDevice->product))); SDL_strlcpy((char*)guid16, pDevice->product, sizeof(pDevice->guid.data) - 4); } diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 1664a907c..628a979c3 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -394,11 +394,15 @@ EMSCRIPTEN_JoystickClose(SDL_Joystick *joystick) static SDL_JoystickGUID EMSCRIPTEN_JoystickGetDeviceGUID(int device_index) { - SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ + /* the GUID is just the name for now */ const char *name = EMSCRIPTEN_JoystickGetDeviceName(device_index); + SDL_JoystickGUID guid; + Uint16 *guid16 = (Uint16 *)guid.data; + SDL_zero(guid); - SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index c0c6e012c..dc2cc8974 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -248,13 +248,17 @@ extern "C" SDL_joyname[0] = NULL; } - static SDL_JoystickGUID HAIKU_JoystickGetDeviceGUID( int device_index ) + static SDL_JoystickGUID HAIKU_JoystickGetDeviceGUID(int device_index) { + /* the GUID is just the name for now */ + const char *name = HAIKU_JoystickGetDeviceName(device_index); SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ - const char *name = HAIKU_JoystickGetDeviceName( device_index ); - SDL_zero( guid ); - SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + Uint16 *guid16 = (Uint16 *)guid.data; + + SDL_zero(guid); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 0bb7954b6..d95abd459 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -603,26 +603,6 @@ HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_H device->interface_protocol = info->interface_protocol; device->usage_page = info->usage_page; device->usage = info->usage; - { - /* FIXME: Is there any way to tell whether this is a Bluetooth device? */ - const Uint16 vendor = device->vendor_id; - const Uint16 product = device->product_id; - const Uint16 version = device->version; - Uint16 *guid16 = (Uint16 *)device->guid.data; - - *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(vendor); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(product); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(version); - *guid16++ = 0; - - /* Note that this is a HIDAPI device for special handling elsewhere */ - device->guid.data[14] = 'h'; - device->guid.data[15] = 0; - } device->dev_lock = SDL_CreateMutex(); /* Need the device name before getting the driver to know whether to ignore this device */ @@ -654,6 +634,27 @@ HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_H } } + { + /* FIXME: Is there any way to tell whether this is a Bluetooth device? */ + const Uint16 vendor = device->vendor_id; + const Uint16 product = device->product_id; + const Uint16 version = device->version; + Uint16 *guid16 = (Uint16 *)device->guid.data; + + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, device->name, SDL_strlen(device->name))); + *guid16++ = SDL_SwapLE16(vendor); + *guid16++ = 0; + *guid16++ = SDL_SwapLE16(product); + *guid16++ = 0; + *guid16++ = SDL_SwapLE16(version); + *guid16++ = 0; + + /* Note that this is a HIDAPI device for special handling elsewhere */ + device->guid.data[14] = 'h'; + device->guid.data[15] = 0; + } + if (num_children > 0) { int i; diff --git a/src/joystick/iphoneos/SDL_mfijoystick.m b/src/joystick/iphoneos/SDL_mfijoystick.m index 662d820dc..372cfcc80 100644 --- a/src/joystick/iphoneos/SDL_mfijoystick.m +++ b/src/joystick/iphoneos/SDL_mfijoystick.m @@ -475,7 +475,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle /* We only need 16 bits for each of these; space them out to fill 128. */ /* Byteswap so devices get same GUID on little/big endian platforms. */ *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); *guid16++ = SDL_SwapLE16(vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16(product); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 307dd5642..497b18490 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -241,7 +241,7 @@ IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid) /* We only need 16 bits for each of these; space them out to fill 128. */ /* Byteswap so devices get same GUID on little/big endian platforms. */ *guid16++ = SDL_SwapLE16(inpid.bustype); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); if (inpid.vendor && inpid.product) { *guid16++ = SDL_SwapLE16(inpid.vendor); diff --git a/src/joystick/os2/SDL_os2joystick.c b/src/joystick/os2/SDL_os2joystick.c index 1c292ff4d..e49fa3289 100644 --- a/src/joystick/os2/SDL_os2joystick.c +++ b/src/joystick/os2/SDL_os2joystick.c @@ -399,12 +399,16 @@ static void OS2_JoystickSetDevicePlayerIndex(int device_index, int player_index) static SDL_JoystickGUID OS2_JoystickGetDeviceGUID(int device_index) { - SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ - const char *name = OS2_JoystickGetDeviceName(device_index); - SDL_zero(guid); - SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); - return guid; + /* the GUID is just the name for now */ + const char *name = OS2_JoystickGetDeviceName(device_index); + SDL_JoystickGUID guid; + Uint16 *guid16 = (Uint16 *)guid.data; + + SDL_zero(guid); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); + return guid; } static SDL_JoystickID OS2_JoystickGetDeviceInstanceID(int device_index) diff --git a/src/joystick/ps2/SDL_sysjoystick.c b/src/joystick/ps2/SDL_sysjoystick.c index f9d1120d2..cf4a82b96 100644 --- a/src/joystick/ps2/SDL_sysjoystick.c +++ b/src/joystick/ps2/SDL_sysjoystick.c @@ -167,13 +167,17 @@ static void PS2_JoystickSetDevicePlayerIndex(int device_index, int player_index) } /* Function to return the stable GUID for a plugged in device */ -static SDL_JoystickGUID PS2_JoystickGetDeviceGUID( int device_index ) +static SDL_JoystickGUID PS2_JoystickGetDeviceGUID(int device_index) { - SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ + /* the GUID is just the name for now */ const char *name = PS2_JoystickGetDeviceName(device_index); + SDL_JoystickGUID guid; + Uint16 *guid16 = (Uint16 *)guid.data; + SDL_zero(guid); - SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index df3be5681..762027346 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -134,11 +134,15 @@ static void PSP_JoystickSetDevicePlayerIndex(int device_index, int player_index) static SDL_JoystickGUID PSP_JoystickGetDeviceGUID(int device_index) { - SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ + /* the GUID is just the name for now */ const char *name = PSP_JoystickGetDeviceName(device_index); + SDL_JoystickGUID guid; + Uint16 *guid16 = (Uint16 *)guid.data; + SDL_zero(guid); - SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 273c75e5a..9849a8c96 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -198,7 +198,7 @@ SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc) /* Byteswap so devices get same GUID on little/big endian platforms. */ guid16 = (Uint16 *)hwdata->guid.data; *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_VIRTUAL); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); *guid16++ = SDL_SwapLE16(hwdata->desc.vendor_id); *guid16++ = 0; *guid16++ = SDL_SwapLE16(hwdata->desc.product_id); diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c index 7b384e7e9..a88983291 100644 --- a/src/joystick/vita/SDL_sysjoystick.c +++ b/src/joystick/vita/SDL_sysjoystick.c @@ -341,13 +341,17 @@ void VITA_JoystickQuit(void) { } -SDL_JoystickGUID VITA_JoystickGetDeviceGUID( int device_index ) +SDL_JoystickGUID VITA_JoystickGetDeviceGUID(int device_index) { + /* the GUID is just the name for now */ + const char *name = VITA_JoystickGetDeviceName(device_index); SDL_JoystickGUID guid; - /* the GUID is just the first 16 chars of the name for now */ - const char *name = VITA_JoystickGetDeviceName( device_index ); - SDL_zero( guid ); - SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + Uint16 *guid16 = (Uint16 *)guid.data; + + SDL_zero(guid); + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_UNKNOWN); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); + SDL_strlcpy((char*)guid16, name, sizeof(guid.data) - 4); return guid; } diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index 8631ca6d7..38040c389 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -501,7 +501,7 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext) guid16 = (Uint16 *)pNewJoystick->guid.data; if (vendor && product) { *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname))); *guid16++ = SDL_SwapLE16(vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16(product); @@ -510,7 +510,7 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext) *guid16++ = 0; } else { *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname))); SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4); } diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index cff656b26..d760a7db2 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -755,26 +755,6 @@ RAWINPUT_AddDevice(HANDLE hDevice) CHECK(device->preparsed_data = (PHIDP_PREPARSED_DATA)SDL_calloc(size, sizeof(BYTE))); CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_PREPARSEDDATA, device->preparsed_data, &size) != (UINT)-1); - { - const Uint16 vendor = device->vendor_id; - const Uint16 product = device->product_id; - const Uint16 version = device->version; - Uint16 *guid16 = (Uint16 *)device->guid.data; - - *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(vendor); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(product); - *guid16++ = 0; - *guid16++ = SDL_SwapLE16(version); - *guid16++ = 0; - - /* Note that this is a RAWINPUT device for special handling elsewhere */ - device->guid.data[14] = 'r'; - device->guid.data[15] = 0; - } - hFile = CreateFileA(dev_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); CHECK(hFile != INVALID_HANDLE_VALUE); @@ -799,6 +779,26 @@ RAWINPUT_AddDevice(HANDLE hDevice) SDL_free(product_string); } } + { + const Uint16 vendor = device->vendor_id; + const Uint16 product = device->product_id; + const Uint16 version = device->version; + Uint16 *guid16 = (Uint16 *)device->guid.data; + + *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); + *guid16++ = SDL_SwapLE16(SDL_crc16(0, device->name, SDL_strlen(device->name))); + *guid16++ = SDL_SwapLE16(vendor); + *guid16++ = 0; + *guid16++ = SDL_SwapLE16(product); + *guid16++ = 0; + *guid16++ = SDL_SwapLE16(version); + *guid16++ = 0; + + /* Note that this is a RAWINPUT device for special handling elsewhere */ + device->guid.data[14] = 'r'; + device->guid.data[15] = 0; + } + device->path = SDL_strdup(dev_name); CloseHandle(hFile); diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index c32c88997..b64df7f45 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -320,7 +320,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde /* FIXME: Is there any way to tell whether this is a Bluetooth device? */ *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); *guid16++ = SDL_SwapLE16(vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16(product); diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index dcf2940ff..a7026a0bb 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -279,13 +279,19 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) } pNewJoystick->bXInputDevice = SDL_TRUE; + pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType)); + if (!pNewJoystick->joystickname) { + SDL_free(pNewJoystick); + return; /* better luck next time? */ + } + SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid); if (!SDL_XInputUseOldJoystickMapping()) { Uint16 *guid16 = (Uint16 *)pNewJoystick->guid.data; GuessXInputDevice(userid, &vendor, &product, &version); *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); - *guid16++ = 0; + *guid16++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname))); *guid16++ = SDL_SwapLE16(vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16(product); @@ -299,12 +305,6 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) } pNewJoystick->SubType = SubType; pNewJoystick->XInputUserId = userid; - pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType)); - if (!pNewJoystick->joystickname) { - SDL_free(pNewJoystick); - return; /* better luck next time? */ - } - SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid); if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) { SDL_free(pNewJoystick);