mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-02-04 10:36:50 +00:00
blissbox: use win32 HID API to get pad type on windows, libusb seems broken there
This commit is contained in:
parent
64ef42c9f9
commit
b9394846dc
@ -1531,7 +1531,7 @@ ifneq ($(findstring Win32,$(OS)),)
|
||||
gfx/drivers_font/gdi_font.o \
|
||||
menu/drivers_display/menu_display_gdi.o
|
||||
|
||||
LIBS += -lmsimg32
|
||||
LIBS += -lmsimg32 -lhid -lsetupapi
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_AVFOUNDATION), 1)
|
||||
|
@ -33,6 +33,16 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) && _WIN32_WINNT >= 0x0500
|
||||
/* MinGW Win32 HID API */
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
#include <setupapi.h>
|
||||
#include <hidsdi.h>
|
||||
/* Why doesn't including cguid.h work to get a GUID_NULL instead? */
|
||||
const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#endif
|
||||
|
||||
#include "../input/input_driver.h"
|
||||
#include "../input/include/blissbox.h"
|
||||
|
||||
@ -359,7 +369,256 @@ static void input_autoconfigure_params_free(autoconfig_params_t *params)
|
||||
params->autoconfig_directory = NULL;
|
||||
}
|
||||
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type(int vid, int pid)
|
||||
#ifdef _WIN32
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type_win32(int vid, int pid)
|
||||
{
|
||||
/* TODO: Remove the check for !defined(_MSC_VER) after making sure this builds on MSVC */
|
||||
|
||||
/* HID API is available since Windows 2000 */
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) && _WIN32_WINNT >= 0x0500
|
||||
HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;
|
||||
GUID guidDeviceInterface = {0};
|
||||
BOOL bResult = TRUE;
|
||||
BOOL success = FALSE;
|
||||
HDEVINFO hDeviceInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
|
||||
ULONG requiredLength = 0;
|
||||
LPTSTR lpDevicePath = NULL;
|
||||
char *devicePath = NULL;
|
||||
DWORD index = 0;
|
||||
DWORD intIndex = 0;
|
||||
size_t nLength = 0;
|
||||
unsigned len = 0;
|
||||
unsigned i = 0;
|
||||
char vidPidString[32] = {0};
|
||||
char vidString[5] = {0};
|
||||
char pidString[5] = {0};
|
||||
char report[USB_PACKET_CTRL_LEN + 1] = {0};
|
||||
|
||||
snprintf(vidString, sizeof(vidString), "%04x", vid);
|
||||
snprintf(pidString, sizeof(pidString), "%04x", pid);
|
||||
|
||||
strlcat(vidPidString, "vid_", sizeof(vidPidString));
|
||||
strlcat(vidPidString, vidString, sizeof(vidPidString));
|
||||
strlcat(vidPidString, "&pid_", sizeof(vidPidString));
|
||||
strlcat(vidPidString, pidString, sizeof(vidPidString));
|
||||
|
||||
HidD_GetHidGuid(&guidDeviceInterface);
|
||||
|
||||
if (!memcmp(&guidDeviceInterface, &GUID_NULL, sizeof(GUID_NULL)))
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: null guid\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get information about all the installed devices for the specified
|
||||
* device interface class.
|
||||
*/
|
||||
hDeviceInfo = SetupDiGetClassDevs(
|
||||
&guidDeviceInterface,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
if (hDeviceInfo == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error in SetupDiGetClassDevs: %d.\n", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Enumerate all the device interfaces in the device information set. */
|
||||
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
while (!success)
|
||||
{
|
||||
success = SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData);
|
||||
|
||||
/* Reset for this iteration */
|
||||
if (lpDevicePath)
|
||||
{
|
||||
LocalFree(lpDevicePath);
|
||||
lpDevicePath = NULL;
|
||||
}
|
||||
|
||||
if (pInterfaceDetailData)
|
||||
{
|
||||
LocalFree(pInterfaceDetailData);
|
||||
pInterfaceDetailData = NULL;
|
||||
}
|
||||
|
||||
/* Check if this is the last item */
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
|
||||
deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
|
||||
|
||||
/* Get information about the device interface. */
|
||||
for (intIndex = 0; (bResult = SetupDiEnumDeviceInterfaces(
|
||||
hDeviceInfo,
|
||||
&DeviceInfoData,
|
||||
&guidDeviceInterface,
|
||||
intIndex,
|
||||
&deviceInterfaceData)); intIndex++)
|
||||
{
|
||||
/* Check if this is the last item */
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
|
||||
/* Check for some other error */
|
||||
if (!bResult)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error in SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
|
||||
* which we need to allocate, so we have to call this function twice.
|
||||
* First to get the size so that we know how much to allocate, and
|
||||
* second to do the actual call with the allocated buffer.
|
||||
*/
|
||||
|
||||
bResult = SetupDiGetDeviceInterfaceDetail(
|
||||
hDeviceInfo,
|
||||
&deviceInterfaceData,
|
||||
NULL, 0,
|
||||
&requiredLength,
|
||||
NULL);
|
||||
|
||||
/* Check for some other error */
|
||||
if (!bResult)
|
||||
{
|
||||
if ((ERROR_INSUFFICIENT_BUFFER == GetLastError()) && (requiredLength > 0))
|
||||
{
|
||||
/* we got the size, now allocate buffer */
|
||||
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);
|
||||
|
||||
if (!pInterfaceDetailData)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error allocating memory for the device detail buffer.\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Other error: %d.\n", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the interface detailed data */
|
||||
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
|
||||
/* Now call it with the correct size and allocated buffer */
|
||||
bResult = SetupDiGetDeviceInterfaceDetail(
|
||||
hDeviceInfo,
|
||||
&deviceInterfaceData,
|
||||
pInterfaceDetailData,
|
||||
requiredLength,
|
||||
NULL,
|
||||
&DeviceInfoData);
|
||||
|
||||
/* Check for some other error */
|
||||
if (!bResult)
|
||||
{
|
||||
RARCH_LOG("[Autoconf]: Error in SetupDiGetDeviceInterfaceDetail: %d.\n", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* copy device path */
|
||||
nLength = _tcslen(pInterfaceDetailData->DevicePath) + 1;
|
||||
lpDevicePath = (TCHAR*)LocalAlloc(LPTR, nLength * sizeof(TCHAR));
|
||||
|
||||
StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);
|
||||
|
||||
devicePath = (char*)malloc(nLength);
|
||||
|
||||
for (len = 0; len < nLength; len++)
|
||||
{
|
||||
devicePath[len] = lpDevicePath[len];
|
||||
}
|
||||
|
||||
lpDevicePath[nLength - 1] = 0;
|
||||
|
||||
if (strstr(devicePath, vidPidString))
|
||||
goto found;
|
||||
}
|
||||
|
||||
success = FALSE;
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!lpDevicePath)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: No devicepath. Error %d.", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
found:
|
||||
/* Open the device */
|
||||
hDeviceHandle = CreateFileA(
|
||||
devicePath,
|
||||
GENERIC_READ, /* | GENERIC_WRITE,*/
|
||||
FILE_SHARE_READ, /* | FILE_SHARE_WRITE,*/
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0, /*FILE_FLAG_OVERLAPPED,*/
|
||||
NULL);
|
||||
|
||||
if (hDeviceHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Can't open device: %d.", GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
free(devicePath);
|
||||
LocalFree(lpDevicePath);
|
||||
LocalFree(pInterfaceDetailData);
|
||||
bResult = SetupDiDestroyDeviceInfoList(hDeviceInfo);
|
||||
|
||||
devicePath = NULL;
|
||||
lpDevicePath = NULL;
|
||||
pInterfaceDetailData = NULL;
|
||||
|
||||
if (!bResult)
|
||||
RARCH_ERR("[Autoconf]: Could not destroy device info list.\n");
|
||||
|
||||
if (!hDeviceHandle || hDeviceHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* device is not connected */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
report[0] = BLISSBOX_USB_FEATURE_REPORT_ID;
|
||||
|
||||
HidD_GetFeature(hDeviceHandle, report, sizeof(report));
|
||||
|
||||
CloseHandle(hDeviceHandle);
|
||||
|
||||
for (i = 0; i < sizeof(blissbox_pad_types) / sizeof(blissbox_pad_types[0]); i++)
|
||||
{
|
||||
const blissbox_pad_type_t *pad = &blissbox_pad_types[i];
|
||||
|
||||
if (!pad || string_is_empty(pad->name))
|
||||
continue;
|
||||
|
||||
if (pad->index == report[0])
|
||||
return pad;
|
||||
}
|
||||
|
||||
RARCH_LOG("[Autoconf]: Could not find connected pad in Bliss-Box port#%d.\n", pid - BLISSBOX_PID);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type_libusb(int vid, int pid)
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
unsigned char answer[USB_PACKET_CTRL_LEN] = {0};
|
||||
@ -437,6 +696,22 @@ error:
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type(int vid, int pid)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if defined(_MSC_VER) || defined(_XBOX)
|
||||
/* no MSVC/XBOX support */
|
||||
return NULL;
|
||||
#else
|
||||
/* MinGW */
|
||||
return input_autoconfigure_get_blissbox_pad_type_win32(vid, pid);
|
||||
#endif
|
||||
#else
|
||||
return input_autoconfigure_get_blissbox_pad_type_libusb(vid, pid);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void input_autoconfigure_override_handler(autoconfig_params_t *params)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user