Improved detection of third party PS4 and PS5 controllers

This commit is contained in:
Sam Lantinga 2022-09-22 23:42:25 -07:00
parent 7312b93d32
commit fa2063fb44
17 changed files with 132 additions and 51 deletions

View file

@ -568,7 +568,7 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
if ((vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) ||
(vendor == USB_VENDOR_SHENZHEN && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) {
(vendor == USB_VENDOR_DRAGONRISE && product == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER)) {
/* GameCube driver has 12 buttons and 6 axes */
SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,", sizeof(mapping_string));
} else if (vendor == USB_VENDOR_NINTENDO &&

View file

@ -2167,6 +2167,11 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam
if (SDL_IsJoystickVirtual(guid)) {
return SDL_CONTROLLER_TYPE_VIRTUAL;
}
#ifdef SDL_JOYSTICK_HIDAPI
if (SDL_IsJoystickHIDAPI(guid)) {
return HIDAPI_GetGameControllerTypeFromGUID(guid);
}
#endif /* SDL_JOYSTICK_HIDAPI */
}
return type;
}

View file

@ -82,7 +82,7 @@ HIDAPI_DriverGameCube_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *n
/* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
return SDL_TRUE;
}
if (vendor_id == USB_VENDOR_SHENZHEN && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) {
if (vendor_id == USB_VENDOR_DRAGONRISE && product_id == USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER) {
/* EVORETRO GameCube Controller Adapter */
return SDL_TRUE;
}
@ -145,8 +145,6 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_EnableGameCubeAdaptors();
#endif
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -219,6 +217,8 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller");
return SDL_TRUE;
}

View file

