Added support for the HORIPAD FPS for Nintendo Switch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c
index 5a3b22a..d2c407c 100644
--- a/src/hidapi/libusb/hid.c
+++ b/src/hidapi/libusb/hid.c
@@ -529,6 +529,22 @@ static struct usb_string_cache_entry *usb_string_cache_insert()
return new_entry;
}
+static int usb_string_can_cache(uint16_t vid, uint16_t pid)
+{
+ if (!vid || !pid) {
+ /* We can't cache these, they aren't unique */
+ return 0;
+ }
+
+ if (vid == 0x0f0d && pid == 0x00dc) {
+ /* HORI reuses this VID/PID for many different products */
+ return 0;
+ }
+
+ /* We can cache these strings */
+ return 1;
+}
+
static const struct usb_string_cache_entry *usb_string_cache_find(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle)
{
struct usb_string_cache_entry *entry = NULL;
@@ -684,6 +700,8 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de
static int should_enumerate_interface(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
{
+ //printf("Checking interface 0x%x %d/%d/%d/%d\n", vendor_id, intf_desc->bInterfaceNumber, intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol);
+
if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID)
return 1;
@@ -766,7 +784,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
get_usb_string(handle, desc.iSerialNumber);
/* Manufacturer and Product strings */
- if (dev_vid && dev_pid) {
+ if (usb_string_can_cache(dev_vid, dev_pid)) {
string_cache = usb_string_cache_find(&desc, handle);
if (string_cache) {
if (string_cache->vendor) {
@@ -1067,6 +1085,19 @@ static int SDLCALL read_thread(void *param)
return 0;
}
+static void init_xbox360(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, struct libusb_config_descriptor *conf_desc)
+{
+ if (idVendor == 0x0f0d && idProduct == 0x00dc) {
+ unsigned char data[20];
+
+ /* The HORIPAD FPS for Nintendo Switch requires this to enable input reports.
+ This VID/PID is also shared with other HORI controllers, but they all seem
+ to be fine with this as well.
+ */
+ libusb_control_transfer(device_handle, 0xC1, 0x01, 0x100, 0x0, data, sizeof(data), 100);
+ }
+}
+
static void init_xboxone(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, struct libusb_config_descriptor *conf_desc)
{
static const int VENDOR_MICROSOFT = 0x045e;
@@ -1186,6 +1217,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
break;
}
+ /* Initialize XBox 360 controllers */
+ if (is_xbox360(desc.idVendor, intf_desc)) {
+ init_xbox360(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
+ }
+
/* Initialize XBox One controllers */
if (is_xboxone(desc.idVendor, intf_desc)) {
init_xboxone(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
diff --git a/src/joystick/controller_type.c b/src/joystick/controller_type.c
index bf4c8ee..1c66ac2 100644
--- a/src/joystick/controller_type.c
+++ b/src/joystick/controller_type.c
@@ -546,6 +546,7 @@ static const ControllerDescription_t arrControllers[] = {
// - NSW-108, classic GameCube controller
// - NSW-244, Fighting Commander arcade pad
// - NSW-278, Hori Pad Mini gamepad
+ // - NSW-326, HORIPAD FPS for Nintendo Switch
//
// The first two, at least, shouldn't have their buttons remapped, and since we
// can't tell which model we're actually using, we won't do any button remapping