input: Hold joystick GUID in binary form

This commit is contained in:
Emmanuel Gil Peyrot 2021-03-23 12:42:32 +01:00
parent 11324968ee
commit 1698fb2af1
7 changed files with 103 additions and 69 deletions

View File

@ -155,8 +155,7 @@ cacheRead(const char *path, _GLFWmapping** out, int* count)
{ {
mapping = &mappings[i]; mapping = &mappings[i];
FREAD_n(mapping->name, 128, f); FREAD_n(mapping->name, 128, f);
FREAD_n(mapping->guid, 32, f); FREAD_n(mapping->guid, 16, f);
mapping->guid[32] = '\0';
FREAD_n(mapping->buttons, 15, f); FREAD_n(mapping->buttons, 15, f);
FREAD_n(mapping->axes, 6, f); FREAD_n(mapping->axes, 6, f);
} }
@ -202,7 +201,7 @@ cacheWrite(const char *path, const _GLFWmapping* mappings, int count)
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
mapping = &mappings[i]; mapping = &mappings[i];
FWRITE_n(mapping->name, 128, f); FWRITE_n(mapping->name, 128, f);
FWRITE_n(mapping->guid, 32, f); FWRITE_n(mapping->guid, 16, f);
FWRITE_n(mapping->buttons, 15, f); FWRITE_n(mapping->buttons, 15, f);
FWRITE_n(mapping->axes, 6, f); FWRITE_n(mapping->axes, 6, f);
} }

View File

@ -126,7 +126,7 @@ static void matchCallback(void* context,
{ {
int jid; int jid;
char name[256]; char name[256];
char guid[33]; uint8_t guid[16];
CFIndex i; CFIndex i;
CFTypeRef property; CFTypeRef property;
uint32_t vendor = 0, product = 0, version = 0; uint32_t vendor = 0, product = 0, version = 0;
@ -169,17 +169,18 @@ static void matchCallback(void* context,
// Generate a joystick GUID that matches the SDL 2.0.5+ one // Generate a joystick GUID that matches the SDL 2.0.5+ one
if (vendor && product) if (vendor && product)
{ {
sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000", guid[0] = 3;
(uint8_t) vendor, (uint8_t) (vendor >> 8), guid[4] = vendor & 0xff;
(uint8_t) product, (uint8_t) (product >> 8), guid[5] = vendor >> 8;
(uint8_t) version, (uint8_t) (version >> 8)); guid[8] = product & 0xff;
guid[9] = product >> 8;
guid[12] = version & 0xff;
guid[13] = version >> 8;
} }
else else
{ {
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00", guid[0] = 5;
name[0], name[1], name[2], name[3], memcpy(&guid[4], name, 11);
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
} }
CFArrayRef elements = CFArrayRef elements =
@ -469,15 +470,17 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
return js->present; return js->present;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(uint8_t guid[16])
{ {
if ((strncmp(guid + 4, "000000000000", 12) == 0) && if ((memcmp(guid + 2, "\0\0\0\0\0\0", 6) == 0) &&
(strncmp(guid + 20, "000000000000", 12) == 0)) (memcmp(guid + 10, "\0\0\0\0\0\0", 6) == 0))
{ {
char original[33]; uint8_t original[16];
strncpy(original, guid, sizeof(original) - 1); memcpy(original, guid, sizeof(original));
sprintf(guid, "03000000%.4s0000%.4s000000000000", memset(guid, '\0', sizeof(original));
original, original + 16); guid[0] = 3;
memcpy(guid + 4, original, 2);
memcpy(guid + 8, original + 8, 2);
} }
} }

View File

@ -30,8 +30,10 @@
#include "internal.h" #include "internal.h"
#include <assert.h> #include <assert.h>
#include <ctype.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -65,13 +67,13 @@ static GLFWbool initJoysticks(void)
// Finds a mapping based on joystick GUID // Finds a mapping based on joystick GUID
// //
static _GLFWmapping* findMapping(const char* guid) static _GLFWmapping* findMapping(const uint8_t guid[16])
{ {
int i; int i;
for (i = 0; i < _glfw.mappingCount; i++) for (i = 0; i < _glfw.mappingCount; i++)
{ {
if (strncmp(_glfw.mappings[i].guid, guid, 32) == 0) if (memcmp(_glfw.mappings[i].guid, guid, sizeof(_glfw.mappings[i].guid)) == 0)
return _glfw.mappings + i; return _glfw.mappings + i;
} }
@ -93,6 +95,19 @@ static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
return GLFW_TRUE; return GLFW_TRUE;
} }
// Converts a binary joystick GUID into a string
//
static void generateUserReadableGUID(const uint8_t guid[16],
char out[33])
{
snprintf(out, 33,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
guid[0], guid[1], guid[2], guid[3],
guid[4], guid[5], guid[6], guid[7],
guid[8], guid[9], guid[10], guid[11],
guid[12], guid[13], guid[14], guid[15]);
}
// Finds a mapping based on joystick GUID and verifies element indices // Finds a mapping based on joystick GUID and verifies element indices
// //
static _GLFWmapping* findValidMapping(const _GLFWjoystick* js) static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
@ -106,9 +121,11 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
{ {
if (!isValidElementForJoystick(mapping->buttons + i, js)) if (!isValidElementForJoystick(mapping->buttons + i, js))
{ {
char guid[33];
generateUserReadableGUID(mapping->guid, guid);
_glfwInputError(GLFW_INVALID_VALUE, _glfwInputError(GLFW_INVALID_VALUE,
"Invalid button in gamepad mapping %s (%s)", "Invalid button in gamepad mapping %s (%s)",
mapping->guid, guid,
mapping->name); mapping->name);
return NULL; return NULL;
} }
@ -118,9 +135,11 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
{ {
if (!isValidElementForJoystick(mapping->axes + i, js)) if (!isValidElementForJoystick(mapping->axes + i, js))
{ {
char guid[33];
generateUserReadableGUID(mapping->guid, guid);
_glfwInputError(GLFW_INVALID_VALUE, _glfwInputError(GLFW_INVALID_VALUE,
"Invalid axis in gamepad mapping %s (%s)", "Invalid axis in gamepad mapping %s (%s)",
mapping->guid, guid,
mapping->name); mapping->name);
return NULL; return NULL;
} }
@ -173,7 +192,23 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
return GLFW_FALSE; return GLFW_FALSE;
} }
memcpy(mapping->guid, c, length); for (i = 0; i < 16; i++)
{
char nibble1 = c[2 * i];
char nibble2 = c[2 * i + 1];
uint8_t value;
if (!isxdigit(nibble1) || !isxdigit(nibble2))
{
_glfwInputError(GLFW_INVALID_VALUE, NULL);
return GLFW_FALSE;
}
nibble1 = toupper(nibble1);
nibble2 = toupper(nibble2);
value = ((nibble1 >= 'A') ? nibble1 - 'A' + 10 : nibble1 - '0') << 4
| ((nibble2 >= 'A') ? nibble2 - 'A' + 10 : nibble2 - '0');
mapping->guid[i] = value;
}
c += length + 1; c += length + 1;
length = strcspn(c, ","); length = strcspn(c, ",");
@ -261,12 +296,6 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
c += strspn(c, ","); c += strspn(c, ",");
} }
for (i = 0; i < 32; i++)
{
if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
mapping->guid[i] += 'a' - 'A';
}
_glfwPlatformUpdateGamepadGUID(mapping->guid); _glfwPlatformUpdateGamepadGUID(mapping->guid);
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -431,7 +460,7 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
// Returns an available joystick object with arrays and name allocated // Returns an available joystick object with arrays and name allocated
// //
_GLFWjoystick* _glfwAllocJoystick(const char* name, _GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid, const uint8_t guid[16],
int axisCount, int axisCount,
int buttonCount, int buttonCount,
int hatCount) int hatCount)
@ -458,7 +487,8 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
js->buttonCount = buttonCount; js->buttonCount = buttonCount;
js->hatCount = hatCount; js->hatCount = hatCount;
strncpy(js->guid, guid, sizeof(js->guid) - 1); memcpy(js->guid, guid, sizeof(js->guid));
generateUserReadableGUID(guid, js->userReadableGUID);
js->mapping = findValidMapping(js); js->mapping = findValidMapping(js);
return js; return js;
@ -1112,7 +1142,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE)) if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return NULL; return NULL;
return js->guid; return js->userReadableGUID;
} }
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer) GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)

