Added support for the HORIPAD FPS for Nintendo Switch

This commit is contained in:
Sam Lantinga 2022-08-05 10:37:38 -07:00
parent a2d3be904b
commit d6a8b43cf7
2 changed files with 38 additions and 1 deletions

View file

@ -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);

View file

@ -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