mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Gamepad (Windows): detect gamepad name by productId
Also improve performance
This commit is contained in:
@@ -13,6 +13,7 @@ Bugfixes:
|
||||
* Fix date time format
|
||||
* Fix compiling with musl (Wifi, Linux, #429)
|
||||
* Don't exit if libpci is failed to init (GPU, Linux, #433)
|
||||
* Names of most well-known gamepads are correctly printed instead of `Wireless Controller` on Windows
|
||||
|
||||
Changes:
|
||||
* Use json-c to parse JSON strings for comments support, instead of using unmaintained cJSON
|
||||
|
||||
+2
-2
@@ -511,7 +511,7 @@ elseif(WIN32)
|
||||
src/detection/gpu/gpu_windows.cpp
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/localip/localip_windows.c
|
||||
src/detection/gamepad/gamepad_windows.cpp
|
||||
src/detection/gamepad/gamepad_windows.c
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/memory/memory_windows.c
|
||||
src/detection/opengl/opengl_windows.c
|
||||
@@ -729,7 +729,7 @@ elseif(WIN32)
|
||||
PRIVATE "version"
|
||||
PRIVATE "setupapi"
|
||||
PRIVATE "dxgi"
|
||||
PRIVATE "dinput8"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "powrprof"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "gamepad.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
|
||||
{
|
||||
switch (vendorId)
|
||||
{
|
||||
// Nintendo
|
||||
case 0x057E:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x2006: return "Nintendo Switch Joycon L";
|
||||
case 0x2007: return "Nintendo Switch Joycon R";
|
||||
case 0x2009: return "Nintendo Switch Pro";
|
||||
case 0x200E: return "Nintendo Switch Charging Grip";
|
||||
case 0x2017: return "Nintendo Switch SNES Controller";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Sony
|
||||
case 0x054C:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x0268: return "Sony Playstation 3 Controller";
|
||||
|
||||
case 0x05C4: return "Sony DualShock 4 Gen1";
|
||||
case 0x09CC: return "Sony DualShock 4 Gen2";
|
||||
case 0x0BA0: return "Sony PS4 Controller USB receiver";
|
||||
|
||||
case 0x0CE6: return "Sony DualSense";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft
|
||||
case 0x045E:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
|
||||
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
|
||||
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
|
||||
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
|
||||
|
||||
case 0x028E: return "Microsoft XBox 360";
|
||||
case 0x028F: return "Microsoft XBox 360 v2";
|
||||
case 0x02A1: return "Microsoft XBox 360";
|
||||
case 0x0291: return "Microsoft XBox 360 USB receiver";
|
||||
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
|
||||
case 0x02DD: return "Microsoft XBox One";
|
||||
case 0xB326: return "Microsoft XBox One Firmware 2015";
|
||||
case 0x02E3: return "Microsoft XBox One Elite";
|
||||
case 0x02FF: return "Microsoft XBox One Elite";
|
||||
case 0x02EA: return "Microsoft XBox One S";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Logitech
|
||||
case 0x046D:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0xC216: return "Logitech F310, DirectInput";
|
||||
case 0xC218: return "Logitech F510, DirectInput";
|
||||
case 0xC219: return "Logitech F710, DirectInput";
|
||||
case 0xC21D: return "Logitech F310";
|
||||
case 0xC21E: return "Logitech F510";
|
||||
case 0xC21F: return "Logitech F710";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
UINT nDevices = 0;
|
||||
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)))
|
||||
return "GetRawInputDeviceList(NULL) failed";
|
||||
if (nDevices == 0)
|
||||
return "No HID devices found";
|
||||
RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
|
||||
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
|
||||
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
|
||||
|
||||
for (UINT i = 0; i < nDevices; ++i) {
|
||||
if (pRawInputDeviceList[i].dwType != 2) continue;
|
||||
|
||||
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
|
||||
|
||||
RID_DEVICE_INFO rdi;
|
||||
UINT rdiSize = sizeof(rdi);
|
||||
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1)
|
||||
continue;
|
||||
|
||||
if (rdi.hid.usUsagePage != 1 || rdi.hid.usUsage != 5) // Gamepad
|
||||
continue;
|
||||
|
||||
WCHAR devName[MAX_PATH] = L"";
|
||||
UINT nameSize = MAX_PATH;
|
||||
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1)
|
||||
continue;
|
||||
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInit(&device->identifier);
|
||||
ffStrbufSetWS(&device->identifier, devName);
|
||||
ffStrbufInit(&device->name);
|
||||
|
||||
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
if (knownGamepad)
|
||||
ffStrbufSetS(&device->name, knownGamepad);
|
||||
else
|
||||
{
|
||||
wchar_t displayName[126];
|
||||
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
|
||||
ffStrbufSetWS(&device->name, displayName);
|
||||
else
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
extern "C" {
|
||||
#include "gamepad.h"
|
||||
}
|
||||
|
||||
#include <initguid.h>
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
CALLBACK BOOL DIEnumDevicesCallback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef)
|
||||
{
|
||||
FFlist* devices = (FFlist*) pvRef;
|
||||
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitF(&device->identifier, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
|
||||
lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3,
|
||||
lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3],
|
||||
lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]);
|
||||
ffStrbufInitS(&device->name, lpddi->tszInstanceName);
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
IDirectInput8A* dinput;
|
||||
if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL)))
|
||||
return "DirectInput8Create() failed";
|
||||
dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ATTACHEDONLY);
|
||||
dinput->Release();
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user