View File

@ -477,7 +477,7 @@ struct _GLFWmapelement
struct _GLFWmapping struct _GLFWmapping
{ {
char name[128]; char name[128];
char guid[33]; uint8_t guid[16];
_GLFWmapelement buttons[15]; _GLFWmapelement buttons[15];
_GLFWmapelement axes[6]; _GLFWmapelement axes[6];
}; };
@ -495,7 +495,8 @@ struct _GLFWjoystick
int hatCount; int hatCount;
char* name; char* name;
void* userPointer; void* userPointer;
char guid[33]; uint8_t guid[16];
char userReadableGUID[33];
_GLFWmapping* mapping; _GLFWmapping* mapping;
// This is defined in the joystick API's joystick.h // This is defined in the joystick API's joystick.h
@ -636,7 +637,7 @@ const char* _glfwPlatformGetClipboardString(void);
GLFWbool _glfwPlatformInitJoysticks(void); GLFWbool _glfwPlatformInitJoysticks(void);
void _glfwPlatformTerminateJoysticks(void); void _glfwPlatformTerminateJoysticks(void);
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
void _glfwPlatformUpdateGamepadGUID(char* guid); void _glfwPlatformUpdateGamepadGUID(uint8_t guid[16]);
uint64_t _glfwPlatformGetTimerValue(void); uint64_t _glfwPlatformGetTimerValue(void);
uint64_t _glfwPlatformGetTimerFrequency(void); uint64_t _glfwPlatformGetTimerFrequency(void);
@ -778,7 +779,7 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
_GLFWjoystick* _glfwAllocJoystick(const char* name, _GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid, const uint8_t guid[16],
int axisCount, int axisCount,
int buttonCount, int buttonCount,
int hatCount); int hatCount);

