SDL: Refactor joystick GUID creation

From 277b033e78235d6ffad7525a1fb9acfef3a43433 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 22 Aug 2022 19:28:21 -0700
Subject: [PATCH] Refactor joystick GUID creation

---
 src/joystick/SDL_joystick.c                   | 40 +++++++++++++++++++
 src/joystick/SDL_joystick_c.h                 |  6 +++
 src/joystick/android/SDL_sysjoystick.c        | 24 +++--------
 src/joystick/bsd/SDL_bsdjoystick.c            |  9 +----
 src/joystick/darwin/SDL_iokitjoystick.c       | 19 +--------
 src/joystick/emscripten/SDL_sysjoystick.c     |  9 +----
 src/joystick/haiku/SDL_haikujoystick.cc       |  9 +----
 src/joystick/hidapi/SDL_hidapijoystick.c      | 22 +---------
 src/joystick/iphoneos/SDL_mfijoystick.m       | 23 ++++-------
 src/joystick/linux/SDL_sysjoystick.c          | 19 +--------
 src/joystick/os2/SDL_os2joystick.c            |  9 +----
 src/joystick/ps2/SDL_sysjoystick.c            |  9 +----
 src/joystick/psp/SDL_sysjoystick.c            |  9 +----
 src/joystick/virtual/SDL_virtualjoystick.c    | 17 +-------
 src/joystick/vita/SDL_sysjoystick.c           |  9 +----
 src/joystick/windows/SDL_dinputjoystick.c     | 16 +-------
 src/joystick/windows/SDL_rawinputjoystick.c   | 21 +---------
 .../windows/SDL_windows_gaming_input.c        | 14 +------
 src/joystick/windows/SDL_xinputjoystick.c     | 17 +-------
 19 files changed, 79 insertions(+), 222 deletions(-)

diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index ac0af330e3d..ba2918b2ece 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1973,6 +1973,46 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c
     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 guid;
+    Uint16 *guid16 = (Uint16 *)guid.data;
+
+    SDL_zero(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(bus);
+    *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name)));
+
+    if (vendor && product) {
+        *guid16++ = SDL_SwapLE16(vendor);
+        *guid16++ = 0;
+        *guid16++ = SDL_SwapLE16(product);
+        *guid16++ = 0;
+        *guid16++ = SDL_SwapLE16(version);
+        guid.data[14] = driver_signature;
+        guid.data[15] = driver_data;
+    } else {
+        size_t available_space = sizeof(guid.data) - 4;
+
+        if (driver_signature) {
+            available_space -= 2;
+            guid.data[14] = driver_signature;
+            guid.data[15] = driver_data;
+        }
+        SDL_strlcpy((char*)guid16, name, available_space);
+    }
+    return guid;
+}
+
+SDL_JoystickGUID
+SDL_CreateJoystickGUIDForName(const char *name)
+{
+    return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0);
+}
+
 SDL_GameControllerType
 SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI)
 {
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index 94a8fe1b715..b1ee5a47ff9 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -62,6 +62,12 @@ extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint1
  */
 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 */
+extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data);
+
+/* 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);
+
 /* Function to return the type of a controller */
 extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI);
 extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name);
diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c
index 581e6e6a9ff..6af06b6a27b 100644
--- a/src/joystick/android/SDL_sysjoystick.c
+++ b/src/joystick/android/SDL_sysjoystick.c
@@ -303,7 +303,6 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
 {
     SDL_joylist_item *item;
     SDL_JoystickGUID guid;
-    Uint16 *guid16 = (Uint16 *)guid.data;
     int i;
     int axis_mask;
 
@@ -355,26 +354,15 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, int vendo
         nhats = 0;
     }
 
-    SDL_memset(guid.data, 0, sizeof(guid.data));
+    guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor_id, product_id, 0, desc, 0, 0);
 
