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
This commit is contained in:
Sam Lantinga
2022-08-22 16:46:55 -07:00
parent 20715fa014
commit c1e0873940
21 changed files with 179 additions and 117 deletions

View File

@@ -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;
}