From e7f03de468792812a7aef668ac207ae35ede1945 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 7 Sep 2023 17:04:01 +0200 Subject: [PATCH] Add steam deck detection and HIDAPI driver scaffold. --- include/SDL_hints.h | 11 ++ src/joystick/SDL_joystick.c | 6 + src/joystick/SDL_joystick_c.h | 3 + src/joystick/controller_list.h | 1 + src/joystick/controller_type.h | 1 + src/joystick/hidapi/SDL_hidapi_steamdeck.c | 157 +++++++++++++++++++++ src/joystick/hidapi/SDL_hidapijoystick.c | 3 + src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 + 8 files changed, 184 insertions(+) create mode 100644 src/joystick/hidapi/SDL_hidapi_steamdeck.c diff --git a/include/SDL_hints.h b/include/SDL_hints.h index af0affc35..1e9b1c8fe 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -943,6 +943,17 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" +/** + * \brief A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" + /** * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index d32e38310..28b4999bc 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2736,6 +2736,12 @@ SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2; } +SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id) +{ + EControllerType eType = GuessControllerType(vendor_id, product_id); + return eType == k_eControllerType_SteamDeck; +} + SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) { return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE; diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 7aaea643d..5cc2a1ad1 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -125,6 +125,9 @@ extern SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 /* Function to return whether a joystick is a Steam Controller */ extern SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id); +/* Function to return whether a joystick is a Steam Deck */ +extern SDL_bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id); + /* Function to return whether a joystick guid comes from the XInput driver */ extern SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid); diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index 6dc503063..fd4dd3db6 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -595,4 +595,5 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller { MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB) { MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB) + { MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamDeck, NULL }, // Valve Steam Deck Builtin Controller }; diff --git a/src/joystick/controller_type.h b/src/joystick/controller_type.h index 9ec6c57ee..ead45f109 100644 --- a/src/joystick/controller_type.h +++ b/src/joystick/controller_type.h @@ -37,6 +37,7 @@ typedef enum k_eControllerType_UnknownSteamController = 1, k_eControllerType_SteamController = 2, k_eControllerType_SteamControllerV2 = 3, + k_eControllerType_SteamDeck = 4, // Other Controllers k_eControllerType_UnknownNonSteamController = 30, diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c new file mode 100644 index 000000000..93a38de8e --- /dev/null +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -0,0 +1,157 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2023 Max Maisel + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_JOYSTICK_HIDAPI + +#include "../SDL_sysjoystick.h" +#include "SDL_events.h" +#include "SDL_hidapijoystick_c.h" + +#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK + +/*****************************************************************************************************/ + +#include + +/*****************************************************************************************************/ + +static void HIDAPI_DriverSteamDeck_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); +} + +static void HIDAPI_DriverSteamDeck_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, callback, userdata); +} + +static SDL_bool HIDAPI_DriverSteamDeck_IsEnabled(void) +{ + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, + SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT)); +} + +static SDL_bool HIDAPI_DriverSteamDeck_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_IsJoystickSteamDeck(vendor_id, product_id); +} + +static SDL_bool HIDAPI_DriverSteamDeck_InitDevice(SDL_HIDAPI_Device *device) +{ + return SDL_FALSE; +} + +static int HIDAPI_DriverSteamDeck_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void HIDAPI_DriverSteamDeck_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + +static SDL_bool HIDAPI_DriverSteamDeck_UpdateDevice(SDL_HIDAPI_Device *device) +{ + return SDL_FALSE; +} + +static SDL_bool HIDAPI_DriverSteamDeck_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return SDL_FALSE; +} + +static int HIDAPI_DriverSteamDeck_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + /* You should use the full Steam Input API for rumble support */ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) +{ + return SDL_Unsupported(); +} + +static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return 0; +} + +static int HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) +{ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) +{ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverSteamDeck_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled) +{ + // On steam deck, sensors are enabled by default. Nothing to do here. + return 0; +} + +static void HIDAPI_DriverSteamDeck_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + // Lizard mode id automatically re-enabled by watchdog. Nothing to do here. +} + +static void HIDAPI_DriverSteamDeck_FreeDevice(SDL_HIDAPI_Device *device) +{ +} + +SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck = { + SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, + SDL_TRUE, + HIDAPI_DriverSteamDeck_RegisterHints, + HIDAPI_DriverSteamDeck_UnregisterHints, + HIDAPI_DriverSteamDeck_IsEnabled, + HIDAPI_DriverSteamDeck_IsSupportedDevice, + HIDAPI_DriverSteamDeck_InitDevice, + HIDAPI_DriverSteamDeck_GetDevicePlayerIndex, + HIDAPI_DriverSteamDeck_SetDevicePlayerIndex, + HIDAPI_DriverSteamDeck_UpdateDevice, + HIDAPI_DriverSteamDeck_OpenJoystick, + HIDAPI_DriverSteamDeck_RumbleJoystick, + HIDAPI_DriverSteamDeck_RumbleJoystickTriggers, + HIDAPI_DriverSteamDeck_GetJoystickCapabilities, + HIDAPI_DriverSteamDeck_SetJoystickLED, + HIDAPI_DriverSteamDeck_SendJoystickEffect, + HIDAPI_DriverSteamDeck_SetSensorsEnabled, + HIDAPI_DriverSteamDeck_CloseJoystick, + HIDAPI_DriverSteamDeck_FreeDevice, +}; + +#endif /* SDL_JOYSTICK_HIDAPI_STEAMDECK */ + +#endif /* SDL_JOYSTICK_HIDAPI */ diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 2fbce400b..f3d441778 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -71,6 +71,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = { #ifdef SDL_JOYSTICK_HIDAPI_STEAM &SDL_HIDAPI_DriverSteam, #endif +#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK + &SDL_HIDAPI_DriverSteamDeck, +#endif #ifdef SDL_JOYSTICK_HIDAPI_SWITCH &SDL_HIDAPI_DriverNintendoClassic, &SDL_HIDAPI_DriverJoyCons, diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index d17203f43..8073f46ec 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -39,6 +39,7 @@ #define SDL_JOYSTICK_HIDAPI_PS5 #define SDL_JOYSTICK_HIDAPI_STADIA #define SDL_JOYSTICK_HIDAPI_STEAM /* Simple support for BLE Steam Controller, hint is disabled by default */ +#define SDL_JOYSTICK_HIDAPI_STEAMDECK #define SDL_JOYSTICK_HIDAPI_SWITCH #define SDL_JOYSTICK_HIDAPI_WII #define SDL_JOYSTICK_HIDAPI_XBOX360 @@ -132,6 +133,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam; +extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamDeck; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;