View File

@ -168,24 +168,25 @@ static GLFWbool openJoystickDevice(const char* path)
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0) if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
strncpy(name, "Unknown", sizeof(name)); strncpy(name, "Unknown", sizeof(name));
char guid[33] = ""; uint8_t guid[16] = {0};
// Generate a joystick GUID that matches the SDL 2.0.5+ one // Generate a joystick GUID that matches the SDL 2.0.5+ one
if (id.vendor && id.product && id.version) if (id.vendor && id.product && id.version)
{ {
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000", guid[0] = id.bustype & 0xff;
id.bustype & 0xff, id.bustype >> 8, guid[1] = id.bustype >> 8;
id.vendor & 0xff, id.vendor >> 8, guid[4] = id.vendor & 0xff;
id.product & 0xff, id.product >> 8, guid[5] = id.vendor >> 8;
id.version & 0xff, id.version >> 8); guid[8] = id.product & 0xff;
guid[9] = id.product >> 8;
guid[12] = id.version & 0xff;
guid[13] = id.version >> 8;
} }
else else
{ {
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00", guid[0] = id.bustype & 0xff;
id.bustype & 0xff, id.bustype >> 8, guid[1] = id.bustype >> 8;
name[0], name[1], name[2], name[3], memcpy(&guid[4], name, 11);
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
} }
int axisCount = 0, buttonCount = 0, hatCount = 0; int axisCount = 0, buttonCount = 0, hatCount = 0;
@ -422,7 +423,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
return js->present; return js->present;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(uint8_t guid[16])
{ {
} }

View File

@ -47,7 +47,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
return GLFW_FALSE; return GLFW_FALSE;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(uint8_t guid[16])
{ {
} }

View File

@ -351,7 +351,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
IDirectInputDevice8* device; IDirectInputDevice8* device;
_GLFWobjenumWin32 data; _GLFWobjenumWin32 data;
_GLFWjoystick* js; _GLFWjoystick* js;
char guid[33]; uint8_t guid[16] = {0};
char name[256]; char name[256];
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
@ -452,18 +452,16 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
// Generate a joystick GUID that matches the SDL 2.0.5+ one // Generate a joystick GUID that matches the SDL 2.0.5+ one
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0) if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
{ {
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000", guid[0] = 3;
(uint8_t) di->guidProduct.Data1, guid[4] = di->guidProduct.Data1 & 0xff;
(uint8_t) (di->guidProduct.Data1 >> 8), guid[5] = (di->guidProduct.Data1 >> 8) & 0xff;
(uint8_t) (di->guidProduct.Data1 >> 16), guid[8] = (di->guidProduct.Data1 >> 16) & 0xff;
(uint8_t) (di->guidProduct.Data1 >> 24)); guid[9] = (di->guidProduct.Data1 >> 24) & 0xff;
} }
else else
{ {
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00", guid[0] = 5;
name[0], name[1], name[2], name[3], memcpy(&guid[4], name, 11);
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
} }
js = _glfwAllocJoystick(name, guid, js = _glfwAllocJoystick(name, guid,
@ -502,7 +500,7 @@ void _glfwDetectJoystickConnectionWin32(void)
for (index = 0; index < XUSER_MAX_COUNT; index++) for (index = 0; index < XUSER_MAX_COUNT; index++)
{ {
int jid; int jid;
char guid[33]; uint8_t guid[16] = {0};
XINPUT_CAPABILITIES xic; XINPUT_CAPABILITIES xic;
_GLFWjoystick* js; _GLFWjoystick* js;
@ -523,8 +521,8 @@ void _glfwDetectJoystickConnectionWin32(void)
continue; continue;
// Generate a joystick GUID that matches the SDL 2.0.5+ one // Generate a joystick GUID that matches the SDL 2.0.5+ one
sprintf(guid, "78696e707574%02x000000000000000000", memcpy(guid, "\x78\x69\x6e\x70\x75\x74", 6);
xic.SubType & 0xff); guid[6] = xic.SubType & 0xff;
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1); js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
if (!js) if (!js)
@ -740,14 +738,16 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
return GLFW_TRUE; return GLFW_TRUE;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(uint8_t guid[16])
{ {
if (strcmp(guid + 20, "504944564944") == 0) if (memcmp(guid + 10, "\x50\x49\x44\x56\x49\x44", 6) == 0)
{ {
char original[33]; uint8_t original[16];
strncpy(original, guid, sizeof(original) - 1); memcpy(original, guid, sizeof(original));
sprintf(guid, "03000000%.4s0000%.4s000000000000", memset(guid, '\0', sizeof(original));
original, original + 4); guid[0] = 3;
memcpy(guid + 4, original, 2);
memcpy(guid + 8, original + 2, 2);
} }
} }