-    /* 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++ = SDL_SwapLE16(SDL_crc16(0, desc, SDL_strlen(desc)));
-
-    if (vendor_id && product_id) {
-        *guid16++ = SDL_SwapLE16(vendor_id);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(product_id);
-        *guid16++ = 0;
-    } else {
-        SDL_strlcpy((char*)guid16, name, 4*sizeof(Uint16));
-        guid16 += 4;
+    /* Update the GUID with capability bits */
+    {
+        Uint16 *guid16 = (Uint16 *)guid.data;
+        guid16[6] = SDL_SwapLE16(button_mask);
+        guid16[7] = SDL_SwapLE16(axis_mask);
     }
 
-    *guid16++ = SDL_SwapLE16(button_mask);
-    *guid16++ = SDL_SwapLE16(axis_mask);
-
     item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
     if (item == NULL) {
         return -1;
diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c
index 55538c74062..71e99d7d9db 100644
--- a/src/joystick/bsd/SDL_bsdjoystick.c
+++ b/src/joystick/bsd/SDL_bsdjoystick.c
@@ -704,14 +704,7 @@ BSD_JoystickGetDeviceGUID(int device_index)
 {
     /* the GUID is just the name for now */
     const char *name = BSD_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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 static int
diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c
index befbfda33b4..40d8a38cbf0 100644
--- a/src/joystick/darwin/SDL_iokitjoystick.c
+++ b/src/joystick/darwin/SDL_iokitjoystick.c
@@ -496,26 +496,11 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
 #ifdef SDL_JOYSTICK_HIDAPI
     if (HIDAPI_IsDevicePresent(vendor, product, version, pDevice->product)) {
         /* The HIDAPI driver is taking care of this device */
-        return 0;
+        return SDL_FALSE;
     }
 #endif
 
-    SDL_memset(pDevice->guid.data, 0, sizeof(pDevice->guid.data));
-
-    if (vendor && product) {
-        *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
-        *guid16++ = SDL_SwapLE16(SDL_crc16(0, pDevice->product, SDL_strlen(pDevice->product)));
-        *guid16++ = SDL_SwapLE16((Uint16)vendor);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16((Uint16)product);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16((Uint16)version);
-        *guid16++ = 0;
-    } else {
-        *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
-        *guid16++ = SDL_SwapLE16(SDL_crc16(0, pDevice->product, SDL_strlen(pDevice->product)));
-        SDL_strlcpy((char*)guid16, pDevice->product, sizeof(pDevice->guid.data) - 4);
-    }
+    pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0);
 
     array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
     if (array) {
diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c
index 628a979c382..c875e991bce 100644
--- a/src/joystick/emscripten/SDL_sysjoystick.c
+++ b/src/joystick/emscripten/SDL_sysjoystick.c
@@ -396,14 +396,7 @@ EMSCRIPTEN_JoystickGetDeviceGUID(int device_index)
 {
     /* 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);
-    *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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 static int
diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc
index dc2cc89745e..cacaf76638f 100644
--- a/src/joystick/haiku/SDL_haikujoystick.cc
+++ b/src/joystick/haiku/SDL_haikujoystick.cc
@@ -252,14 +252,7 @@ extern "C"
     {
         /* the GUID is just the name for now */
         const char *name = HAIKU_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;
+        return SDL_CreateJoystickGUIDForName(name);
     }
 
     static int HAIKU_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index d95abd45989..a7baee6348c 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -634,26 +634,8 @@ 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;
-    }
+    /* 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);
 
     if (num_children > 0) {
         int i;
diff --git a/src/joystick/iphoneos/SDL_mfijoystick.m b/src/joystick/iphoneos/SDL_mfijoystick.m
index 372cfcc809d..6c04e3800e8 100644
--- a/src/joystick/iphoneos/SDL_mfijoystick.m
+++ b/src/joystick/iphoneos/SDL_mfijoystick.m
@@ -220,7 +220,6 @@ @interface GCMicroGamepad (SDL)
 static BOOL
 IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
 {
-    Uint16 *guid16 = (Uint16 *)device->guid.data;
     Uint16 vendor = 0;
     Uint16 product = 0;
     Uint8 subtype = 0;
@@ -472,23 +471,17 @@ @interface GCMicroGamepad (SDL)
     }
 #endif /* TARGET_OS_TV */
 
-    /* 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++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name)));
-    *guid16++ = SDL_SwapLE16(vendor);
-    *guid16++ = 0;
-    *guid16++ = SDL_SwapLE16(product);
-    *guid16++ = 0;
-
-    *guid16++ = SDL_SwapLE16(device->button_mask);
-
     if (vendor == USB_VENDOR_APPLE) {
         /* Note that this is an MFI controller and what subtype it is */
-        device->guid.data[14] = 'm';
-        device->guid.data[15] = subtype;
+        device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, 0, name, 'm', subtype);
     } else {
-        device->guid.data[15] = subtype;
+        device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, 0, name, 0, subtype);
+    }
+
+    /* Update the GUID with capability bits */
+    {
+        Uint16 *guid16 = (Uint16 *)device->guid.data;
+        guid16[6] = SDL_SwapLE16(device->button_mask);
     }
 
     /* This will be set when the first button press of the controller is
diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index 497b1849012..bca23c358d9 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -192,7 +192,6 @@ static int
 IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
 {
     struct input_id inpid;
-    Uint16 *guid16 = (Uint16 *)guid->data;
     char *name;
     char product_string[128];
 
@@ -236,23 +235,7 @@ IsJoystick(const char *path, int fd, char **name_return, SDL_JoystickGUID *guid)
     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
 
-    SDL_memset(guid->data, 0, sizeof(guid->data));
-
-    /* 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++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name)));
-
-    if (inpid.vendor && inpid.product) {
-        *guid16++ = SDL_SwapLE16(inpid.vendor);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(inpid.product);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(inpid.version);
-        *guid16++ = 0;
-    } else {
-        SDL_strlcpy((char*)guid16, name, sizeof(guid->data) - 4);
-    }
+    *guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, name, 0, 0);
 
     if (SDL_ShouldIgnoreJoystick(name, *guid)) {
         SDL_free(name);
diff --git a/src/joystick/os2/SDL_os2joystick.c b/src/joystick/os2/SDL_os2joystick.c
index e49fa32899e..bf2dc605cad 100644
--- a/src/joystick/os2/SDL_os2joystick.c
+++ b/src/joystick/os2/SDL_os2joystick.c
@@ -401,14 +401,7 @@ static SDL_JoystickGUID OS2_JoystickGetDeviceGUID(int device_index)
 {
     /* 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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 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 cf4a82b960e..c43a1ef1078 100644
--- a/src/joystick/ps2/SDL_sysjoystick.c
+++ b/src/joystick/ps2/SDL_sysjoystick.c
@@ -171,14 +171,7 @@ static SDL_JoystickGUID PS2_JoystickGetDeviceGUID(int device_index)
 {
     /* 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);
-    *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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 /* Function to get the current instance id of the joystick located at device_index */
diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c
index 762027346ff..06c0f285bfd 100644
--- a/src/joystick/psp/SDL_sysjoystick.c
+++ b/src/joystick/psp/SDL_sysjoystick.c
@@ -136,14 +136,7 @@ static SDL_JoystickGUID PSP_JoystickGetDeviceGUID(int device_index)
 {
     /* 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);
-    *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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 /* Function to perform the mapping from device index to the instance id for this index */
diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c
index 9849a8c9668..9a6d9430e50 100644
--- a/src/joystick/virtual/SDL_virtualjoystick.c
+++ b/src/joystick/virtual/SDL_virtualjoystick.c
@@ -101,7 +101,6 @@ SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
     joystick_hwdata *hwdata = NULL;
     int device_index = -1;
     const char *name = NULL;
-    Uint16 *guid16;
     int axis_triggerleft = -1;
     int axis_triggerright = -1;
 
@@ -194,21 +193,7 @@ SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc)
         }
     }
 
