From 8657fa8b3b79f6f9a516ff4763dd235e03cd8d44 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 15 Nov 2024 15:55:13 -0800 Subject: [PATCH] Improved reliability of the Steam Controller driver --- src/joystick/hidapi/SDL_hidapi_steam.c | 72 +++++++++++++------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 336bc2ff7d..68fb01017b 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -28,6 +28,9 @@ #ifdef SDL_JOYSTICK_HIDAPI_STEAM +// Define this if you want to log all packets from the controller +// #define DEBUG_STEAM_PROTOCOL + #define SDL_HINT_JOYSTICK_HIDAPI_STEAM_PAIRING_ENABLED "SDL_JOYSTICK_HIDAPI_STEAM_PAIRING_ENABLED" #if defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) @@ -210,11 +213,7 @@ static uint8_t GetSegmentHeader(int nSegmentNumber, bool bLastPacket) static void hexdump(const uint8_t *ptr, int len) { - int i; - for (i = 0; i < len; ++i) { - printf("%02x ", ptr[i]); - } - printf("\n"); + HIDAPI_DumpPacket("Data", ptr, len); } static void ResetSteamControllerPacketAssembler(SteamControllerPacketAssembler *pAssembler) @@ -418,22 +417,25 @@ static int GetFeatureReport(SDL_HIDAPI_Device *dev, unsigned char uBuffer[65]) static int ReadResponse(SDL_HIDAPI_Device *dev, uint8_t uBuffer[65], int nExpectedResponse) { - int nRet = GetFeatureReport(dev, uBuffer); + for (int nRetries = 0; nRetries < 10; nRetries++) { + int nRet = GetFeatureReport(dev, uBuffer); - DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse); + DPRINTF("ReadResponse( %p %p 0x%x )\n", dev, uBuffer, nExpectedResponse); + + if (nRet < 0) { + continue; + } + + DPRINTF("ReadResponse got %d bytes of data: ", nRet); + HEXDUMP(uBuffer, nRet); + + if (uBuffer[1] != nExpectedResponse) { + continue; + } - if (nRet < 0) { return nRet; } - - DPRINTF("ReadResponse got %d bytes of data: ", nRet); - HEXDUMP(uBuffer, nRet); - - if (uBuffer[1] != nExpectedResponse) { - return -1; - } - - return nRet; + return -1; } //--------------------------------------------------------------------------- @@ -1223,15 +1225,23 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) const Uint8 *pPacket; r = ReadSteamController(device->dev, data, sizeof(data)); - if (r == 0) { + if (r <= 0) { + if (r < 0) { + // Failed to read from controller + if (ctx->connected) { + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + ctx->connected = false; + } + return false; + } break; } - nPacketLength = 0; - if (r > 0) { - nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&ctx->m_assembler, data, r); - } +#ifdef DEBUG_STEAM_PROTOCOL + HIDAPI_DumpPacket("Steam Controller packet: size = %d", data, r); +#endif + nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&ctx->m_assembler, data, r); pPacket = ctx->m_assembler.uBuffer; if (nPacketLength > 0 && UpdateSteamControllerState(pPacket, nPacketLength, &ctx->m_state)) { @@ -1321,11 +1331,6 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) } ctx->m_last_state = ctx->m_state; - } else if (ctx->connected && D0G_IS_WIRELESS_DISCONNECT(pPacket, nPacketLength)) { - // Controller has disconnected from the wireless dongle - HIDAPI_JoystickDisconnected(device, device->joysticks[0]); - joystick = NULL; - ctx->connected = false; } else if (!ctx->connected && D0G_IS_WIRELESS_CONNECT(pPacket, nPacketLength)) { // Controller has connected to the wireless dongle if (!HIDAPI_JoystickConnected(device, NULL)) { @@ -1337,14 +1342,11 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) joystick = SDL_GetJoystickFromID(device->joysticks[0]); ctx->connected = true; - } - - if (r <= 0) { - // Failed to read from controller - if (ctx->connected) { - HIDAPI_JoystickDisconnected(device, device->joysticks[0]); - } - return false; + } else if (ctx->connected && D0G_IS_WIRELESS_DISCONNECT(pPacket, nPacketLength)) { + // Controller has disconnected from the wireless dongle + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + joystick = NULL; + ctx->connected = false; } } return true;