mirror of https://github.com/encounter/SDL.git
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:
parent
27035425e0
commit
43aa1fa9e7
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,9 +321,7 @@ 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) {
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 ) );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -41,10 +41,10 @@
|
||||||
StackOverflow. It is used with his permission. */
|
StackOverflow. It is used with his permission. */
|
||||||
typedef int pthread_barrierattr_t;
|
typedef int pthread_barrierattr_t;
|
||||||
typedef struct pthread_barrier {
|
typedef struct pthread_barrier {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
int count;
|
int count;
|
||||||
int trip_count;
|
int trip_count;
|
||||||
} pthread_barrier_t;
|
} pthread_barrier_t;
|
||||||
|
|
||||||
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
|
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
|
||||||
|
@ -178,22 +178,22 @@ static void free_hid_device(hid_device *dev)
|
||||||
free(dev->input_report_buf);
|
free(dev->input_report_buf);
|
||||||
|
|
||||||
if (device_list) {
|
if (device_list) {
|
||||||
if (device_list->dev == dev) {
|
if (device_list->dev == dev) {
|
||||||
device_list = device_list->next;
|
device_list = device_list->next;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct hid_device_list_node *node = device_list;
|
struct hid_device_list_node *node = device_list;
|
||||||
while (node) {
|
while (node) {
|
||||||
if (node->next && node->next->dev == dev) {
|
if (node->next && node->next->dev == dev) {
|
||||||
struct hid_device_list_node *new_next = node->next->next;
|
struct hid_device_list_node *new_next = node->next->next;
|
||||||
free(node->next);
|
free(node->next);
|
||||||
node->next = new_next;
|
node->next = new_next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the thread objects */
|
/* Clean up the thread objects */
|
||||||
|
@ -478,9 +478,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||||
|
|
||||||
IOHIDDeviceRef dev = device_array[i];
|
IOHIDDeviceRef dev = device_array[i];
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -751,17 +751,17 @@ SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
|
||||||
int
|
int
|
||||||
SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
SDL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LockJoysticks();
|
SDL_LockJoysticks();
|
||||||
result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms);
|
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;
|
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,37 +1363,120 @@ 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 {
|
||||||
|
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)) {
|
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
|
||||||
case k_eControllerType_XBox360Controller:
|
/* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
|
||||||
return SDL_CONTROLLER_TYPE_XBOX360;
|
static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
|
||||||
case k_eControllerType_XBoxOneController:
|
static const int XB360_IFACE_SUBCLASS = 93;
|
||||||
return SDL_CONTROLLER_TYPE_XBOXONE;
|
static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
|
||||||
case k_eControllerType_PS3Controller:
|
static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
|
||||||
return SDL_CONTROLLER_TYPE_PS3;
|
static const int XBONE_IFACE_SUBCLASS = 71;
|
||||||
case k_eControllerType_PS4Controller:
|
static const int XBONE_IFACE_PROTOCOL = 208;
|
||||||
return SDL_CONTROLLER_TYPE_PS4;
|
|
||||||
case k_eControllerType_SwitchProController:
|
if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||||
case k_eControllerType_SwitchInputOnlyController:
|
interface_subclass == XB360_IFACE_SUBCLASS &&
|
||||||
return SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
|
(interface_protocol == XB360_IFACE_PROTOCOL ||
|
||||||
default:
|
interface_protocol == XB360W_IFACE_PROTOCOL)) {
|
||||||
return SDL_CONTROLLER_TYPE_UNKNOWN;
|
|
||||||
|
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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
|
@ -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,15 +823,24 @@ 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,
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
Loading…
Reference in New Issue