diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index 8dae1a2f2..04710b45e 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -46,7 +46,7 @@ HIDAPI_DriverCombined_IsEnabled(void) } static SDL_bool -HIDAPI_DriverCombined_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverCombined_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { /* This is always explicitly created for combined devices */ return SDL_FALSE; diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 97321b853..bbd7a05cb 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -76,7 +76,7 @@ HIDAPI_DriverGameCube_IsEnabled(void) } static SDL_bool -HIDAPI_DriverGameCube_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) { /* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */ diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 3d285809e..7808052a8 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -67,7 +67,7 @@ HIDAPI_DriverLuna_IsEnabled(void) } static SDL_bool -HIDAPI_DriverLuna_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverLuna_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return (type == SDL_CONTROLLER_TYPE_AMAZON_LUNA) ? SDL_TRUE : SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index c52a87bb4..15ceb96fa 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -104,7 +104,7 @@ HIDAPI_DriverPS3_IsEnabled(void) } static SDL_bool -HIDAPI_DriverPS3_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverPS3_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) { return SDL_TRUE; diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index cdabd60bf..368567952 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -171,7 +171,7 @@ HIDAPI_DriverPS4_IsEnabled(void) } static SDL_bool -HIDAPI_DriverPS4_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverPS4_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index fa8a8ff0f..172d5e60a 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -273,7 +273,7 @@ HIDAPI_DriverPS5_IsEnabled(void) } static SDL_bool -HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverPS5_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 36bb79468..69ab1a4a0 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -102,7 +102,7 @@ HIDAPI_DriverShield_IsEnabled(void) } static SDL_bool -HIDAPI_DriverShield_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverShield_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return (type == SDL_CONTROLLER_TYPE_NVIDIA_SHIELD) ? SDL_TRUE : SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 435031b31..23056acff 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -68,7 +68,7 @@ HIDAPI_DriverStadia_IsEnabled(void) } static SDL_bool -HIDAPI_DriverStadia_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverStadia_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return (type == SDL_CONTROLLER_TYPE_GOOGLE_STADIA) ? SDL_TRUE : SDL_FALSE; } diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 27a541cc9..2faf65c36 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1017,7 +1017,7 @@ HIDAPI_DriverSteam_IsEnabled(void) } static SDL_bool -HIDAPI_DriverSteam_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverSteam_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { return SDL_IsJoystickSteamController(vendor_id, product_id); } diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 3b2c00366..60d5bf6b1 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -302,229 +302,6 @@ typedef struct { } SDL_DriverSwitch_Context; -static SDL_bool -HasHomeLED(SDL_DriverSwitch_Context *ctx) -{ - Uint16 vendor_id = ctx->device->vendor_id; - Uint16 product_id = ctx->device->product_id; - - /* The Power A Nintendo Switch Pro controllers don't have a Home LED */ - if (vendor_id == 0 && product_id == 0) { - return SDL_FALSE; - } - - /* HORI Wireless Switch Pad */ - if (vendor_id == 0x0f0d && product_id == 0x00f6) { - return SDL_FALSE; - } - - /* The Nintendo Online classic controllers don't have a Home LED */ - if (vendor_id == USB_VENDOR_NINTENDO && - ctx->m_eControllerType > k_eSwitchDeviceInfoControllerType_ProController) { - return SDL_FALSE; - } - - return SDL_TRUE; -} - -static SDL_bool -AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType) -{ - /* These controllers don't have a diamond button configuration, so always use labels */ - switch (eControllerType) { - case k_eSwitchDeviceInfoControllerType_NESLeft: - case k_eSwitchDeviceInfoControllerType_NESRight: - case k_eSwitchDeviceInfoControllerType_N64: - case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: - return SDL_TRUE; - default: - return SDL_FALSE; - } -} - -static SDL_bool -IsGameCubeFormFactor(int vendor_id, int product_id) -{ - static Uint32 gamecube_formfactor[] = { - MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ - MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */ - }; - Uint32 id = MAKE_VIDPID(vendor_id, product_id); - int i; - - for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) { - if (id == gamecube_formfactor[i]) { - return SDL_TRUE; - } - } - return SDL_FALSE; -} - -static void -HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata); -} - -static void -HIDAPI_DriverNintendoClassic_UnregisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata); -} - -static SDL_bool -HIDAPI_DriverNintendoClassic_IsEnabled(void) -{ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, - SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, - SDL_HIDAPI_DEFAULT)); -} - -static SDL_bool -HIDAPI_DriverNintendoClassic_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) -{ - if (vendor_id == USB_VENDOR_NINTENDO) { - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) { - if (SDL_strncmp(name, "NES Controller", 14) == 0) { - return SDL_TRUE; - } - } - - if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { - return SDL_TRUE; - } - - if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) { - return SDL_TRUE; - } - - if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) { - return SDL_TRUE; - } - } - - return SDL_FALSE; -} - -static void -HIDAPI_DriverJoyCons_RegisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata); -} - -static void -HIDAPI_DriverJoyCons_UnregisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata); -} - -static SDL_bool -HIDAPI_DriverJoyCons_IsEnabled(void) -{ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, - SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, - SDL_HIDAPI_DEFAULT)); -} - -static SDL_bool -HIDAPI_DriverJoyCons_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) -{ - if (vendor_id == USB_VENDOR_NINTENDO) { - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT || - product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT || - product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - return SDL_TRUE; - } - } - return SDL_FALSE; -} - -static void -HIDAPI_DriverSwitch_RegisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata); -} - -static void -HIDAPI_DriverSwitch_UnregisterHints(SDL_HintCallback callback, void *userdata) -{ - SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata); -} - -static SDL_bool -HIDAPI_DriverSwitch_IsEnabled(void) -{ - return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, - SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, - SDL_HIDAPI_DEFAULT)); -} - -static SDL_bool -HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) -{ - /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB - with the same VID/PID as when connected over Bluetooth but doesn't actually - support communication over USB. The most reliable way to block this without allowing the - controller to continually attempt to reconnect is to filter it out by manufactuer/product string. - Note that the controller does have a different product string when connected over Bluetooth. - */ - if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) { - return SDL_FALSE; - } - - /* If it's handled by another driver, it's not handled here */ - if (HIDAPI_DriverNintendoClassic_IsSupportedDevice(name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol) || - HIDAPI_DriverJoyCons_IsSupportedDevice(name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol)) { - return SDL_FALSE; - } - - return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE; -} - -static const char * -HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) -{ - /* Give a user friendly name for this controller */ - if (vendor_id == USB_VENDOR_NINTENDO) { - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { - /* We don't know if this is left or right, just leave it alone */ - return NULL; - } - - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) { - return "Nintendo Switch Joy-Con (L)"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) { - if (SDL_strncmp(name, "NES Controller", 14) == 0) { - if (SDL_strstr(name, "(L)") != 0) { - return "Nintendo NES Controller (L)"; - } else if (SDL_strstr(name, "(R)") != 0) { - return "Nintendo NES Controller (R)"; - } else { - /* Not sure what this is, just leave it alone */ - return NULL; - } - } - return "Nintendo Switch Joy-Con (R)"; - } - - if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { - return "Nintendo N64 Controller"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) { - return "Nintendo SEGA Genesis Controller"; - } - - if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) { - return "Nintendo SNES Controller"; - } - } - - return "Nintendo Switch Pro Controller"; -} - static int ReadInput(SDL_DriverSwitch_Context *ctx) { /* Make sure we don't try to read at the same time a write is happening */ @@ -1180,6 +957,238 @@ ReadJoyConControllerType(SDL_HIDAPI_Device *device) return eControllerType; } +static SDL_bool +HasHomeLED(SDL_DriverSwitch_Context *ctx) +{ + Uint16 vendor_id = ctx->device->vendor_id; + Uint16 product_id = ctx->device->product_id; + + /* The Power A Nintendo Switch Pro controllers don't have a Home LED */ + if (vendor_id == 0 && product_id == 0) { + return SDL_FALSE; + } + + /* HORI Wireless Switch Pad */ + if (vendor_id == 0x0f0d && product_id == 0x00f6) { + return SDL_FALSE; + } + + /* The Nintendo Online classic controllers don't have a Home LED */ + if (vendor_id == USB_VENDOR_NINTENDO && + ctx->m_eControllerType > k_eSwitchDeviceInfoControllerType_ProController) { + return SDL_FALSE; + } + + return SDL_TRUE; +} + +static SDL_bool +AlwaysUsesLabels(int vendor_id, int product_id, ESwitchDeviceInfoControllerType eControllerType) +{ + /* These controllers don't have a diamond button configuration, so always use labels */ + switch (eControllerType) { + case k_eSwitchDeviceInfoControllerType_NESLeft: + case k_eSwitchDeviceInfoControllerType_NESRight: + case k_eSwitchDeviceInfoControllerType_N64: + case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: + return SDL_TRUE; + default: + return SDL_FALSE; + } +} + +static SDL_bool +IsGameCubeFormFactor(int vendor_id, int product_id) +{ + static Uint32 gamecube_formfactor[] = { + MAKE_VIDPID(0x0e6f, 0x0185), /* PDP Wired Fight Pad Pro for Nintendo Switch */ + MAKE_VIDPID(0x20d6, 0xa711), /* Core (Plus) Wired Controller */ + }; + Uint32 id = MAKE_VIDPID(vendor_id, product_id); + int i; + + for (i = 0; i < SDL_arraysize(gamecube_formfactor); ++i) { + if (id == gamecube_formfactor[i]) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static void +HIDAPI_DriverNintendoClassic_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata); +} + +static void +HIDAPI_DriverNintendoClassic_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, callback, userdata); +} + +static SDL_bool +HIDAPI_DriverNintendoClassic_IsEnabled(void) +{ + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, + SDL_HIDAPI_DEFAULT)); +} + +static SDL_bool +HIDAPI_DriverNintendoClassic_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +{ + if (vendor_id == USB_VENDOR_NINTENDO) { + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) { + if (SDL_strncmp(name, "NES Controller", 14) == 0) { + return SDL_TRUE; + } + } + + if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { + return SDL_TRUE; + } + + if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) { + return SDL_TRUE; + } + + if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) { + return SDL_TRUE; + } + } + + return SDL_FALSE; +} + +static void +HIDAPI_DriverJoyCons_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata); +} + +static void +HIDAPI_DriverJoyCons_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, callback, userdata); +} + +static SDL_bool +HIDAPI_DriverJoyCons_IsEnabled(void) +{ + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, + SDL_HIDAPI_DEFAULT)); +} + +static SDL_bool +HIDAPI_DriverJoyCons_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +{ + if (vendor_id == USB_VENDOR_NINTENDO) { + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_PRO && device) { + /* This might be a Kinvoca Joy-Con that reports VID/PID as a Switch Pro controller */ + ESwitchDeviceInfoControllerType eControllerType = ReadJoyConControllerType(device); + if (eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft || + eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { + return SDL_TRUE; + } + } + + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT || + product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT || + product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static void +HIDAPI_DriverSwitch_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata); +} + +static void +HIDAPI_DriverSwitch_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, callback, userdata); +} + +static SDL_bool +HIDAPI_DriverSwitch_IsEnabled(void) +{ + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, + SDL_HIDAPI_DEFAULT)); +} + +static SDL_bool +HIDAPI_DriverSwitch_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +{ + /* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB + with the same VID/PID as when connected over Bluetooth but doesn't actually + support communication over USB. The most reliable way to block this without allowing the + controller to continually attempt to reconnect is to filter it out by manufactuer/product string. + Note that the controller does have a different product string when connected over Bluetooth. + */ + if (SDL_strcmp(name, "HORI Wireless Switch Pad") == 0) { + return SDL_FALSE; + } + + /* If it's handled by another driver, it's not handled here */ + if (HIDAPI_DriverNintendoClassic_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol) || + HIDAPI_DriverJoyCons_IsSupportedDevice(device, name, type, vendor_id, product_id, version, interface_number, interface_class, interface_subclass, interface_protocol)) { + return SDL_FALSE; + } + + return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) ? SDL_TRUE : SDL_FALSE; +} + +static const char * +HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id) +{ + /* Give a user friendly name for this controller */ + if (vendor_id == USB_VENDOR_NINTENDO) { + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) { + /* We don't know if this is left or right, just leave it alone */ + return NULL; + } + + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) { + return "Nintendo Switch Joy-Con (L)"; + } + + if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) { + if (SDL_strncmp(name, "NES Controller", 14) == 0) { + if (SDL_strstr(name, "(L)") != 0) { + return "Nintendo NES Controller (L)"; + } else if (SDL_strstr(name, "(R)") != 0) { + return "Nintendo NES Controller (R)"; + } else { + /* Not sure what this is, just leave it alone */ + return NULL; + } + } + return "Nintendo Switch Joy-Con (R)"; + } + + if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) { + return "Nintendo N64 Controller"; + } + + if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) { + return "Nintendo SEGA Genesis Controller"; + } + + if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) { + return "Nintendo SNES Controller"; + } + } + + return "Nintendo Switch Pro Controller"; +} + static void UpdateDeviceIdentity(SDL_HIDAPI_Device *device) { diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index a3a968ba9..5254a16ad 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -69,7 +69,7 @@ HIDAPI_DriverXbox360_IsEnabled(void) } static SDL_bool -HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */ diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 2d0ad026e..c3fd3a010 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -75,7 +75,7 @@ HIDAPI_DriverXbox360W_IsEnabled(void) } static SDL_bool -HIDAPI_DriverXbox360W_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverXbox360W_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */ diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 94f04b6e0..17a30a072 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -289,7 +289,7 @@ HIDAPI_DriverXboxOne_IsEnabled(void) } static SDL_bool -HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +HIDAPI_DriverXboxOne_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { #ifdef __LINUX__ if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) { diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index ebe666d32..014d64c30 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -217,7 +217,7 @@ HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, co for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) { SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i]; - if (driver->enabled && driver->IsSupportedDevice(name, type, vendor_id, product_id, version, -1, 0, 0, 0)) { + if (driver->enabled && driver->IsSupportedDevice(NULL, name, type, vendor_id, product_id, version, -1, 0, 0, 0)) { return SDL_TRUE; } } @@ -254,7 +254,7 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device) type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol); for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) { SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i]; - if (driver->enabled && driver->IsSupportedDevice(device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) { + if (driver->enabled && driver->IsSupportedDevice(device, device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) { return driver; } } diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index fbf21acd2..b5d23e26f 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -101,7 +101,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver void (*RegisterHints)(SDL_HintCallback callback, void *userdata); void (*UnregisterHints)(SDL_HintCallback callback, void *userdata); SDL_bool (*IsEnabled)(void); - SDL_bool (*IsSupportedDevice)(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol); + SDL_bool (*IsSupportedDevice)(SDL_HIDAPI_Device *device, const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol); const char *(*GetDeviceName)(const char *name, Uint16 vendor_id, Uint16 product_id); SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device); int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id);