Use the original manufacturer and product strings for the joystick CRC

This allows the most information possible for the CRC string, which is used to differentiate controllers with the same VID/PID.

Fixes https://github.com/libsdl-org/SDL/issues/8724

(cherry picked from commit 1f1ee6f77c492e17a9691c367110c11529fab3fb)
This commit is contained in:
Sam Lantinga 2023-12-20 19:05:20 -08:00
parent d76097dc5e
commit 919cd56b20
14 changed files with 37 additions and 32 deletions

View file

@ -2449,21 +2449,26 @@ char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_n
return name; return name;
} }
SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *vendor_name, const char *product_name, Uint8 driver_signature, Uint8 driver_data)
{ {
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
Uint16 *guid16 = (Uint16 *)guid.data; Uint16 *guid16 = (Uint16 *)guid.data;
Uint16 crc = 0;
SDL_zero(guid); SDL_zero(guid);
if (!name) { if (vendor_name && *vendor_name && product_name && *product_name) {
name = ""; SDL_crc16(crc, vendor_name, SDL_strlen(vendor_name));
SDL_crc16(crc, " ", 1);
SDL_crc16(crc, product_name, SDL_strlen(product_name));
} else if (product_name) {
SDL_crc16(crc, product_name, SDL_strlen(product_name));
} }
/* We only need 16 bits for each of these; space them out to fill 128. */ /* 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. */ /* Byteswap so devices get same GUID on little/big endian platforms. */
*guid16++ = SDL_SwapLE16(bus); *guid16++ = SDL_SwapLE16(bus);
*guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); *guid16++ = SDL_SwapLE16(crc);
if (vendor && product) { if (vendor && product) {
*guid16++ = SDL_SwapLE16(vendor); *guid16++ = SDL_SwapLE16(vendor);
@ -2481,14 +2486,14 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc
guid.data[14] = driver_signature; guid.data[14] = driver_signature;
guid.data[15] = driver_data; guid.data[15] = driver_data;
} }
SDL_strlcpy((char *)guid16, name, available_space); SDL_strlcpy((char *)guid16, product_name, available_space);
} }
return guid; return guid;
} }
SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name) SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name)
{ {
return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0); return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, NULL, name, 0, 0);
} }
void SDL_SetJoystickGUIDVendor(SDL_JoystickGUID *guid, Uint16 vendor) void SDL_SetJoystickGUIDVendor(SDL_JoystickGUID *guid, Uint16 vendor)

View file

@ -71,7 +71,7 @@ extern int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id);
extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name); extern char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name);
/* Function to create a GUID for a joystick based on the VID/PID and name */ /* Function to create a GUID for a joystick based on the VID/PID and name */
extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data); extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *vendor_name, const char *product_name, Uint8 driver_signature, Uint8 driver_data);
/* Function to create a GUID for a joystick based on the name, with no VID/PID information */ /* Function to create a GUID for a joystick based on the name, with no VID/PID information */
extern SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name); extern SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name);

View file

@ -344,7 +344,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
nhats = 0; nhats = 0;
} }
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, desc, 0, 0); guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, NULL, desc, 0, 0);
/* Update the GUID with capability bits */ /* Update the GUID with capability bits */
{ {

View file

@ -456,7 +456,7 @@ static int MaybeAddDevice(const char *path)
struct usb_device_info di; struct usb_device_info di;
if (ioctl(hw->fd, USB_GET_DEVICEINFO, &di) != -1) { if (ioctl(hw->fd, USB_GET_DEVICEINFO, &di) != -1) {
name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product); name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name, 0, 0); guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0);
#ifdef SDL_JOYSTICK_HIDAPI #ifdef SDL_JOYSTICK_HIDAPI
if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) { if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {

View file

@ -499,7 +499,7 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
} }
#endif #endif
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0); pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0);
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);

View file

@ -666,7 +666,7 @@ void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name)
void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 vendor_id, Uint16 product_id) void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 vendor_id, Uint16 product_id)
{ {
/* Don't set the device product ID directly, or we'll constantly re-enumerate this device */ /* Don't set the device product ID directly, or we'll constantly re-enumerate this device */
device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->name, 'h', 0); device->guid = SDL_CreateJoystickGUID(device->guid.data[0], vendor_id, product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0);
} }
static void HIDAPI_UpdateJoystickSerial(SDL_HIDAPI_Device *device) static void HIDAPI_UpdateJoystickSerial(SDL_HIDAPI_Device *device)
@ -895,18 +895,11 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
/* Need the device name before getting the driver to know whether to ignore this device */ /* Need the device name before getting the driver to know whether to ignore this device */
{ {
char *manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string);
char *product_string = HIDAPI_ConvertString(info->product_string);
char *serial_number = HIDAPI_ConvertString(info->serial_number); char *serial_number = HIDAPI_ConvertString(info->serial_number);
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string); device->manufacturer_string = HIDAPI_ConvertString(info->manufacturer_string);
device->product_string = HIDAPI_ConvertString(info->product_string);
if (manufacturer_string) { device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, device->manufacturer_string, device->product_string);
SDL_free(manufacturer_string);
}
if (product_string) {
SDL_free(product_string);
}
if (serial_number && *serial_number) { if (serial_number && *serial_number) {
device->serial = serial_number; device->serial = serial_number;
@ -915,6 +908,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
} }
if (!device->name) { if (!device->name) {
SDL_free(device->manufacturer_string);
SDL_free(device->product_string);
SDL_free(device->serial); SDL_free(device->serial);
SDL_free(device->path); SDL_free(device->path);
SDL_free(device); SDL_free(device);
@ -923,7 +918,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
} }
/* FIXME: Is there any way to tell whether this is a Bluetooth device? */ /* FIXME: Is there any way to tell whether this is a Bluetooth device? */
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'h', 0); device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0);
device->joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; device->joystick_type = SDL_JOYSTICK_TYPE_GAMECONTROLLER;
device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol); device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
@ -993,6 +988,8 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device)
device->magic = NULL; device->magic = NULL;
SDL_DestroyMutex(device->dev_lock); SDL_DestroyMutex(device->dev_lock);
SDL_free(device->manufacturer_string);
SDL_free(device->product_string);
SDL_free(device->serial); SDL_free(device->serial);
SDL_free(device->name); SDL_free(device->name);
SDL_free(device->path); SDL_free(device->path);

