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];
FREAD_n(mapping->name, 128, f);
FREAD_n(mapping->guid, 32, f);
mapping->guid[32] = '\0';
FREAD_n(mapping->guid, 16, f);
FREAD_n(mapping->buttons, 15, 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) {
mapping = &mappings[i];
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->axes, 6, f);
}

View File

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

View File

@ -30,8 +30,10 @@
#include "internal.h"
#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -65,13 +67,13 @@ static GLFWbool initJoysticks(void)
// Finds a mapping based on joystick GUID
//
static _GLFWmapping* findMapping(const char* guid)
static _GLFWmapping* findMapping(const uint8_t guid[16])
{
int 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;
}
@ -93,6 +95,19 @@ static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
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
//
static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
@ -106,9 +121,11 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
{
if (!isValidElementForJoystick(mapping->buttons + i, js))
{
char guid[33];
generateUserReadableGUID(mapping->guid, guid);
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid button in gamepad mapping %s (%s)",
mapping->guid,
guid,
mapping->name);
return NULL;
}
@ -118,9 +135,11 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
{
if (!isValidElementForJoystick(mapping->axes + i, js))
{
char guid[33];
generateUserReadableGUID(mapping->guid, guid);
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid axis in gamepad mapping %s (%s)",
mapping->guid,
guid,
mapping->name);
return NULL;
}
@ -173,7 +192,23 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
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;
length = strcspn(c, ",");
@ -261,12 +296,6 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
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);
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
//
_GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid,
const uint8_t guid[16],
int axisCount,
int buttonCount,
int hatCount)
@ -458,7 +487,8 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
js->buttonCount = buttonCount;
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);
return js;
@ -1112,7 +1142,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid)
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return NULL;
return js->guid;
return js->userReadableGUID;
}
GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)

View File

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

View File

@ -168,24 +168,25 @@ static GLFWbool openJoystickDevice(const char* path)
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
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
if (id.vendor && id.product && id.version)
{
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
id.bustype & 0xff, id.bustype >> 8,
id.vendor & 0xff, id.vendor >> 8,
id.product & 0xff, id.product >> 8,
id.version & 0xff, id.version >> 8);
guid[0] = id.bustype & 0xff;
guid[1] = id.bustype >> 8;
guid[4] = id.vendor & 0xff;
guid[5] = id.vendor >> 8;
guid[8] = id.product & 0xff;
guid[9] = id.product >> 8;
guid[12] = id.version & 0xff;
guid[13] = id.version >> 8;
}
else
{
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
id.bustype & 0xff, id.bustype >> 8,
name[0], name[1], name[2], name[3],
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
guid[0] = id.bustype & 0xff;
guid[1] = id.bustype >> 8;
memcpy(&guid[4], name, 11);
}
int axisCount = 0, buttonCount = 0, hatCount = 0;
@ -422,7 +423,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
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;
}
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;
_GLFWobjenumWin32 data;
_GLFWjoystick* js;
char guid[33];
uint8_t guid[16] = {0};
char name[256];
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
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
{
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
(uint8_t) di->guidProduct.Data1,
(uint8_t) (di->guidProduct.Data1 >> 8),
(uint8_t) (di->guidProduct.Data1 >> 16),
(uint8_t) (di->guidProduct.Data1 >> 24));
guid[0] = 3;
guid[4] = di->guidProduct.Data1 & 0xff;
guid[5] = (di->guidProduct.Data1 >> 8) & 0xff;
guid[8] = (di->guidProduct.Data1 >> 16) & 0xff;
guid[9] = (di->guidProduct.Data1 >> 24) & 0xff;
}
else
{
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
name[0], name[1], name[2], name[3],
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
guid[0] = 5;
memcpy(&guid[4], name, 11);
}
js = _glfwAllocJoystick(name, guid,
@ -502,7 +500,7 @@ void _glfwDetectJoystickConnectionWin32(void)
for (index = 0; index < XUSER_MAX_COUNT; index++)
{
int jid;
char guid[33];
uint8_t guid[16] = {0};
XINPUT_CAPABILITIES xic;
_GLFWjoystick* js;
@ -523,8 +521,8 @@ void _glfwDetectJoystickConnectionWin32(void)
continue;
// Generate a joystick GUID that matches the SDL 2.0.5+ one
sprintf(guid, "78696e707574%02x000000000000000000",
xic.SubType & 0xff);
memcpy(guid, "\x78\x69\x6e\x70\x75\x74", 6);
guid[6] = xic.SubType & 0xff;
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
if (!js)
@ -740,14 +738,16 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
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];
strncpy(original, guid, sizeof(original) - 1);
sprintf(guid, "03000000%.4s0000%.4s000000000000",
original, original + 4);
uint8_t original[16];
memcpy(original, guid, sizeof(original));
memset(guid, '\0', sizeof(original));
guid[0] = 3;
memcpy(guid + 4, original, 2);
memcpy(guid + 8, original + 2, 2);
}
}