Match gamepad by USB vendor+product on Linux

This commit is contained in:
Locria Cyber 2023-06-12 22:44:29 +00:00
parent 3fa2360720
commit 1e9380584a
No known key found for this signature in database
GPG Key ID: ED0D424AE4406330
3 changed files with 57 additions and 3 deletions

View File

@ -67,15 +67,50 @@ static GLFWbool initJoysticks(void)
return _glfw.joysticksInitialized = GLFW_TRUE; return _glfw.joysticksInitialized = GLFW_TRUE;
} }
uint16_t parseHexDigit(char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
assert(GLFW_FALSE);
}
struct vendor_product
{
uint16_t vendor;
uint16_t product;
};
static struct vendor_product parseGUID(const char* guid)
{
struct vendor_product result;
result.vendor = parseHexDigit(guid[8]) | (parseHexDigit(guid[9]) << 8);
result.product = parseHexDigit(guid[16]) | (parseHexDigit(guid[17]) << 8);
return result;
}
// Finds a mapping based on joystick GUID // Finds a mapping based on joystick GUID
// //
static _GLFWmapping* findMapping(const char* guid) static _GLFWmapping* findMapping(const char* guid)
{ {
int i; struct vendor_product this;
for (i = 0; i < _glfw.mappingCount; i++) // exact match
for (int i = 0; i < _glfw.mappingCount; i++)
{ {
if (strcmp(_glfw.mappings[i].guid, guid) == 0) if (strncmp(_glfw.mappings[i].guid, guid, 32) == 0)
return _glfw.mappings + i;
}
// only match vendor product
this = parseGUID(guid);
for (int i = 0; i < _glfw.mappingCount; i++)
{
struct vendor_product that = parseGUID(_glfw.mappings[i].guid);
if (memcmp(&this, &that, sizeof(struct vendor_product)) == 0)
return _glfw.mappings + i; return _glfw.mappings + i;
} }

View File

@ -74,6 +74,7 @@ typedef struct _GLFWmonitor _GLFWmonitor;
typedef struct _GLFWcursor _GLFWcursor; typedef struct _GLFWcursor _GLFWcursor;
typedef struct _GLFWmapelement _GLFWmapelement; typedef struct _GLFWmapelement _GLFWmapelement;
typedef struct _GLFWmapping _GLFWmapping; typedef struct _GLFWmapping _GLFWmapping;
typedef struct _GLFWusbinfo _GLFWusbinfo;
typedef struct _GLFWjoystick _GLFWjoystick; typedef struct _GLFWjoystick _GLFWjoystick;
typedef struct _GLFWtls _GLFWtls; typedef struct _GLFWtls _GLFWtls;
typedef struct _GLFWmutex _GLFWmutex; typedef struct _GLFWmutex _GLFWmutex;
@ -631,6 +632,16 @@ struct _GLFWmapping
_GLFWmapelement axes[6]; _GLFWmapelement axes[6];
}; };
// USB vendor, product, version
//
struct _GLFWusbinfo
{
uint16_t bustype;
uint16_t vendor;
uint16_t product;
uint16_t version;
};
// Joystick structure // Joystick structure
// //
struct _GLFWjoystick struct _GLFWjoystick
@ -646,6 +657,7 @@ struct _GLFWjoystick
char name[128]; char name[128];
void* userPointer; void* userPointer;
char guid[33]; char guid[33];
_GLFWusbinfo usbInfo;
_GLFWmapping* mapping; _GLFWmapping* mapping;
// This is defined in platform.h // This is defined in platform.h

View File

@ -172,6 +172,12 @@ static GLFWbool openJoystickDevice(const char* path)
char guid[33] = ""; char guid[33] = "";
_GLFWusbinfo usbinfo;
usbinfo.bustype = id.bustype;
usbinfo.vendor = id.vendor;
usbinfo.product = id.product;
usbinfo.version = id.version;
// 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)
{ {
@ -231,6 +237,7 @@ static GLFWbool openJoystickDevice(const char* path)
close(linjs.fd); close(linjs.fd);
return GLFW_FALSE; return GLFW_FALSE;
} }
js->usbInfo = usbinfo;
strncpy(linjs.path, path, sizeof(linjs.path) - 1); strncpy(linjs.path, path, sizeof(linjs.path) - 1);
memcpy(&js->linjs, &linjs, sizeof(linjs)); memcpy(&js->linjs, &linjs, sizeof(linjs));