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

@ -470,7 +470,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
// Only register controller with the native side once it has been fully configured // Only register controller with the native side once it has been fully configured
if (!isRegistered()) { if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId()); Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0); mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0);
setRegistered(); setRegistered();
} }
} }

View File

@ -241,17 +241,7 @@ public class HIDDeviceManager {
} }
} }
private boolean isHIDDeviceUSB(UsbDevice usbDevice) { private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) {
for (int interface_number = 0; interface_number < usbDevice.getInterfaceCount(); ++interface_number) {
if (isHIDDeviceInterface(usbDevice, interface_number)) {
return true;
}
}
return false;
}
private boolean isHIDDeviceInterface(UsbDevice usbDevice, int interface_number) {
UsbInterface usbInterface = usbDevice.getInterface(interface_number);
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) { if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
return true; return true;
} }
@ -331,10 +321,8 @@ public class HIDDeviceManager {
} }
private void handleUsbDeviceAttached(UsbDevice usbDevice) { private void handleUsbDeviceAttached(UsbDevice usbDevice) {
if (isHIDDeviceUSB(usbDevice)) {
connectHIDDeviceUSB(usbDevice); connectHIDDeviceUSB(usbDevice);
} }
}
private void handleUsbDeviceDetached(UsbDevice usbDevice) { private void handleUsbDeviceDetached(UsbDevice usbDevice) {
List<Integer> devices = new ArrayList<Integer>(); List<Integer> devices = new ArrayList<Integer>();
@ -366,11 +354,12 @@ public class HIDDeviceManager {
private void connectHIDDeviceUSB(UsbDevice usbDevice) { private void connectHIDDeviceUSB(UsbDevice usbDevice) {
synchronized (this) { synchronized (this) {
for (int interface_number = 0; interface_number < usbDevice.getInterfaceCount(); interface_number++) { for (int interface_number = 0; interface_number < usbDevice.getInterfaceCount(); interface_number++) {
if (isHIDDeviceInterface(usbDevice, interface_number)) { UsbInterface usbInterface = usbDevice.getInterface(interface_number);
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_number); if (isHIDDeviceInterface(usbDevice, usbInterface)) {
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, usbInterface.getId());
int id = device.getId(); int id = device.getId();
mDevicesById.put(id, device); mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), interface_number); HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol());
} }
} }
} }
@ -670,7 +659,7 @@ public class HIDDeviceManager {
private native void HIDDeviceRegisterCallback(); private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback(); private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number); native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
native void HIDDeviceOpenPending(int deviceID); native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened); native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID); native void HIDDeviceDisconnected(int deviceID);

View File

@ -419,6 +419,9 @@ LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
pDst->usage_page = pSrc->usage_page; pDst->usage_page = pSrc->usage_page;
pDst->usage = pSrc->usage; pDst->usage = pSrc->usage;
pDst->interface_number = pSrc->interface_number; pDst->interface_number = pSrc->interface_number;
pDst->interface_class = pSrc->interface_class;
pDst->interface_subclass = pSrc->interface_subclass;
pDst->interface_protocol = pSrc->interface_protocol;
pDst->next = NULL; pDst->next = NULL;
} }
#endif /* SDL_LIBUSB_DYNAMIC */ #endif /* SDL_LIBUSB_DYNAMIC */
@ -438,6 +441,9 @@ PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
pDst->usage_page = pSrc->usage_page; pDst->usage_page = pSrc->usage_page;
pDst->usage = pSrc->usage; pDst->usage = pSrc->usage;
pDst->interface_number = pSrc->interface_number; pDst->interface_number = pSrc->interface_number;
pDst->interface_class = pSrc->interface_class;
pDst->interface_subclass = pSrc->interface_subclass;
pDst->interface_protocol = pSrc->interface_protocol;
pDst->next = NULL; pDst->next = NULL;
} }
#endif /* HAVE_PLATFORM_BACKEND */ #endif /* HAVE_PLATFORM_BACKEND */

View File