-    /* 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 = (Uint16 *)hwdata->guid.data;
-    *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_VIRTUAL);
-    *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);
-    *guid16++ = 0;
-    *guid16++ = 0;
-    *guid16++ = 0; /* This will be overwritten below with the virtual controller signature */
-
-    /* Note that this is a Virtual device and what subtype it is */
-    hwdata->guid.data[14] = 'v';
-    hwdata->guid.data[15] = (Uint8)hwdata->desc.type;
+    hwdata->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_VIRTUAL, hwdata->desc.vendor_id, hwdata->desc.product_id, 0, name, 'v', (Uint8)hwdata->desc.type);
 
     /* Allocate fields for different control-types */
     if (hwdata->desc.naxes > 0) {
diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c
index a88983291da..059b8799802 100644
--- a/src/joystick/vita/SDL_sysjoystick.c
+++ b/src/joystick/vita/SDL_sysjoystick.c
@@ -345,14 +345,7 @@ 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;
-    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;
+    return SDL_CreateJoystickGUIDForName(name);
 }
 
 static int
diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c
index 38040c3893b..95cd09a495c 100644
--- a/src/joystick/windows/SDL_dinputjoystick.c
+++ b/src/joystick/windows/SDL_dinputjoystick.c
@@ -443,7 +443,6 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
 #define CHECK(expression) { if(!(expression)) goto err; }
     JoyStick_DeviceData *pNewJoystick = NULL;
     JoyStick_DeviceData *pPrevJoystick = NULL;
