Skip to content

Commit 9ee4c08

Browse files
committed
Gamepad (Windows): detect gamepad name by productId
Also improve performance
1 parent 725d2f2 commit 9ee4c08

File tree

4 files changed

+142
-34
lines changed

4 files changed

+142
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Bugfixes:
1313
* Fix date time format
1414
* Fix compiling with musl (Wifi, Linux, #429)
1515
* Don't exit if libpci is failed to init (GPU, Linux, #433)
16+
* Names of most well-known gamepads are correctly printed instead of `Wireless Controller` on Windows
1617

1718
Changes:
1819
* Use json-c to parse JSON strings for comments support, instead of using unmaintained cJSON

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ elseif(WIN32)
511511
src/detection/gpu/gpu_windows.cpp
512512
src/detection/host/host_windows.c
513513
src/detection/localip/localip_windows.c
514-
src/detection/gamepad/gamepad_windows.cpp
514+
src/detection/gamepad/gamepad_windows.c
515515
src/detection/media/media_nosupport.c
516516
src/detection/memory/memory_windows.c
517517
src/detection/opengl/opengl_windows.c
@@ -729,7 +729,7 @@ elseif(WIN32)
729729
PRIVATE "version"
730730
PRIVATE "setupapi"
731731
PRIVATE "dxgi"
732-
PRIVATE "dinput8"
732+
PRIVATE "hid"
733733
PRIVATE "wtsapi32"
734734
PRIVATE "powrprof"
735735
)
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#include "gamepad.h"
2+
#include "common/io/io.h"
3+
#include "util/mallocHelper.h"
4+
#include "util/windows/unicode.h"
5+
6+
#include <windows.h>
7+
#include <hidsdi.h>
8+
9+
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
10+
{
11+
switch (vendorId)
12+
{
13+
// Nintendo
14+
case 0x057E:
15+
{
16+
switch (productId)
17+
{
18+
case 0x2006: return "Nintendo Switch Joycon L";
19+
case 0x2007: return "Nintendo Switch Joycon R";
20+
case 0x2009: return "Nintendo Switch Pro";
21+
case 0x200E: return "Nintendo Switch Charging Grip";
22+
case 0x2017: return "Nintendo Switch SNES Controller";
23+
24+
default: return NULL;
25+
}
26+
}
27+
28+
// Sony
29+
case 0x054C:
30+
{
31+
switch (productId)
32+
{
33+
case 0x0268: return "Sony Playstation 3 Controller";
34+
35+
case 0x05C4: return "Sony DualShock 4 Gen1";
36+
case 0x09CC: return "Sony DualShock 4 Gen2";
37+
case 0x0BA0: return "Sony PS4 Controller USB receiver";
38+
39+
case 0x0CE6: return "Sony DualSense";
40+
41+
default: return NULL;
42+
}
43+
}
44+
45+
// Microsoft
46+
case 0x045E:
47+
{
48+
switch (productId)
49+
{
50+
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
51+
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
52+
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
53+
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
54+
55+
case 0x028E: return "Microsoft XBox 360";
56+
case 0x028F: return "Microsoft XBox 360 v2";
57+
case 0x02A1: return "Microsoft XBox 360";
58+
case 0x0291: return "Microsoft XBox 360 USB receiver";
59+
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
60+
case 0x02DD: return "Microsoft XBox One";
61+
case 0xB326: return "Microsoft XBox One Firmware 2015";
62+
case 0x02E3: return "Microsoft XBox One Elite";
63+
case 0x02FF: return "Microsoft XBox One Elite";
64+
case 0x02EA: return "Microsoft XBox One S";
65+
66+
default: return NULL;
67+
}
68+
}
69+
70+
// Logitech
71+
case 0x046D:
72+
{
73+
switch (productId)
74+
{
75+
case 0xC216: return "Logitech F310, DirectInput";
76+
case 0xC218: return "Logitech F510, DirectInput";
77+
case 0xC219: return "Logitech F710, DirectInput";
78+
case 0xC21D: return "Logitech F310";
79+
case 0xC21E: return "Logitech F510";
80+
case 0xC21F: return "Logitech F710";
81+
82+
default: return NULL;
83+
}
84+
}
85+
86+
default: return NULL;
87+
}
88+
}
89+
90+
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
91+
{
92+
UINT nDevices = 0;
93+
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)))
94+
return "GetRawInputDeviceList(NULL) failed";
95+
if (nDevices == 0)
96+
return "No HID devices found";
97+
RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
98+
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
99+
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
100+
101+
for (UINT i = 0; i < nDevices; ++i) {
102+
if (pRawInputDeviceList[i].dwType != 2) continue;
103+
104+
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
105+
106+
RID_DEVICE_INFO rdi;
107+
UINT rdiSize = sizeof(rdi);
108+
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1)
109+
continue;
110+
111+
if (rdi.hid.usUsagePage != 1 || rdi.hid.usUsage != 5) // Gamepad
112+
continue;
113+
114+
WCHAR devName[MAX_PATH] = L"";
115+
UINT nameSize = MAX_PATH;
116+
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1)
117+
continue;
118+
119+
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
120+
ffStrbufInit(&device->identifier);
121+
ffStrbufSetWS(&device->identifier, devName);
122+
ffStrbufInit(&device->name);
123+
124+
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
125+
if (knownGamepad)
126+
ffStrbufSetS(&device->name, knownGamepad);
127+
else
128+
{
129+
wchar_t displayName[126];
130+
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
131+
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
132+
ffStrbufSetWS(&device->name, displayName);
133+
else
134+
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
135+
}
136+
}
137+
138+
return NULL;
139+
}

src/detection/gamepad/gamepad_windows.cpp

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)