@ -739,7 +739,7 @@ extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz); JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz);
extern "C" extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface ); JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol );
extern "C" extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID); JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
@ -828,7 +828,7 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallbac
} }
extern "C" extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface ) JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol )
{ {
LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface ); LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface );
@ -842,6 +842,9 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNI
pInfo->manufacturer_string = CreateWStringFromJString( env, sManufacturer ); pInfo->manufacturer_string = CreateWStringFromJString( env, sManufacturer );
pInfo->product_string = CreateWStringFromJString( env, sProduct ); pInfo->product_string = CreateWStringFromJString( env, sProduct );
pInfo->interface_number = nInterface; pInfo->interface_number = nInterface;
pInfo->interface_class = nInterfaceClass;
pInfo->interface_subclass = nInterfaceSubclass;
pInfo->interface_protocol = nInterfaceProtocol;
hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) ); hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );

View File

@ -78,6 +78,12 @@ namespace NAMESPACE {
only if the device contains more than one interface. */ only if the device contains more than one interface. */
int interface_number; int interface_number;
/** Additional information about the USB interface.
Valid on libusb and Android implementations. */
int interface_class;
int interface_subclass;
int interface_protocol;
/** Pointer to the next device */ /** Pointer to the next device */
struct hid_device_info *next; struct hid_device_info *next;
}; };

View File

@ -714,6 +714,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
/* Interface Number */ /* Interface Number */
cur_dev->interface_number = interface_num; cur_dev->interface_number = interface_num;
cur_dev->interface_class = intf_desc->bInterfaceClass;
cur_dev->interface_subclass = intf_desc->bInterfaceSubClass;
cur_dev->interface_protocol = intf_desc->bInterfaceProtocol;
} }
} }
} /* altsettings */ } /* altsettings */

View File

@ -481,6 +481,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
if (!dev) { if (!dev) {
continue; continue;
} }
dev_vid = get_vendor_id(dev); dev_vid = get_vendor_id(dev);
dev_pid = get_product_id(dev); dev_pid = get_product_id(dev);

View File

@ -1352,7 +1352,7 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
Uint16 vendor, product; Uint16 vendor, product;
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); 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 (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
if (SDL_IsJoystickXInput(guid)) { if (SDL_IsJoystickXInput(guid)) {
/* This is probably an Xbox One controller */ /* This is probably an Xbox One controller */
@ -1363,39 +1363,122 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
} }
SDL_GameControllerType 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) { if (vendor == 0x0000 && product == 0x0000) {
/* Some devices are only identifiable by their name */ /* Some devices are only identifiable by their name */
if (SDL_strcmp(name, "Lic Pro Controller") == 0 || if (SDL_strcmp(name, "Lic Pro Controller") == 0 ||
SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 || SDL_strcmp(name, "Nintendo Wireless Gamepad") == 0 ||
SDL_strcmp(name, "Wireless Gamepad") == 0) { SDL_strcmp(name, "Wireless Gamepad") == 0) {
/* HORI or PowerA Switch Pro Controller clone */ /* HORI or PowerA Switch Pro Controller clone */
return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
} } else {
return SDL_CONTROLLER_TYPE_UNKNOWN; type = SDL_CONTROLLER_TYPE_UNKNOWN;
}
if (vendor == 0x0001 && product == 0x0001) {
return SDL_CONTROLLER_TYPE_UNKNOWN;
} }
} else if (vendor == 0x0001 && product == 0x0001) {
type = SDL_CONTROLLER_TYPE_UNKNOWN;
} else {
switch (GuessControllerType(vendor, product)) { switch (GuessControllerType(vendor, product)) {
case k_eControllerType_XBox360Controller: case k_eControllerType_XBox360Controller:
return SDL_CONTROLLER_TYPE_XBOX360; type = SDL_CONTROLLER_TYPE_XBOX360;
break;
case k_eControllerType_XBoxOneController: case k_eControllerType_XBoxOneController:
return SDL_CONTROLLER_TYPE_XBOXONE; type = SDL_CONTROLLER_TYPE_XBOXONE;
break;
case k_eControllerType_PS3Controller: case k_eControllerType_PS3Controller:
return SDL_CONTROLLER_TYPE_PS3; type = SDL_CONTROLLER_TYPE_PS3;
break;
case k_eControllerType_PS4Controller: case k_eControllerType_PS4Controller:
return SDL_CONTROLLER_TYPE_PS4; type = SDL_CONTROLLER_TYPE_PS4;
break;
case k_eControllerType_SwitchProController: case k_eControllerType_SwitchProController:
case k_eControllerType_SwitchInputOnlyController: case k_eControllerType_SwitchInputOnlyController:
return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
break;
default: default:
return SDL_CONTROLLER_TYPE_UNKNOWN; type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
} }
} }
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 SDL_bool
SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product) SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor, Uint16 product)
{ {
@ -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; return SDL_TRUE;
} }