-    Uint16 *guid16;
     Uint16 vendor = 0;
     Uint16 product = 0;
     Uint16 version = 0;
@@ -493,25 +492,14 @@ EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
     SDL_zerop(pNewJoystick);
     SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path));
     SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
-    SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
 
     pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
     CHECK(pNewJoystick->joystickname);
 
-    guid16 = (Uint16 *)pNewJoystick->guid.data;
     if (vendor && product) {
-        *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
-        *guid16++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname)));
-        *guid16++ = SDL_SwapLE16(vendor);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(product);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(version);
-        *guid16++ = 0;
+        pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 0, 0);
     } else {
-        *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_BLUETOOTH);
-        *guid16++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname)));
-        SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
+        pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, pNewJoystick->joystickname, 0, 0);
     }
 
     CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c
index d760a7db2d8..42490ea8b30 100644
--- a/src/joystick/windows/SDL_rawinputjoystick.c
+++ b/src/joystick/windows/SDL_rawinputjoystick.c
@@ -779,25 +779,8 @@ 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->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);
 
diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
index b64df7f45ed..cf9e77b6e36 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -254,7 +254,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
         Uint16 product = 0;
         Uint16 version = 0;
         SDL_JoystickType type = SDL_JOYSTICK_TYPE_UNKNOWN;
-        Uint16 *guid16 = (Uint16 *)guid.data;
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
         __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL;
         SDL_bool ignore_joystick = SDL_FALSE;
@@ -319,18 +318,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++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name)));
-        *guid16++ = SDL_SwapLE16(vendor);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(product);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(version);
-        *guid16++ = 0;
-
-        /* Note that this is a Windows Gaming Input device for special handling elsewhere */
-        guid.data[14] = 'w';
-        guid.data[15] = (Uint8)type;
+        guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, name, 'w', (Uint8)type);
 
 #ifdef SDL_JOYSTICK_HIDAPI
         if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c
index a7026a0bb59..05f5e002bef 100644
--- a/src/joystick/windows/SDL_xinputjoystick.c
+++ b/src/joystick/windows/SDL_xinputjoystick.c
@@ -286,22 +286,7 @@ AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
     }
     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++ = SDL_SwapLE16(SDL_crc16(0, pNewJoystick->joystickname, SDL_strlen(pNewJoystick->joystickname)));
-        *guid16++ = SDL_SwapLE16(vendor);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(product);
-        *guid16++ = 0;
-        *guid16++ = SDL_SwapLE16(version);
-        *guid16++ = 0;
-
-        /* Note that this is an XInput device and what subtype it is */
-        pNewJoystick->guid.data[14] = 'x';
-        pNewJoystick->guid.data[15] = SubType;
+        pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, pNewJoystick->joystickname, 'x', SubType);
     }
     pNewJoystick->SubType = SubType;
     pNewJoystick->XInputUserId = userid;