Added support for detecting previously unknown Xbox 360 and Xbox One controllers using the HIDAPI driver with libusb and Android

This commit is contained in:
Sam Lantinga 2020-01-18 11:21:14 -08:00
parent 27035425e0
commit 43aa1fa9e7
18 changed files with 244 additions and 141 deletions

View file

@ -751,17 +751,17 @@ SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
int
SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
{
int result;
int result;
if (!SDL_PrivateJoystickValid(joystick)) {
return -1;
}
SDL_LockJoysticks();
SDL_LockJoysticks();
result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
SDL_UnlockJoysticks();
SDL_UnlockJoysticks();
return result;
return result;
}
/*
@ -1352,7 +1352,7 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
Uint16 vendor, product;
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL);
type = SDL_GetJoystickGameControllerType(vendor, product, name);
type = SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0);
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
if (SDL_IsJoystickXInput(guid)) {
/* This is probably an Xbox One controller */
@ -1363,37 +1363,120 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
}
SDL_GameControllerType
SDL_GetJoystickGameControllerType(Uint16 vendor, Uint16 product, const char *name)
SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
if (vendor == 0x0000 && product == 0x0000) {
/* Some devices are only identifiable by their name */
if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
SDL_strcmp(name, "Wireless Gamepad") == 0) {
/* HORI or PowerA Switch Pro Controller clone */
return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
} else {
type = SDL_CONTROLLER_TYPE_UNKNOWN;
}
} else if (vendor == 0x0001 && product == 0x0001) {
type = SDL_CONTROLLER_TYPE_UNKNOWN;
} else {
switch (GuessControllerType(vendor, product)) {
case k_eControllerType_XBox360Controller:
type = SDL_CONTROLLER_TYPE_XBOX360;
break;
case k_eControllerType_XBoxOneController:
type = SDL_CONTROLLER_TYPE_XBOXONE;
break;
case k_eControllerType_PS3Controller:
type = SDL_CONTROLLER_TYPE_PS3;
break;
case k_eControllerType_PS4Controller:
type = SDL_CONTROLLER_TYPE_PS4;
break;
case k_eControllerType_SwitchProController:
case k_eControllerType_SwitchInputOnlyController:
type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
break;
default:
type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
}
return SDL_CONTROLLER_TYPE_UNKNOWN;
}
if (vendor == 0x0001 && product == 0x0001) {
return SDL_CONTROLLER_TYPE_UNKNOWN;
}
switch (GuessControllerType(vendor, product)) {
case k_eControllerType_XBox360Controller:
return SDL_CONTROLLER_TYPE_XBOX360;
case k_eControllerType_XBoxOneController:
return SDL_CONTROLLER_TYPE_XBOXONE;
case k_eControllerType_PS3Controller:
return SDL_CONTROLLER_TYPE_PS3;
case k_eControllerType_PS4Controller:
return SDL_CONTROLLER_TYPE_PS4;
case k_eControllerType_SwitchProController:
case k_eControllerType_SwitchInputOnlyController:
return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
default:
return SDL_CONTROLLER_TYPE_UNKNOWN;
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
/* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
static const int XB360_IFACE_SUBCLASS = 93;
static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
static const int XBONE_IFACE_SUBCLASS = 71;
static const int XBONE_IFACE_PROTOCOL = 208;
if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
interface_subclass == XB360_IFACE_SUBCLASS &&
(interface_protocol == XB360_IFACE_PROTOCOL ||
interface_protocol == XB360W_IFACE_PROTOCOL)) {
static const int SUPPORTED_VENDORS[] = {
0x0079, /* GPD Win 2 */
0x044f, /* Thrustmaster */
0x045e, /* Microsoft */
0x046d, /* Logitech */
0x056e, /* Elecom */
0x06a3, /* Saitek */
0x0738, /* Mad Catz */
0x07ff, /* Mad Catz */
0x0e6f, /* PDP */
0x0f0d, /* Hori */
0x1038, /* SteelSeries */
0x11c9, /* Nacon */
0x12ab, /* Unknown */
0x1430, /* RedOctane */
0x146b, /* BigBen */
0x1532, /* Razer Sabertooth */
0x15e4, /* Numark */
0x162e, /* Joytech */
0x1689, /* Razer Onza */
0x1bad, /* Harmonix */
0x24c6, /* PowerA */
};
int i;
for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
if (vendor == SUPPORTED_VENDORS[i]) {
type = SDL_CONTROLLER_TYPE_XBOX360;
break;
}
}
}
if (interface_number == 0 &&
interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
interface_subclass == XBONE_IFACE_SUBCLASS &&
interface_protocol == XBONE_IFACE_PROTOCOL) {
static const int SUPPORTED_VENDORS[] = {
0x045e, /* Microsoft */
0x0738, /* Mad Catz */
0x0e6f, /* PDP */
0x0f0d, /* Hori */
0x1532, /* Razer Wildcat */
0x24c6, /* PowerA */
0x2e24, /* Hyperkin */
};
int i;
for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
if (vendor == SUPPORTED_VENDORS[i]) {
type = SDL_CONTROLLER_TYPE_XBOXONE;
break;
}
}
}
}
return type;
}
SDL_bool
@ -1686,7 +1769,7 @@ SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
}
}
if (SDL_GetJoystickGameControllerType(vendor, product, name) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) {
if (SDL_GetJoystickGameControllerType(name, vendor, product, -1, 0, 0, 0) == SDL_CONTROLLER_TYPE_PS4 && SDL_IsPS4RemapperRunning()) {
return SDL_TRUE;
}