View File

@ -60,7 +60,7 @@ extern const char *SDL_GetCustomJoystickName(Uint16 vendor, Uint16 product);
/* Function to return the type of a controller */ /* Function to return the type of a controller */
extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name); extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name);
extern SDL_GameControllerType SDL_GetJoystickGameControllerType(Uint16 vendor, Uint16 product, const char *name); extern SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
/* Function to return whether a joystick is a Nintendo Switch Pro controller */ /* Function to return whether a joystick is a Nintendo Switch Pro controller */
extern SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id); extern SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id);

View File

@ -50,9 +50,9 @@ typedef struct {
} SDL_DriverGameCube_Context; } SDL_DriverGameCube_Context;
static SDL_bool static SDL_bool
HIDAPI_DriverGameCube_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverGameCube_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
if (vendor_id == 0x057e && product_id == 0x0337) { if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) {
/* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */ /* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
return SDL_TRUE; return SDL_TRUE;
} }

View File

@ -37,15 +37,6 @@
#ifdef SDL_JOYSTICK_HIDAPI_PS4 #ifdef SDL_JOYSTICK_HIDAPI_PS4
#define SONY_USB_VID 0x054C
#define SONY_DS4_PID 0x05C4
#define SONY_DS4_DONGLE_PID 0x0BA0
#define SONY_DS4_SLIM_PID 0x09CC
#define RAZER_USB_VID 0x1532
#define RAZER_PANTHERA_PID 0X0401
#define RAZER_PANTHERA_EVO_PID 0x1008
#define USB_PACKET_LENGTH 64 #define USB_PACKET_LENGTH 64
typedef enum typedef enum
@ -139,15 +130,15 @@ static Uint32 crc32(Uint32 crc, const void *data, int count)
} }
static SDL_bool static SDL_bool
HIDAPI_DriverPS4_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverPS4_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
return (SDL_GetJoystickGameControllerType(vendor_id, product_id, name) == SDL_CONTROLLER_TYPE_PS4); return (SDL_GetJoystickGameControllerType(name, vendor_id, product_id, interface_number, interface_class, interface_subclass, interface_protocol) == SDL_CONTROLLER_TYPE_PS4);
} }
static const char * static const char *
HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id) HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
{ {
if (vendor_id == SONY_USB_VID) { if (vendor_id == USB_VENDOR_SONY) {
return "PS4 Controller"; return "PS4 Controller";
} }
return NULL; return NULL;
@ -186,8 +177,8 @@ static SDL_bool CheckUSBConnected(hid_device *dev)
static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id) static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
{ {
/* The Razer Panthera fight stick hangs when trying to rumble */ /* The Razer Panthera fight stick hangs when trying to rumble */
if (vendor_id == RAZER_USB_VID && if (vendor_id == USB_VENDOR_RAZER &&
(product_id == RAZER_PANTHERA_PID || product_id == RAZER_PANTHERA_EVO_PID)) { (product_id == USB_PRODUCT_RAZER_PANTHERA || product_id == USB_PRODUCT_RAZER_PANTHERA_EVO)) {
return SDL_FALSE; return SDL_FALSE;
} }
return SDL_TRUE; return SDL_TRUE;
@ -232,10 +223,10 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
device->context = ctx; device->context = ctx;
/* Check for type of connection */ /* Check for type of connection */
ctx->is_dongle = (device->vendor_id == SONY_USB_VID && device->product_id == SONY_DS4_DONGLE_PID); ctx->is_dongle = (device->vendor_id == USB_VENDOR_SONY && device->product_id == USB_PRODUCT_SONY_DS4_DONGLE);
if (ctx->is_dongle) { if (ctx->is_dongle) {
ctx->is_bluetooth = SDL_FALSE; ctx->is_bluetooth = SDL_FALSE;
} else if (device->vendor_id == SONY_USB_VID) { } else if (device->vendor_id == USB_VENDOR_SONY) {
ctx->is_bluetooth = !CheckUSBConnected(device->dev); ctx->is_bluetooth = !CheckUSBConnected(device->dev);
} else { } else {
/* Third party controllers appear to all be wired */ /* Third party controllers appear to all be wired */
@ -246,8 +237,8 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
#endif #endif
/* Check to see if audio is supported */ /* Check to see if audio is supported */
if (device->vendor_id == SONY_USB_VID && if (device->vendor_id == USB_VENDOR_SONY &&
(device->product_id == SONY_DS4_SLIM_PID || device->product_id == SONY_DS4_DONGLE_PID )) { (device->product_id == USB_PRODUCT_SONY_DS4_SLIM || device->product_id == USB_PRODUCT_SONY_DS4_DONGLE)) {
ctx->audio_supported = SDL_TRUE; ctx->audio_supported = SDL_TRUE;
} }
@ -491,6 +482,12 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
static void static void
HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{ {
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
if (ctx->rumble_expiration) {
HIDAPI_DriverPS4_RumbleJoystick(device, joystick, 0, 0, 0);
}
hid_close(device->dev); hid_close(device->dev);
device->dev = NULL; device->dev = NULL;

View File

@ -241,9 +241,9 @@ static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id)
} }
static SDL_bool static SDL_bool
HIDAPI_DriverSwitch_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
return (SDL_GetJoystickGameControllerType(vendor_id, product_id, name) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO); return (SDL_GetJoystickGameControllerType(name, vendor_id, product_id, interface_number, interface_class, interface_subclass, interface_protocol) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO);
} }
static const char * static const char *
@ -1094,6 +1094,10 @@ HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
{ {
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
if (ctx->m_nRumbleExpiration) {
HIDAPI_DriverSwitch_RumbleJoystick(device, joystick, 0, 0, 0);
}
if (!ctx->m_bInputOnly) { if (!ctx->m_bInputOnly) {
/* Restore simple input mode for other applications */ /* Restore simple input mode for other applications */
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState); SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);

View File

@ -247,32 +247,30 @@ HIDAPI_DriverXbox360_QuitWindowsGamingInput(SDL_DriverXbox360_Context *ctx)
#endif /* SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT */ #endif /* SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT */
static SDL_bool static SDL_bool
HIDAPI_DriverXbox360_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(vendor_id, product_id, name); const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
const Uint16 MICROSOFT_USB_VID = 0x045e; SDL_GameControllerType type = SDL_GetJoystickGameControllerType(name, vendor_id, product_id, interface_number, interface_class, interface_subclass, interface_protocol);
const Uint16 NVIDIA_USB_VID = 0x0955;
if (vendor_id == NVIDIA_USB_VID) { if (vendor_id == USB_VENDOR_NVIDIA) {
/* This is the NVIDIA Shield controller which doesn't talk Xbox controller protocol */ /* This is the NVIDIA Shield controller which doesn't talk Xbox controller protocol */
return SDL_FALSE; return SDL_FALSE;
} }
if (vendor_id == MICROSOFT_USB_VID) { if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x0719)) ||
if (product_id == 0x0291 || product_id == 0x0719) { (type == SDL_CONTROLLER_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) {
/* This is the wireless dongle, which talks a different protocol */ /* This is the wireless dongle, which talks a different protocol */
return SDL_FALSE; return SDL_FALSE;
} }
}
if (interface_number > 0) { if (interface_number > 0) {
/* This is the chatpad or other input interface, not the Xbox 360 interface */ /* This is the chatpad or other input interface, not the Xbox 360 interface */
return SDL_FALSE; return SDL_FALSE;
} }
#if defined(__MACOSX__) || defined(__WIN32__) #if defined(__MACOSX__) || defined(__WIN32__)
if (vendor_id == 0x045e && product_id == 0x028e && version == 1) { if (vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x028e && version == 1) {
/* This is the Steam Virtual Gamepad, which isn't supported by this driver */ /* This is the Steam Virtual Gamepad, which isn't supported by this driver */
return SDL_FALSE; return SDL_FALSE;
} }
if (vendor_id == 0x045e && product_id == 0x02e0) { if (vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x02e0) {
/* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */ /* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */
return SDL_FALSE; return SDL_FALSE;
} }
@ -822,9 +820,11 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
static void static void
HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{ {
#if defined(SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT) || defined(SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT)
SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context; SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context;
#endif
if (ctx->rumble_expiration) {
HIDAPI_DriverXbox360_RumbleJoystick(device, joystick, 0, 0, 0);
}
#ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT #ifdef SDL_JOYSTICK_HIDAPI_WINDOWS_XINPUT
if (ctx->xinput_enabled) { if (ctx->xinput_enabled) {

View File

@ -45,12 +45,14 @@ typedef struct {
static SDL_bool static SDL_bool
HIDAPI_DriverXbox360W_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverXbox360W_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
const Uint16 MICROSOFT_USB_VID = 0x045e; const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(name, vendor_id, product_id, interface_number, interface_class, interface_subclass, interface_protocol);
if (vendor_id == MICROSOFT_USB_VID) { if ((vendor_id == USB_VENDOR_MICROSOFT && (product_id == 0x0291 || product_id == 0x0719)) ||
return (product_id == 0x0291 || product_id == 0x0719); (type == SDL_CONTROLLER_TYPE_XBOX360 && interface_protocol == XB360W_IFACE_PROTOCOL)) {
return SDL_TRUE;
} }
return SDL_FALSE; return SDL_FALSE;
} }
@ -290,6 +292,11 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
static void static void
HIDAPI_DriverXbox360W_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) HIDAPI_DriverXbox360W_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{ {
SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context;
if (ctx->rumble_expiration) {
HIDAPI_DriverXbox360W_RumbleJoystick(device, joystick, 0, 0, 0);
}
} }
static void static void

View File

@ -147,11 +147,6 @@ static SDL_bool
IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id) IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
{ {
/* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */ /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
const Uint16 USB_VENDOR_MICROSOFT = 0x045e;
const Uint16 USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH = 0x02e0;
const Uint16 USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH = 0x02fd;
const Uint16 USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH = 0x0b05;
if (vendor_id == USB_VENDOR_MICROSOFT) { if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH || if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH || product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
@ -165,9 +160,6 @@ IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
static SDL_bool static SDL_bool
ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id) ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
{ {
const Uint16 USB_VENDOR_MICROSOFT = 0x045e;
const Uint16 USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 = 0x0b00;
if (vendor_id == USB_VENDOR_MICROSOFT) { if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
return SDL_TRUE; return SDL_TRUE;
@ -180,8 +172,6 @@ ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
static SDL_bool static SDL_bool
ControllerNeedsRumbleSequenceSynchronized(Uint16 vendor_id, Uint16 product_id) ControllerNeedsRumbleSequenceSynchronized(Uint16 vendor_id, Uint16 product_id)
{ {
const Uint16 USB_VENDOR_MICROSOFT = 0x045e;
if (vendor_id == USB_VENDOR_MICROSOFT) { if (vendor_id == USB_VENDOR_MICROSOFT) {
/* All Xbox One controllers, from model 1537 through Elite Series 2, appear to need this */ /* All Xbox One controllers, from model 1537 through Elite Series 2, appear to need this */
return SDL_TRUE; return SDL_TRUE;
@ -221,9 +211,6 @@ SynchronizeRumbleSequence(hid_device *dev, SDL_DriverXboxOne_Context *ctx)
static SDL_bool static SDL_bool
ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id) ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
{ {
const Uint16 USB_VENDOR_HYPERKIN = 0x2e24;
const Uint16 USB_VENDOR_PDP = 0x0e6f;
if (vendor_id == USB_VENDOR_HYPERKIN) { if (vendor_id == USB_VENDOR_HYPERKIN) {
/* The Hyperkin controllers always send 0x02 when waiting for init, /* The Hyperkin controllers always send 0x02 when waiting for init,
and the Hyperkin Duke plays an Xbox startup animation, so we want and the Hyperkin Duke plays an Xbox startup animation, so we want
@ -310,19 +297,19 @@ SendControllerInit(hid_device *dev, SDL_DriverXboxOne_Context *ctx)
} }
static SDL_bool static SDL_bool
HIDAPI_DriverXboxOne_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name) HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{ {
#ifdef __LINUX__ #ifdef __LINUX__
if (IsBluetoothXboxOneController(vendor_id, product_id)) { if (IsBluetoothXboxOneController(vendor_id, product_id)) {
/* We can't do rumble on this device, hid_write() fails, so don't try to open it here */ /* We can't do rumble on this device, hid_write() fails, so don't try to open it here */
return SDL_FALSE; return SDL_FALSE;
} }
if (vendor_id == 0x24c6 && product_id == 0x541a) { if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
/* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */ /* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
return SDL_FALSE; return SDL_FALSE;
} }
#endif #endif
return (SDL_GetJoystickGameControllerType(vendor_id, product_id, name) == SDL_CONTROLLER_TYPE_XBOXONE); return (SDL_GetJoystickGameControllerType(name, vendor_id, product_id, interface_number, interface_class, interface_subclass, interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE);
} }
static const char * static const char *

View File

@ -389,7 +389,7 @@ HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, co
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) { for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i]; SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
if (driver->enabled && driver->IsSupportedDevice(vendor_id, product_id, version, -1, name)) { if (driver->enabled && driver->IsSupportedDevice(name, vendor_id, product_id, version, -1, 0, 0, 0)) {
return SDL_TRUE; return SDL_TRUE;
} }
} }
@ -418,7 +418,7 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) { for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i]; SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
if (driver->enabled && driver->IsSupportedDevice(device->vendor_id, device->product_id, device->version, device->interface_number, device->name)) { if (driver->enabled && driver->IsSupportedDevice(device->name, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
return driver; return driver;
} }
} }
@ -647,6 +647,9 @@ HIDAPI_AddDevice(struct hid_device_info *info)
device->product_id = info->product_id; device->product_id = info->product_id;
device->version = info->release_number; device->version = info->release_number;
device->interface_number = info->interface_number; device->interface_number = info->interface_number;
device->interface_class = info->interface_class;
device->interface_subclass = info->interface_subclass;
device->interface_protocol = info->interface_protocol;
device->usage_page = info->usage_page; device->usage_page = info->usage_page;
device->usage = info->usage; device->usage = info->usage;
{ {
@ -736,7 +739,7 @@ HIDAPI_AddDevice(struct hid_device_info *info)
HIDAPI_SetupDeviceDriver(device); HIDAPI_SetupDeviceDriver(device);
#ifdef DEBUG_HIDAPI #ifdef DEBUG_HIDAPI
SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, interface %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s\n", device->name, device->vendor_id, device->product_id, device->version, device->interface_number, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE"); SDL_Log("Added HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s\n", device->name, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->hint : "NONE");
#endif #endif
} }
@ -812,6 +815,7 @@ SDL_bool
HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
{ {
SDL_HIDAPI_Device *device; SDL_HIDAPI_Device *device;
SDL_bool supported = SDL_FALSE;
SDL_bool result = SDL_FALSE; SDL_bool result = SDL_FALSE;
/* Make sure we're initialized, as this could be called from other drivers during startup */ /* Make sure we're initialized, as this could be called from other drivers during startup */
@ -819,16 +823,25 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
return SDL_FALSE; return SDL_FALSE;
} }
/* Don't update the device list for devices we know aren't supported */ /* Only update the device list for devices we know might be supported.
if (!HIDAPI_IsDeviceSupported(vendor_id, product_id, version, name)) { If we did this for every device, it would hit the USB driver too hard and potentially
return SDL_FALSE; lock up the system. This won't catch devices that we support but can only detect using
USB interface details, like Xbox controllers, but hopefully the device list update is
responsive enough to catch those.
*/
supported = HIDAPI_IsDeviceSupported(vendor_id, product_id, version, name);
#if defined(SDL_JOYSTICK_HIDAPI_XBOX360) || defined(SDL_JOYSTICK_HIDAPI_XBOXONE)
if (!supported &&
(SDL_strstr(name, "Xbox") || SDL_strstr(name, "X-Box") || SDL_strstr(name, "XBOX"))) {
supported = SDL_TRUE;
} }
#endif /* SDL_JOYSTICK_HIDAPI_XBOX360 || SDL_JOYSTICK_HIDAPI_XBOXONE */
/* Make sure the device list is completely up to date when we check for device presence */ if (supported) {
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) { if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
HIDAPI_UpdateDeviceList(); HIDAPI_UpdateDeviceList();
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock); SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
} }
}
/* Note that this isn't a perfect check - there may be multiple devices with 0 VID/PID, /* Note that this isn't a perfect check - there may be multiple devices with 0 VID/PID,
or a different name than we have it listed here, etc, but if we support the device or a different name than we have it listed here, etc, but if we support the device
@ -845,8 +858,8 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
/* If we're looking for the wireless XBox 360 controller, also look for the dongle */ /* If we're looking for the wireless XBox 360 controller, also look for the dongle */
if (!result && vendor_id == 0x045e && product_id == 0x02a1) { if (!result && vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x02a1) {
return HIDAPI_IsDevicePresent(0x045e, 0x0719, version, name); return HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, 0x0719, version, name);
} }
#ifdef DEBUG_HIDAPI #ifdef DEBUG_HIDAPI

View File

@ -24,6 +24,7 @@
#define SDL_JOYSTICK_HIDAPI_H #define SDL_JOYSTICK_HIDAPI_H
#include "../../hidapi/hidapi/hidapi.h" #include "../../hidapi/hidapi/hidapi.h"
#include "../usb_ids.h"
/* This is the full set of HIDAPI drivers available */ /* This is the full set of HIDAPI drivers available */
#define SDL_JOYSTICK_HIDAPI_PS4 #define SDL_JOYSTICK_HIDAPI_PS4
@ -59,6 +60,9 @@ typedef struct _SDL_HIDAPI_Device
Uint16 version; Uint16 version;
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
int interface_number; /* Available on Windows and Linux */ int interface_number; /* Available on Windows and Linux */
int interface_class;
int interface_subclass;
int interface_protocol;
Uint16 usage_page; /* Available on Windows and Mac OS X */ Uint16 usage_page; /* Available on Windows and Mac OS X */
Uint16 usage; /* Available on Windows and Mac OS X */ Uint16 usage; /* Available on Windows and Mac OS X */
@ -78,7 +82,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
{ {
const char *hint; const char *hint;
SDL_bool enabled; SDL_bool enabled;
SDL_bool (*IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name); SDL_bool (*IsSupportedDevice)(const char *name, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id); const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device); SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id); int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id);

View File

@ -374,7 +374,7 @@ SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) { if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) {
Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1); Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1);
Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1); Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1);
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(vendor_id, product_id, ""); SDL_GameControllerType type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
if (type == SDL_CONTROLLER_TYPE_XBOX360 || if (type == SDL_CONTROLLER_TYPE_XBOX360 ||
type == SDL_CONTROLLER_TYPE_XBOXONE || type == SDL_CONTROLLER_TYPE_XBOXONE ||
(vendor_id == 0x28DE && product_id == 0x11FF)) { (vendor_id == 0x28DE && product_id == 0x11FF)) {