@ -77,8 +77,6 @@ HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverLuna_Context *ctx;
HIDAPI_SetDeviceName(device, "Amazon Luna Controller");
ctx = (SDL_DriverLuna_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -86,6 +84,9 @@ HIDAPI_DriverLuna_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
device->type = SDL_CONTROLLER_TYPE_AMAZON_LUNA;
HIDAPI_SetDeviceName(device, "Amazon Luna Controller");
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -133,13 +133,15 @@ static SDL_bool
HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverPS3_Context *ctx;
SDL_bool is_shanwan = SDL_FALSE;
if (device->vendor_id == USB_VENDOR_SONY) {
if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
HIDAPI_SetDeviceName(device, "ShanWan PS3 Controller");
} else {
HIDAPI_SetDeviceName(device, "PS3 Controller");
}
if (device->vendor_id == USB_VENDOR_SONY &&
SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
is_shanwan = SDL_TRUE;
}
if (device->vendor_id == USB_VENDOR_SHANWAN ||
device->vendor_id == USB_VENDOR_SHANWAN_ALT) {
is_shanwan = SDL_TRUE;
}
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
@ -148,13 +150,10 @@ HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
ctx->device = device;
ctx->is_shanwan = is_shanwan;
device->context = ctx;
if (SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
ctx->is_shanwan = SDL_TRUE;
}
/* Set the controller into report mode over Bluetooth */
{
Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
@ -189,6 +188,9 @@ HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
}
}
device->type = SDL_CONTROLLER_TYPE_PS3;
HIDAPI_SetDeviceName(device, "PS3 Controller");
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -168,12 +168,6 @@ HIDAPI_DriverPS4_IsEnabled(void)
SDL_HIDAPI_DEFAULT));
}
static SDL_bool
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;
}
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
@ -181,6 +175,21 @@ static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report
return SDL_hid_get_feature_report(dev, report, length);
}
static SDL_bool
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)
{
Uint8 data[USB_PACKET_LENGTH];
int size;
if (device && SONY_THIRDPARTY_VENDOR(device->vendor_id) &&
(size = ReadFeatureReport(device->dev, k_ePS4FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
data[2] == 0x27) {
/* Supported third party controller */
return SDL_TRUE;
}
return (type == SDL_CONTROLLER_TYPE_PS4) ? SDL_TRUE : SDL_FALSE;
}
static void
SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
{
@ -216,10 +225,6 @@ HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
int size;
char serial[18];
if (device->vendor_id == USB_VENDOR_SONY) {
HIDAPI_SetDeviceName(device, "PS4 Controller");
}
ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -309,6 +314,10 @@ HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
}
}
device->type = SDL_CONTROLLER_TYPE_PS4;
if (device->vendor_id == USB_VENDOR_SONY) {
HIDAPI_SetDeviceName(device, "PS4 Controller");
}
HIDAPI_SetDeviceSerial(device, serial);
return HIDAPI_JoystickConnected(device, NULL);

View file

@ -250,12 +250,6 @@ HIDAPI_DriverPS5_IsEnabled(void)
SDL_HIDAPI_DEFAULT));
}
static SDL_bool
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;
}
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
@ -263,6 +257,21 @@ static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report
return SDL_hid_get_feature_report(dev, report, length);
}
static SDL_bool
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)
{
Uint8 data[USB_PACKET_LENGTH];
int size;
if (device && SONY_THIRDPARTY_VENDOR(device->vendor_id) &&
(size = ReadFeatureReport(device->dev, k_EPS5FeatureReportIdCapabilities, data, sizeof(data))) == 48 &&
data[2] == 0x28) {
/* Supported third party controller */
return SDL_TRUE;
}
return (type == SDL_CONTROLLER_TYPE_PS5) ? SDL_TRUE : SDL_FALSE;
}
static void
SetLedsForPlayerIndex(DS5EffectsState_t *effects, int player_index)
{
@ -317,10 +326,6 @@ HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
int size;
char serial[18];
if (device->vendor_id == USB_VENDOR_SONY) {
HIDAPI_SetDeviceName(device, "PS5 Controller");
}
ctx = (SDL_DriverPS5_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -416,6 +421,10 @@ HIDAPI_DriverPS5_InitDevice(SDL_HIDAPI_Device *device)
ctx->use_alternate_report = SDL_TRUE;
}
device->type = SDL_CONTROLLER_TYPE_PS5;
if (device->vendor_id == USB_VENDOR_SONY) {
HIDAPI_SetDeviceName(device, "PS5 Controller");
}
HIDAPI_SetDeviceSerial(device, serial);
return HIDAPI_JoystickConnected(device, NULL);

View file

@ -112,8 +112,6 @@ HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverShield_Context *ctx;
HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller");
ctx = (SDL_DriverShield_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -121,6 +119,9 @@ HIDAPI_DriverShield_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
device->type = SDL_CONTROLLER_TYPE_NVIDIA_SHIELD;
HIDAPI_SetDeviceName(device, "NVIDIA SHIELD Controller");
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -78,8 +78,6 @@ HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverStadia_Context *ctx;
HIDAPI_SetDeviceName(device, "Google Stadia Controller");
ctx = (SDL_DriverStadia_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -87,6 +85,9 @@ HIDAPI_DriverStadia_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
device->type = SDL_CONTROLLER_TYPE_GOOGLE_STADIA;
HIDAPI_SetDeviceName(device, "Google Stadia Controller");
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -1027,8 +1027,6 @@ HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteam_Context *ctx;
HIDAPI_SetDeviceName(device, "Steam Controller");
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
SDL_OutOfMemory();
@ -1036,6 +1034,8 @@ HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
HIDAPI_SetDeviceName(device, "Steam Controller");
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -1161,32 +1161,40 @@ UpdateDeviceIdentity(SDL_HIDAPI_Device *device)
case k_eSwitchDeviceInfoControllerType_JoyConLeft:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (L)");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT);
device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
break;
case k_eSwitchDeviceInfoControllerType_JoyConRight:
HIDAPI_SetDeviceName(device, "Nintendo Switch Joy-Con (R)");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT);
device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
break;
case k_eSwitchDeviceInfoControllerType_ProController:
HIDAPI_SetDeviceName(device, "Nintendo Switch Pro Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SWITCH_PRO);
device->type = SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO;
break;
case k_eSwitchDeviceInfoControllerType_NESLeft:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (L)");
device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_NESRight:
HIDAPI_SetDeviceName(device, "Nintendo NES Controller (R)");
device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_SNES:
HIDAPI_SetDeviceName(device, "Nintendo SNES Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SNES_CONTROLLER);
device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_N64:
HIDAPI_SetDeviceName(device, "Nintendo N64 Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_N64_CONTROLLER);
device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
case k_eSwitchDeviceInfoControllerType_SEGA_Genesis:
HIDAPI_SetDeviceName(device, "Nintendo SEGA Genesis Controller");
HIDAPI_SetDeviceProduct(device, USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER);
device->type = SDL_CONTROLLER_TYPE_UNKNOWN;
break;
default:
break;

View file

@ -157,6 +157,8 @@ HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device)
device->context = ctx;
device->type = SDL_CONTROLLER_TYPE_XBOX360;
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -159,6 +159,8 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
device->type = SDL_CONTROLLER_TYPE_XBOX360;
return SDL_TRUE;
}

View file

@ -340,6 +340,8 @@ HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
SDL_Log("Controller version: %d (0x%.4x)\n", device->version, device->version);
#endif
device->type = SDL_CONTROLLER_TYPE_XBOXONE;
return HIDAPI_JoystickConnected(device, NULL);
}

View file

@ -235,7 +235,6 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
const Uint16 USAGE_GAMEPAD = 0x0005;
const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
int i;
SDL_GameControllerType type;
if (device->num_children > 0) {
return &SDL_HIDAPI_DriverCombined;
@ -254,10 +253,9 @@ 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, 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, device->type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
return driver;
}
}
@ -690,6 +688,7 @@ HIDAPI_AddDevice(const struct SDL_hid_device_info *info, int num_children, SDL_H
/* FIXME: Is there any way to tell whether this is a Bluetooth device? */
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, device->vendor_id, device->product_id, device->version, device->name, 'h', 0);
device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
if (num_children > 0) {
int i;
@ -914,14 +913,13 @@ HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Devi
/* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER &&
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
device->type == SDL_CONTROLLER_TYPE_XBOXONE) {
return SDL_TRUE;
}
/* If we're looking for an XInput controller, match it against any other Xbox controller */
if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
SDL_GameControllerType type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
if (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) {
if (device->type == SDL_CONTROLLER_TYPE_XBOX360 || device->type == SDL_CONTROLLER_TYPE_XBOXONE) {
return SDL_TRUE;
}
}
@ -947,8 +945,7 @@ HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
SDL_LockJoysticks();
for (device = SDL_HIDAPI_devices; device; device = device->next) {
if (device->driver &&
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
if (device->driver && device->type == type) {
result = SDL_TRUE;
break;
}
@ -1013,6 +1010,24 @@ HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, cons
return result;
}
SDL_GameControllerType
HIDAPI_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid)
{
SDL_HIDAPI_Device *device;
SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
SDL_LockJoysticks();
for (device = SDL_HIDAPI_devices; device; device = device->next) {
if (SDL_memcmp(&guid, &device->guid, sizeof(guid)) == 0) {
type = device->type;
break;
}
}
SDL_UnlockJoysticks();
return type;
}
static void
HIDAPI_JoystickDetect(void)
{

View file

@ -73,6 +73,7 @@ typedef struct _SDL_HIDAPI_Device
int interface_protocol;
Uint16 usage_page; /* Available on Windows and Mac OS X */
Uint16 usage; /* Available on Windows and Mac OS X */
SDL_GameControllerType type;
struct _SDL_HIDAPI_DeviceDriver *driver;
void *context;
@ -144,6 +145,9 @@ extern SDL_bool HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type);
/* Return true if a HID device is present and supported as a joystick */
extern SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
/* Return the type of a game controller if it's present and supported */
extern SDL_GameControllerType HIDAPI_GetGameControllerTypeFromGUID(SDL_JoystickGUID guid);
extern void HIDAPI_UpdateDevices(void);
extern void HIDAPI_SetDeviceName(SDL_HIDAPI_Device *device, const char *name);
extern void HIDAPI_SetDeviceProduct(SDL_HIDAPI_Device *device, Uint16 product_id);

View file

@ -27,21 +27,41 @@
#define USB_VENDOR_8BITDO 0x2dc8
#define USB_VENDOR_AMAZON 0x1949
#define USB_VENDOR_APPLE 0x05ac
#define USB_VENDOR_DRAGONRISE 0x0079
#define USB_VENDOR_GOOGLE 0x18d1
#define USB_VENDOR_HORI 0x0f0d
#define USB_VENDOR_HYPERKIN 0x2e24
#define USB_VENDOR_MADCATZ 0x0738
#define USB_VENDOR_MICROSOFT 0x045e
#define USB_VENDOR_NACON 0x146b
#define USB_VENDOR_NINTENDO 0x057e
#define USB_VENDOR_NVIDIA 0x0955
#define USB_VENDOR_PDP 0x0e6f
#define USB_VENDOR_POWERA 0x24c6
#define USB_VENDOR_POWERA_ALT 0x20d6
#define USB_VENDOR_QANBA 0x2c22
#define USB_VENDOR_RAZER 0x1532
#define USB_VENDOR_SHANWAN 0x2563
#define USB_VENDOR_SHENZHEN 0x0079
#define USB_VENDOR_SHANWAN_ALT 0x20bc
#define USB_VENDOR_SONY 0x054c
#define USB_VENDOR_THRUSTMASTER 0x044f
#define USB_VENDOR_VALVE 0x28de
#define SONY_THIRDPARTY_VENDOR(X) \
(X == USB_VENDOR_DRAGONRISE || \
X == USB_VENDOR_HORI || \
X == USB_VENDOR_MADCATZ || \
X == USB_VENDOR_NACON || \
X == USB_VENDOR_PDP || \
X == USB_VENDOR_POWERA || \
X == USB_VENDOR_POWERA_ALT || \
X == USB_VENDOR_QANBA || \
X == USB_VENDOR_RAZER || \
X == USB_VENDOR_SHANWAN || \
X == USB_VENDOR_SHANWAN_ALT || \
X == USB_VENDOR_THRUSTMASTER || \
X == 0x7545 /* SZ-MYPOWER */)
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER 0x2002
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400