View file

@ -59,6 +59,8 @@ typedef struct _SDL_HIDAPI_Device
{ {
const void *magic; const void *magic;
char *name; char *name;
char *manufacturer_string;
char *product_string;
char *path; char *path;
Uint16 vendor_id; Uint16 vendor_id;
Uint16 product_id; Uint16 product_id;

View file

@ -666,7 +666,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
} else { } else {
signature = device->button_mask; signature = device->button_mask;
} }
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, NULL, name, 'm', subtype);
if (SDL_ShouldIgnoreJoystick(name, device->guid)) { if (SDL_ShouldIgnoreJoystick(name, device->guid)) {
return SDL_FALSE; return SDL_FALSE;

View file

@ -319,7 +319,7 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend
SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version); SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
#endif #endif
*guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, name, 0, 0); *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
if (SDL_ShouldIgnoreJoystick(name, *guid)) { if (SDL_ShouldIgnoreJoystick(name, *guid)) {
SDL_free(name); SDL_free(name);

View file

@ -191,7 +191,7 @@ int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
} }
} }
hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, name, 'v', (Uint8)hwdata->desc.type); hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, NULL, name, 'v', (Uint8)hwdata->desc.type);
/* Allocate fields for different control-types */ /* Allocate fields for different control-types */
if (hwdata->desc.naxes > 0) { if (hwdata->desc.naxes > 0) {

View file

@ -511,9 +511,9 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
CHECK(pNewJoystick->joystickname); CHECK(pNewJoystick->joystickname);
if (vendor && product) { if (vendor && product) {
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 0, 0); pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 0, 0);
} else { } else {
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, pNewJoystick->joystickname, 0, 0); pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, NULL, name, 0, 0);
} }
CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)); CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));

View file

@ -916,6 +916,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
} }
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string); device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, manufacturer_string, product_string, 'r', 0);
if (manufacturer_string) { if (manufacturer_string) {
SDL_free(manufacturer_string); SDL_free(manufacturer_string);
@ -925,8 +926,6 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
} }
} }
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'r', 0);
device->path = SDL_strdup(dev_name); device->path = SDL_strdup(dev_name);
CloseHandle(hFile); CloseHandle(hFile);

View file

@ -527,7 +527,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
__x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller); __x_ABI_CWindows_CGaming_CInput_CIGameController_Release(gamecontroller);
} }
guid = SDL_CreateJoystickGUID(bus, vendor, product, version, name, 'w', (Uint8)type); guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
if (SDL_ShouldIgnoreJoystick(name, guid)) { if (SDL_ShouldIgnoreJoystick(name, guid)) {
ignore_joystick = SDL_TRUE; ignore_joystick = SDL_TRUE;

View file

@ -156,6 +156,7 @@ int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid)
static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
{ {
const char *name = NULL;
Uint16 vendor = 0; Uint16 vendor = 0;
Uint16 product = 0; Uint16 product = 0;
Uint16 version = 0; Uint16 version = 0;
@ -207,16 +208,17 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
return; /* better luck next time? */ return; /* better luck next time? */
} }
name = GetXInputName(userid, SubType);
GetXInputDeviceInfo(userid, &vendor, &product, &version); GetXInputDeviceInfo(userid, &vendor, &product, &version);
pNewJoystick->bXInputDevice = SDL_TRUE; pNewJoystick->bXInputDevice = SDL_TRUE;
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, GetXInputName(userid, SubType)); pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
if (!pNewJoystick->joystickname) { if (!pNewJoystick->joystickname) {
SDL_free(pNewJoystick); SDL_free(pNewJoystick);
return; /* better luck next time? */ return; /* better luck next time? */
} }
(void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid); (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%d", userid);
if (!SDL_XInputUseOldJoystickMapping()) { if (!SDL_XInputUseOldJoystickMapping()) {
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 'x', SubType); pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 'x', SubType);
} }
pNewJoystick->SubType = SubType; pNewJoystick->SubType = SubType;
pNewJoystick->XInputUserId = userid; pNewJoystick->XInputUserId = userid;