mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Split up blissbox code into separate file
tasks/task_autodetect_blissbox.c
This commit is contained in:
parent
f852209040
commit
7748ac207c
@ -230,6 +230,7 @@ OBJ += \
|
||||
managers/state_manager.o \
|
||||
gfx/drivers_font_renderer/bitmapfont.o \
|
||||
tasks/task_autodetect.o \
|
||||
tasks/task_autodetect_blissbox.o \
|
||||
input/input_autodetect_builtin.o \
|
||||
input/input_keymaps.o \
|
||||
input/input_remapping.o \
|
||||
|
@ -606,6 +606,7 @@ FONTS
|
||||
INPUT
|
||||
============================================================ */
|
||||
#include "../tasks/task_autodetect.c"
|
||||
#include "../tasks/task_autodetect_blissbox.c"
|
||||
#ifdef HAVE_AUDIOMIXER
|
||||
#include "../tasks/task_audio_mixer.c"
|
||||
#endif
|
||||
|
@ -31,77 +31,12 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
int index;
|
||||
} blissbox_pad_type_t;
|
||||
|
||||
const blissbox_pad_type_t blissbox_pad_types[] =
|
||||
{
|
||||
{"A5200", 6},
|
||||
{"A5200_TB", 50},
|
||||
{"A7800", 4},
|
||||
{"ATARI", 0},
|
||||
{"ATARI_KEYPAD", 43},
|
||||
{"ATMARK", 10},
|
||||
{"BALLY", 42},
|
||||
{"CD32", 24},
|
||||
{"CDI", 33},
|
||||
{"COL", 1},
|
||||
{"COL_FLASHBACK", 48}, /* 3.0 */
|
||||
{"DC_ASCI", 15},
|
||||
{"DC_PAD", 16},
|
||||
{"DC_TWIN", 35}, /* 3.0 */
|
||||
{"FC_ARKANOID", 53},
|
||||
{"FC_NES", 52},
|
||||
{"GC", 9},
|
||||
{"GC_WHEEL", 18},
|
||||
{"GEN_3", 20},
|
||||
{"GEN_6", 21},
|
||||
{"GRAVIS_EX", 38},
|
||||
{"HAMMERHEAD", 40},
|
||||
{"HPD", 7},
|
||||
{"INTELI", 14},
|
||||
{"JAG", 11},
|
||||
{"MSSW", 39},
|
||||
{"N64", 19},
|
||||
{"NEO", 49},
|
||||
{"NES", 17},
|
||||
{"NES_ARKANOID", 30},
|
||||
{"NES_GUN", 28},
|
||||
{"NES_POWERPAD", 36},
|
||||
{"PADDLES", 41},
|
||||
{"PC_FX", 26},
|
||||
{"PC_GAMEPAD", 46},
|
||||
{"PSX_DIGITAL", 65},
|
||||
{"PSX_DS", 115},
|
||||
{"PSX_DS2", 121},
|
||||
{"PSX_FS", 83},
|
||||
{"PSX_JOGCON", 227}, /* 3.0 */
|
||||
{"PSX_NEGCON", 51},
|
||||
{"PSX_WHEEL", 12},
|
||||
{"SAC", 34},
|
||||
{"SATURN_ANALOG", 8},
|
||||
{"SATURN_DIGITAL", 3},
|
||||
{"SMS", 22},
|
||||
{"SNES", 27},
|
||||
{"SNESS_NTT", 47}, /* 3.0 */
|
||||
{"SPEEK", 45},
|
||||
{"TG16", 23},
|
||||
{"TG16_6BUTTON", 54}, /* 3.0 */
|
||||
{"THREE_DO", 25},
|
||||
{"THREE_DO_ANALOG", 37},
|
||||
{"VEC", 5},
|
||||
{"V_BOY", 29},
|
||||
{"WII_CLASSIC", 31},
|
||||
{"WII_DRUM", 55}, /* 3.0 */
|
||||
{"WII_MPLUS", 32},
|
||||
{"WII_NUNCHUK", 13},
|
||||
{"ZXSINC", 44},
|
||||
{"gx4000", 2},
|
||||
{NULL, 0}, /* used to mark unconnected ports, do not remove */
|
||||
};
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -21,56 +21,9 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <lists/dir_list.h>
|
||||
#include <file/file_path.h>
|
||||
#include <file/config_file.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
#ifdef __FreeBSD__
|
||||
#include <libusb.h>
|
||||
#else
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) && _WIN32_WINNT >= 0x0500
|
||||
/* MinGW Win32 HID API */
|
||||
#include <minwindef.h>
|
||||
#include <wtypes.h>
|
||||
#include <tchar.h>
|
||||
#ifdef __NO_INLINE__
|
||||
/* Workaround MinGW issue where compiling without -O2 (which sets __NO_INLINE__) causes the strsafe functions
|
||||
* to never be defined (only declared).
|
||||
*/
|
||||
#define __CRT_STRSAFE_IMPL
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#include <guiddef.h>
|
||||
#include <ks.h>
|
||||
#include <setupapi.h>
|
||||
#include <winapifamily.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <hidsdi.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Why doesn't including cguid.h work to get a GUID_NULL instead? */
|
||||
#ifdef __cplusplus
|
||||
EXTERN_C __attribute__((weak))
|
||||
const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#else
|
||||
__attribute__((weak))
|
||||
const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../input/include/blissbox.h"
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../file_path_special.h"
|
||||
#include "../list_special.h"
|
||||
@ -78,22 +31,9 @@ const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#include "../retroarch.h"
|
||||
|
||||
#include "tasks_internal.h"
|
||||
|
||||
/* HID Class-Specific Requests values. See section 7.2 of the HID specifications */
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_CTRL_IN LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
|
||||
#define USB_PACKET_CTRL_LEN 5
|
||||
#define USB_TIMEOUT 5000 /* timeout in ms */
|
||||
|
||||
/* only one blissbox per machine is currently supported */
|
||||
static const blissbox_pad_type_t *blissbox_pads[BLISSBOX_MAX_PADS] = {NULL};
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
static struct libusb_device_handle *autoconfig_libusb_handle = NULL;
|
||||
#endif
|
||||
#include "../input/include/blissbox.h"
|
||||
|
||||
typedef struct autoconfig_disconnect autoconfig_disconnect_t;
|
||||
typedef struct autoconfig_params autoconfig_params_t;
|
||||
|
||||
struct autoconfig_disconnect
|
||||
{
|
||||
@ -101,16 +41,6 @@ struct autoconfig_disconnect
|
||||
char *msg;
|
||||
};
|
||||
|
||||
struct autoconfig_params
|
||||
{
|
||||
int32_t vid;
|
||||
int32_t pid;
|
||||
unsigned idx;
|
||||
uint32_t max_users;
|
||||
char *name;
|
||||
char *autoconfig_directory;
|
||||
};
|
||||
|
||||
static bool input_autoconfigured[MAX_USERS];
|
||||
static unsigned input_device_name_index[MAX_INPUT_DEVICES];
|
||||
static bool input_autoconfigure_swap_override;
|
||||
@ -418,407 +348,6 @@ static void input_autoconfigure_params_free(autoconfig_params_t *params)
|
||||
params->autoconfig_directory = NULL;
|
||||
}
|
||||
|
||||
#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
|
||||
HDEVINFO hDeviceInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;
|
||||
BOOL bResult = TRUE;
|
||||
BOOL success = FALSE;
|
||||
GUID guidDeviceInterface = {0};
|
||||
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)
|
||||
{
|
||||
/* Windows sometimes erroneously fails to open with a sharing violation:
|
||||
* https://github.com/signal11/hidapi/issues/231
|
||||
* If this happens, trying again with read + write usually works for some reason.
|
||||
*/
|
||||
|
||||
/* 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 for reading and writing: %d.", GetLastError());
|
||||
runloop_msg_queue_push("Bliss-Box already in use. Please make sure other programs are not using it.", 2, 300, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
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);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type_libusb(int vid, int pid)
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
unsigned i;
|
||||
unsigned char answer[USB_PACKET_CTRL_LEN] = {0};
|
||||
int ret = libusb_init(NULL);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not initialize libusb.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
autoconfig_libusb_handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
|
||||
|
||||
if (!autoconfig_libusb_handle)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not find or open libusb device %d:%d.\n", vid, pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_detach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
ret = libusb_set_configuration(autoconfig_libusb_handle, 1);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_set_configuration.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_claim_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_claim_interface.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_control_transfer(autoconfig_libusb_handle, USB_CTRL_IN, USB_HID_GET_REPORT, BLISSBOX_USB_FEATURE_REPORT_ID, 0, answer, USB_PACKET_CTRL_LEN, USB_TIMEOUT);
|
||||
|
||||
if (ret < 0)
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_control_transfer.\n");
|
||||
|
||||
libusb_release_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_attach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
|
||||
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 == answer[0])
|
||||
return pad;
|
||||
}
|
||||
|
||||
RARCH_LOG("[Autoconf]: Could not find connected pad in Bliss-Box port#%d.\n", pid - BLISSBOX_PID);
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
if (params->vid == BLISSBOX_VID)
|
||||
{
|
||||
if (params->pid == BLISSBOX_UPDATE_MODE_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box in update mode detected. Ignoring.\n");
|
||||
else if (params->pid == BLISSBOX_OLD_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box 1.0 firmware detected. Please update to 2.0 or later.\n");
|
||||
else if (params->pid >= BLISSBOX_PID && params->pid <= BLISSBOX_PID + BLISSBOX_MAX_PAD_INDEX)
|
||||
{
|
||||
const blissbox_pad_type_t *pad;
|
||||
char name[255] = {0};
|
||||
int index = params->pid - BLISSBOX_PID;
|
||||
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box detected. Getting pad type...\n");
|
||||
|
||||
if (blissbox_pads[index])
|
||||
pad = blissbox_pads[index];
|
||||
else
|
||||
pad = input_autoconfigure_get_blissbox_pad_type(params->vid, params->pid);
|
||||
|
||||
if (pad && !string_is_empty(pad->name))
|
||||
{
|
||||
RARCH_LOG("[Autoconf]: Found Bliss-Box pad type: %s (%d) in port#%d\n", pad->name, pad->index, index);
|
||||
|
||||
if (params->name)
|
||||
free(params->name);
|
||||
|
||||
/* override name given to autoconfig so it knows what kind of pad this is */
|
||||
strlcat(name, "Bliss-Box 4-Play ", sizeof(name));
|
||||
strlcat(name, pad->name, sizeof(name));
|
||||
|
||||
params->name = strdup(name);
|
||||
|
||||
blissbox_pads[index] = pad;
|
||||
}
|
||||
/* use NULL entry to mark as an unconnected port */
|
||||
else
|
||||
blissbox_pads[index] = &blissbox_pad_types[ARRAY_SIZE(blissbox_pad_types) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void input_autoconfigure_connect_handler(retro_task_t *task)
|
||||
{
|
||||
autoconfig_params_t *params = (autoconfig_params_t*)task->state;
|
||||
@ -999,7 +528,8 @@ void input_autoconfigure_connect(
|
||||
state->max_users = *(
|
||||
input_driver_get_uint(INPUT_ACTION_MAX_USERS));
|
||||
|
||||
input_autoconfigure_override_handler(state);
|
||||
if (state->vid == BLISSBOX_VID)
|
||||
input_autoconfigure_override_handler(state);
|
||||
|
||||
if (!string_is_empty(state->name))
|
||||
input_config_set_device_name(state->idx, state->name);
|
||||
|
551
tasks/task_autodetect_blissbox.c
Normal file
551
tasks/task_autodetect_blissbox.c
Normal file
@ -0,0 +1,551 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "../verbosity.h"
|
||||
#include "../retroarch.h"
|
||||
|
||||
#include "tasks_internal.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
#ifdef __FreeBSD__
|
||||
#include <libusb.h>
|
||||
#else
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) && _WIN32_WINNT >= 0x0500
|
||||
/* MinGW Win32 HID API */
|
||||
#include <minwindef.h>
|
||||
#include <wtypes.h>
|
||||
#include <tchar.h>
|
||||
#ifdef __NO_INLINE__
|
||||
/* Workaround MinGW issue where compiling without -O2 (which sets __NO_INLINE__) causes the strsafe functions
|
||||
* to never be defined (only declared).
|
||||
*/
|
||||
#define __CRT_STRSAFE_IMPL
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#include <guiddef.h>
|
||||
#include <ks.h>
|
||||
#include <setupapi.h>
|
||||
#include <winapifamily.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <hidsdi.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Why doesn't including cguid.h work to get a GUID_NULL instead? */
|
||||
#ifdef __cplusplus
|
||||
EXTERN_C __attribute__((weak))
|
||||
const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#else
|
||||
__attribute__((weak))
|
||||
const GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../input/include/blissbox.h"
|
||||
|
||||
/* HID Class-Specific Requests values. See section 7.2 of the HID specifications */
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_CTRL_IN LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
|
||||
#define USB_PACKET_CTRL_LEN 5
|
||||
#define USB_TIMEOUT 5000 /* timeout in ms */
|
||||
|
||||
const blissbox_pad_type_t blissbox_pad_types[] =
|
||||
{
|
||||
{"A5200", 6},
|
||||
{"A5200_TB", 50},
|
||||
{"A7800", 4},
|
||||
{"ATARI", 0},
|
||||
{"ATARI_KEYPAD", 43},
|
||||
{"ATMARK", 10},
|
||||
{"BALLY", 42},
|
||||
{"CD32", 24},
|
||||
{"CDI", 33},
|
||||
{"COL", 1},
|
||||
{"COL_FLASHBACK", 48}, /* 3.0 */
|
||||
{"DC_ASCI", 15},
|
||||
{"DC_PAD", 16},
|
||||
{"DC_TWIN", 35}, /* 3.0 */
|
||||
{"FC_ARKANOID", 53},
|
||||
{"FC_NES", 52},
|
||||
{"GC", 9},
|
||||
{"GC_WHEEL", 18},
|
||||
{"GEN_3", 20},
|
||||
{"GEN_6", 21},
|
||||
{"GRAVIS_EX", 38},
|
||||
{"HAMMERHEAD", 40},
|
||||
{"HPD", 7},
|
||||
{"INTELI", 14},
|
||||
{"JAG", 11},
|
||||
{"MSSW", 39},
|
||||
{"N64", 19},
|
||||
{"NEO", 49},
|
||||
{"NES", 17},
|
||||
{"NES_ARKANOID", 30},
|
||||
{"NES_GUN", 28},
|
||||
{"NES_POWERPAD", 36},
|
||||
{"PADDLES", 41},
|
||||
{"PC_FX", 26},
|
||||
{"PC_GAMEPAD", 46},
|
||||
{"PSX_DIGITAL", 65},
|
||||
{"PSX_DS", 115},
|
||||
{"PSX_DS2", 121},
|
||||
{"PSX_FS", 83},
|
||||
{"PSX_JOGCON", 227}, /* 3.0 */
|
||||
{"PSX_NEGCON", 51},
|
||||
{"PSX_WHEEL", 12},
|
||||
{"SAC", 34},
|
||||
{"SATURN_ANALOG", 8},
|
||||
{"SATURN_DIGITAL", 3},
|
||||
{"SMS", 22},
|
||||
{"SNES", 27},
|
||||
{"SNESS_NTT", 47}, /* 3.0 */
|
||||
{"SPEEK", 45},
|
||||
{"TG16", 23},
|
||||
{"TG16_6BUTTON", 54}, /* 3.0 */
|
||||
{"THREE_DO", 25},
|
||||
{"THREE_DO_ANALOG", 37},
|
||||
{"VEC", 5},
|
||||
{"V_BOY", 29},
|
||||
{"WII_CLASSIC", 31},
|
||||
{"WII_DRUM", 55}, /* 3.0 */
|
||||
{"WII_MPLUS", 32},
|
||||
{"WII_NUNCHUK", 13},
|
||||
{"ZXSINC", 44},
|
||||
{"gx4000", 2},
|
||||
{NULL, 0}, /* used to mark unconnected ports, do not remove */
|
||||
};
|
||||
|
||||
|
||||
/* only one blissbox per machine is currently supported */
|
||||
static const blissbox_pad_type_t *blissbox_pads[BLISSBOX_MAX_PADS] = {NULL};
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
static struct libusb_device_handle *autoconfig_libusb_handle = NULL;
|
||||
#endif
|
||||
|
||||
#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
|
||||
HDEVINFO hDeviceInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
||||
HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;
|
||||
BOOL bResult = TRUE;
|
||||
BOOL success = FALSE;
|
||||
GUID guidDeviceInterface = {0};
|
||||
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)
|
||||
{
|
||||
/* Windows sometimes erroneously fails to open with a sharing violation:
|
||||
* https://github.com/signal11/hidapi/issues/231
|
||||
* If this happens, trying again with read + write usually works for some reason.
|
||||
*/
|
||||
|
||||
/* 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 for reading and writing: %d.", GetLastError());
|
||||
runloop_msg_queue_push("Bliss-Box already in use. Please make sure other programs are not using it.", 2, 300, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
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);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type_libusb(int vid, int pid)
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
unsigned i;
|
||||
unsigned char answer[USB_PACKET_CTRL_LEN] = {0};
|
||||
int ret = libusb_init(NULL);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not initialize libusb.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
autoconfig_libusb_handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
|
||||
|
||||
if (!autoconfig_libusb_handle)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not find or open libusb device %d:%d.\n", vid, pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_detach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
ret = libusb_set_configuration(autoconfig_libusb_handle, 1);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_set_configuration.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_claim_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_claim_interface.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_control_transfer(autoconfig_libusb_handle, USB_CTRL_IN, USB_HID_GET_REPORT, BLISSBOX_USB_FEATURE_REPORT_ID, 0, answer, USB_PACKET_CTRL_LEN, USB_TIMEOUT);
|
||||
|
||||
if (ret < 0)
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_control_transfer.\n");
|
||||
|
||||
libusb_release_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_attach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
|
||||
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 == answer[0])
|
||||
return pad;
|
||||
}
|
||||
|
||||
RARCH_LOG("[Autoconf]: Could not find connected pad in Bliss-Box port#%d.\n", pid - BLISSBOX_PID);
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#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
|
||||
}
|
||||
|
||||
void input_autoconfigure_override_handler(void *data)
|
||||
{
|
||||
autoconfig_params_t *params = (autoconfig_params_t*)data;
|
||||
|
||||
if (params->pid == BLISSBOX_UPDATE_MODE_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box in update mode detected. Ignoring.\n");
|
||||
else if (params->pid == BLISSBOX_OLD_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box 1.0 firmware detected. Please update to 2.0 or later.\n");
|
||||
else if (params->pid >= BLISSBOX_PID && params->pid <= BLISSBOX_PID + BLISSBOX_MAX_PAD_INDEX)
|
||||
{
|
||||
const blissbox_pad_type_t *pad;
|
||||
char name[255] = {0};
|
||||
int index = params->pid - BLISSBOX_PID;
|
||||
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box detected. Getting pad type...\n");
|
||||
|
||||
if (blissbox_pads[index])
|
||||
pad = blissbox_pads[index];
|
||||
else
|
||||
pad = input_autoconfigure_get_blissbox_pad_type(params->vid, params->pid);
|
||||
|
||||
if (pad && !string_is_empty(pad->name))
|
||||
{
|
||||
RARCH_LOG("[Autoconf]: Found Bliss-Box pad type: %s (%d) in port#%d\n", pad->name, pad->index, index);
|
||||
|
||||
if (params->name)
|
||||
free(params->name);
|
||||
|
||||
/* override name given to autoconfig so it knows what kind of pad this is */
|
||||
strlcat(name, "Bliss-Box 4-Play ", sizeof(name));
|
||||
strlcat(name, pad->name, sizeof(name));
|
||||
|
||||
params->name = strdup(name);
|
||||
|
||||
blissbox_pads[index] = pad;
|
||||
}
|
||||
/* use NULL entry to mark as an unconnected port */
|
||||
else
|
||||
blissbox_pads[index] = &blissbox_pad_types[ARRAY_SIZE(blissbox_pad_types) - 1];
|
||||
}
|
||||
}
|
@ -46,6 +46,19 @@ typedef struct nbio_buf
|
||||
char *path;
|
||||
} nbio_buf_t;
|
||||
|
||||
typedef struct autoconfig_params autoconfig_params_t;
|
||||
|
||||
struct autoconfig_params
|
||||
{
|
||||
int32_t vid;
|
||||
int32_t pid;
|
||||
unsigned idx;
|
||||
uint32_t max_users;
|
||||
char *name;
|
||||
char *autoconfig_directory;
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
typedef struct
|
||||
{
|
||||
@ -159,6 +172,8 @@ unsigned input_autoconfigure_get_device_name_index(unsigned i);
|
||||
|
||||
void input_autoconfigure_reset(void);
|
||||
|
||||
void input_autoconfigure_override_handler(void *data);
|
||||
|
||||
void input_autoconfigure_connect(
|
||||
const char *name,
|
||||
const char *display_name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user