diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c index 5a3b22a47..d2c407c96 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 bf4c8ee7b..1c66ac2e7 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