21 #include "../../SDL_internal.h"
23 #ifdef SDL_JOYSTICK_HIDAPI
31 #include "../SDL_sysjoystick.h"
36 #ifdef SDL_JOYSTICK_HIDAPI_STEAM
51 #include "steam/controller_constants.h"
52 #include "steam/controller_structs.h"
54 typedef struct SteamControllerStateInternal_t
57 uint32 eControllerType;
86 unsigned short sTriggerL;
87 unsigned short sTriggerR;
102 short sGyroSteeringAngle;
104 unsigned short sBatteryLevel;
107 unsigned short sPressurePadLeft;
108 unsigned short sPressurePadRight;
110 unsigned short sPressureBumperLeft;
111 unsigned short sPressureBumperRight;
114 short sPrevLeftPad[2];
115 short sPrevLeftStick[2];
116 } SteamControllerStateInternal_t;
120 #define STEAM_RIGHT_TRIGGER_MASK 0x00000001
121 #define STEAM_LEFT_TRIGGER_MASK 0x00000002
122 #define STEAM_RIGHT_BUMPER_MASK 0x00000004
123 #define STEAM_LEFT_BUMPER_MASK 0x00000008
124 #define STEAM_BUTTON_0_MASK 0x00000010
125 #define STEAM_BUTTON_1_MASK 0x00000020
126 #define STEAM_BUTTON_2_MASK 0x00000040
127 #define STEAM_BUTTON_3_MASK 0x00000080
128 #define STEAM_TOUCH_0_MASK 0x00000100
129 #define STEAM_TOUCH_1_MASK 0x00000200
130 #define STEAM_TOUCH_2_MASK 0x00000400
131 #define STEAM_TOUCH_3_MASK 0x00000800
132 #define STEAM_BUTTON_MENU_MASK 0x00001000
133 #define STEAM_BUTTON_STEAM_MASK 0x00002000
134 #define STEAM_BUTTON_ESCAPE_MASK 0x00004000
135 #define STEAM_BUTTON_BACK_LEFT_MASK 0x00008000
136 #define STEAM_BUTTON_BACK_RIGHT_MASK 0x00010000
137 #define STEAM_BUTTON_LEFTPAD_CLICKED_MASK 0x00020000
138 #define STEAM_BUTTON_RIGHTPAD_CLICKED_MASK 0x00040000
139 #define STEAM_LEFTPAD_FINGERDOWN_MASK 0x00080000
140 #define STEAM_RIGHTPAD_FINGERDOWN_MASK 0x00100000
141 #define STEAM_JOYSTICK_BUTTON_MASK 0x00400000
142 #define STEAM_LEFTPAD_AND_JOYSTICK_MASK 0x00800000
146 #define D0G_IS_VALID_WIRELESS_EVENT(data, len) ((len) >= 5 && (data)[0] == 1 && (data)[1] == 0 && (data)[2] == 3 && (data)[3] >= 1)
147 #define D0G_GET_WIRELESS_EVENT_TYPE(data) ((data)[4])
148 #define D0G_WIRELESS_DISCONNECTED 1
149 #define D0G_WIRELESS_ESTABLISHED 2
150 #define D0G_WIRELESS_NEWLYPAIRED 3
152 #define D0G_IS_WIRELESS_DISCONNECT(data, len) ( D0G_IS_VALID_WIRELESS_EVENT(data,len) && D0G_GET_WIRELESS_EVENT_TYPE(data) == D0G_WIRELESS_DISCONNECTED )
154 #define MAX_REPORT_SEGMENT_PAYLOAD_SIZE 18
160 uint8_t uBuffer[ MAX_REPORT_SEGMENT_PAYLOAD_SIZE * 8 + 1 ];
161 int nExpectedSegmentNumber;
163 } SteamControllerPacketAssembler;
167 #define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
170 #define offsetof(s,m) (size_t)&(((s *)0)->m)
172 #ifdef DEBUG_STEAM_CONTROLLER
173 #define DPRINTF(format, ...) printf(format, ##__VA_ARGS__)
174 #define HEXDUMP(ptr, len) hexdump(ptr, len)
176 #define DPRINTF(format, ...)
177 #define HEXDUMP(ptr, len)
179 #define printf SDL_Log
181 #define MAX_REPORT_SEGMENT_SIZE ( MAX_REPORT_SEGMENT_PAYLOAD_SIZE + 2 )
182 #define CALC_REPORT_SEGMENT_NUM(index) ( ( index / MAX_REPORT_SEGMENT_PAYLOAD_SIZE ) & 0x07 )
183 #define REPORT_SEGMENT_DATA_FLAG 0x80
184 #define REPORT_SEGMENT_LAST_FLAG 0x40
185 #define BLE_REPORT_NUMBER 0x03
187 #define STEAMCONTROLLER_TRIGGER_MAX_ANALOG 26000
190 #undef ENABLE_MOUSE_MODE
198 #define RADIO_WORKAROUND_SLEEP_ATTEMPTS 50
199 #define RADIO_WORKAROUND_SLEEP_DURATION_US 500
202 #define CONTROLLER_CONFIGURATION_DELAY_US 3000
204 static uint8_t GetSegmentHeader(
int nSegmentNumber,
bool bLastPacket )
206 uint8_t header = REPORT_SEGMENT_DATA_FLAG;
207 header |= nSegmentNumber;
209 header |= REPORT_SEGMENT_LAST_FLAG;
217 for (
i = 0;
i <
len ; ++
i )
218 printf(
"%02x ",
ptr[
i]);
222 static void ResetSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler )
224 memset( pAssembler->uBuffer, 0,
sizeof( pAssembler->uBuffer ) );
225 pAssembler->nExpectedSegmentNumber = 0;
228 static void InitializeSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler )
231 pAssembler->bIsBle =
true;
232 ResetSteamControllerPacketAssembler( pAssembler );
239 static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler,
const uint8_t *pSegment,
int nSegmentLength )
241 if ( pAssembler->bIsBle )
243 HEXDUMP( pSegment, nSegmentLength );
245 if ( pSegment[ 0 ] != BLE_REPORT_NUMBER )
251 if ( nSegmentLength != MAX_REPORT_SEGMENT_SIZE )
253 printf(
"Bad segment size! %d\n", (
int)nSegmentLength );
254 hexdump( pSegment, nSegmentLength );
255 ResetSteamControllerPacketAssembler( pAssembler );
259 uint8_t uSegmentHeader = pSegment[ 1 ];
260 DPRINTF(
"GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
262 if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 )
268 int nSegmentNumber = uSegmentHeader & 0x07;
269 if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber )
271 ResetSteamControllerPacketAssembler( pAssembler );
273 if ( nSegmentNumber )
276 DPRINTF(
"Bad segment number, got %d, expected %d\n",
277 nSegmentNumber, pAssembler->nExpectedSegmentNumber );
282 memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
284 MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
286 if ( uSegmentHeader & REPORT_SEGMENT_LAST_FLAG )
288 pAssembler->nExpectedSegmentNumber = 0;
289 return ( nSegmentNumber + 1 ) * MAX_REPORT_SEGMENT_PAYLOAD_SIZE;
292 pAssembler->nExpectedSegmentNumber++;
297 memcpy( pAssembler->uBuffer,
300 return nSegmentLength;
306 #define BLE_MAX_READ_RETRIES 8
308 static int SetFeatureReport(
hid_device *dev,
unsigned char uBuffer[65],
int nActualDataLen )
310 DPRINTF(
"SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
316 if ( nActualDataLen < 1 )
319 int nSegmentNumber = 0;
320 uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
323 unsigned char *pBufferPtr = uBuffer + 1;
326 while ( nActualDataLen > 0 )
328 int nBytesInPacket = nActualDataLen > MAX_REPORT_SEGMENT_PAYLOAD_SIZE ? MAX_REPORT_SEGMENT_PAYLOAD_SIZE : nActualDataLen;
330 nActualDataLen -= nBytesInPacket;
333 memset( uPacketBuffer, 0,
sizeof( uPacketBuffer ) );
334 uPacketBuffer[ 0 ] = BLE_REPORT_NUMBER;
335 uPacketBuffer[ 1 ] = GetSegmentHeader( nSegmentNumber, nActualDataLen == 0 );
336 memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
338 pBufferPtr += nBytesInPacket;
342 DPRINTF(
"SetFeatureReport() ret = %d\n", nRet);
349 static int GetFeatureReport(
hid_device *dev,
unsigned char uBuffer[65] )
351 DPRINTF(
"GetFeatureReport( %p %p )\n", dev, uBuffer );
357 SteamControllerPacketAssembler assembler;
358 InitializeSteamControllerPacketAssembler( &assembler );
361 uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
362 while( nRetries < BLE_MAX_READ_RETRIES )
364 memset( uSegmentBuffer, 0,
sizeof( uSegmentBuffer ) );
365 uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
367 DPRINTF(
"GetFeatureReport ble ret=%d\n", nRet );
368 HEXDUMP( uSegmentBuffer, nRet );
371 if ( nRet > 2 && ( uSegmentBuffer[ 1 ] & REPORT_SEGMENT_DATA_FLAG ) )
378 int nPacketLength = WriteSegmentToSteamControllerPacketAssembler( &assembler,
382 if ( nPacketLength > 0 && nPacketLength < 65 )
386 memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
387 return nPacketLength;
393 printf(
"Could not get a full ble packet after %d retries\n", nRetries );
400 static int ReadResponse(
hid_device *dev,
uint8_t uBuffer[65],
int nExpectedResponse )
402 DPRINTF(
"ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
403 int nRet = GetFeatureReport( dev, uBuffer );
408 DPRINTF(
"ReadResponse got %d bytes of data: ", nRet );
409 HEXDUMP( uBuffer, nRet );
411 if ( uBuffer[1] != nExpectedResponse )
420 static bool ResetSteamController(
hid_device *dev,
bool bSuppressErrorSpew )
422 DPRINTF(
"ResetSteamController hid=%p\n", dev );
424 unsigned char buf[65];
428 buf[1] = ID_GET_ATTRIBUTES_VALUES;
429 res = SetFeatureReport( dev,
buf, 2 );
432 if ( !bSuppressErrorSpew )
433 printf(
"GET_ATTRIBUTES_VALUES failed for controller %p\n", dev );
439 res = ReadResponse( dev,
buf, ID_GET_ATTRIBUTES_VALUES );
440 if (
res < 0 ||
buf[1] != ID_GET_ATTRIBUTES_VALUES )
443 if ( !bSuppressErrorSpew )
444 printf(
"Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
448 int nAttributesLength =
buf[ 2 ];
449 if ( nAttributesLength >
res )
451 if ( !bSuppressErrorSpew )
452 printf(
"Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
458 buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
459 res = SetFeatureReport( dev,
buf, 2 );
462 if ( !bSuppressErrorSpew )
463 printf(
"CLEAR_DIGITAL_MAPPINGS failed for controller %p\n", dev );
469 buf[1] = ID_LOAD_DEFAULT_SETTINGS;
471 res = SetFeatureReport( dev,
buf, 3 );
474 if ( !bSuppressErrorSpew )
475 printf(
"LOAD_DEFAULT_SETTINGS failed for controller %p\n", dev );
481 #define ADD_SETTING(SETTING, VALUE) \
482 buf[3+nSettings*3] = SETTING; \
483 buf[3+nSettings*3+1] = ((uint16_t)VALUE)&0xFF; \
484 buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
488 buf[1] = ID_SET_SETTINGS_VALUES;
489 ADD_SETTING( SETTING_WIRELESS_PACKET_VERSION, 2 );
490 ADD_SETTING( SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE );
491 #ifdef ENABLE_MOUSE_MODE
492 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
493 ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 1 );
494 ADD_SETTING( SETTING_MOMENTUM_MAXIMUM_VELOCITY, 20000 );
495 ADD_SETTING( SETTING_MOMENTUM_DECAY_AMMOUNT, 50 );
497 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE );
498 ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 0 );
500 buf[2] = nSettings*3;
502 res = SetFeatureReport( dev,
buf, 3+nSettings*3 );
505 if ( !bSuppressErrorSpew )
506 printf(
"SET_SETTINGS failed for controller %p\n", dev );
510 #ifdef ENABLE_MOUSE_MODE
512 bool bMappingsCleared =
false;
514 for ( iRetry = 0; iRetry < 2; ++iRetry )
517 buf[1] = ID_GET_DIGITAL_MAPPINGS;
520 res = SetFeatureReport( dev,
buf, 4 );
523 printf(
"GET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
527 res = ReadResponse( dev,
buf, ID_GET_DIGITAL_MAPPINGS );
528 if (
res < 0 ||
buf[1] != ID_GET_DIGITAL_MAPPINGS )
530 printf(
"Bad GET_DIGITAL_MAPPINGS response for controller %p\n", dev );
535 if (
buf[2] == 1 &&
buf[3] == 0xFF )
537 bMappingsCleared =
true;
540 usleep( CONTROLLER_CONFIGURATION_DELAY_US );
543 if ( !bMappingsCleared && !bSuppressErrorSpew )
545 printf(
"Warning: CLEAR_DIGITAL_MAPPINGS never completed for controller %p\n", dev );
550 buf[1] = ID_SET_DIGITAL_MAPPINGS;
552 buf[3] = IO_DIGITAL_BUTTON_RIGHT_TRIGGER;
553 buf[4] = DEVICE_MOUSE;
554 buf[5] = MOUSE_BTN_LEFT;
555 buf[6] = IO_DIGITAL_BUTTON_LEFT_TRIGGER;
556 buf[7] = DEVICE_MOUSE;
557 buf[8] = MOUSE_BTN_RIGHT;
559 res = SetFeatureReport( dev,
buf, 9 );
562 if ( !bSuppressErrorSpew )
563 printf(
"SET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
566 #endif // ENABLE_MOUSE_MODE
577 memset( pData, 0, nDataSize );
578 pData[ 0 ] = BLE_REPORT_NUMBER;
579 return hid_read( dev, pData, nDataSize );
586 static void CloseSteamController(
hid_device *dev )
589 unsigned char buf[65];
594 buf[1] = ID_SET_DEFAULT_DIGITAL_MAPPINGS;
595 SetFeatureReport( dev,
buf, 2 );
599 buf[1] = ID_LOAD_DEFAULT_SETTINGS;
601 SetFeatureReport( dev,
buf, 3 );
605 buf[1] = ID_SET_SETTINGS_VALUES;
606 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
607 buf[2] = nSettings*3;
608 SetFeatureReport( dev,
buf, 3+nSettings*3 );
615 static float RemapValClamped(
float val,
float A,
float B,
float C,
float D)
619 return (
val - B ) >= 0.0f ? D : C;
623 float cVal = (
val - A) / (B - A);
624 cVal =
clamp( cVal, 0.0
f, 1.0
f );
626 return C + (D - C) * cVal;
634 static void RotatePad(
int *pX,
int *pY,
float flAngleInRad )
636 short int origX = *pX, origY = *pY;
638 *pX = (int)(
SDL_cosf( flAngleInRad ) * origX -
SDL_sinf( flAngleInRad ) * origY );
639 *pY = (int)(
SDL_sinf( flAngleInRad ) * origX +
SDL_cosf( flAngleInRad ) * origY );
641 static void RotatePadShort(
short *pX,
short *pY,
float flAngleInRad )
643 short int origX = *pX, origY = *pY;
645 *pX = (short)(
SDL_cosf( flAngleInRad ) * origX -
SDL_sinf( flAngleInRad ) * origY );
646 *pY = (short)(
SDL_sinf( flAngleInRad ) * origX +
SDL_cosf( flAngleInRad ) * origY );
653 static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState, ValveControllerStatePacket_t *pStatePacket )
655 memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
658 pState->eControllerType = 2;
659 pState->unPacketNum = pStatePacket->unPacketNum;
662 memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
663 pState->ulButtons &= ~0xFFFF000000LL;
666 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
669 pState->sLeftPadX = pState->sPrevLeftPad[0] = pStatePacket->sLeftPadX;
670 pState->sLeftPadY = pState->sPrevLeftPad[1] = pStatePacket->sLeftPadY;
672 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
675 pState->sLeftStickX = pState->sPrevLeftStick[0];
676 pState->sLeftStickY = pState->sPrevLeftStick[1];
681 pState->sPrevLeftStick[0] = 0;
682 pState->sPrevLeftStick[1] = 0;
700 pState->sPrevLeftStick[0] = pState->sLeftStickX = pStatePacket->sLeftPadX;
701 pState->sPrevLeftStick[1] = pState->sLeftStickY = pStatePacket->sLeftPadY;
710 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
713 pState->sLeftPadX = pState->sPrevLeftPad[0];
714 pState->sLeftPadY = pState->sPrevLeftPad[1];
719 pState->sPrevLeftPad[0] = 0;
720 pState->sPrevLeftPad[1] = 0;
723 if (pState->ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK)
725 pState->ulButtons &= ~STEAM_BUTTON_LEFTPAD_CLICKED_MASK;
726 pState->ulButtons |= STEAM_JOYSTICK_BUTTON_MASK;
733 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
734 pState->ulButtons |= STEAM_LEFTPAD_FINGERDOWN_MASK;
736 pState->sRightPadX = pStatePacket->sRightPadX;
737 pState->sRightPadY = pStatePacket->sRightPadY;
739 int nLeftPadX = pState->sLeftPadX;
740 int nLeftPadY = pState->sLeftPadY;
741 int nRightPadX = pState->sRightPadX;
742 int nRightPadY = pState->sRightPadY;
745 const float flRotationAngle = 0.261799f;
747 RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle);
748 RotatePad(&nRightPadX, &nRightPadY, flRotationAngle);
751 if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
760 if (pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK)
768 pState->sTriggerL = (
unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nLeft << 7) | pStatePacket->ButtonTriggerData.Triggers.nLeft, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0,
SDL_MAX_SINT16 );
769 pState->sTriggerR = (
unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nRight << 7) | pStatePacket->ButtonTriggerData.Triggers.nRight, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0,
SDL_MAX_SINT16 );
776 static bool UpdateBLESteamControllerState(
const uint8_t *pData,
int nDataSize, SteamControllerStateInternal_t *pState )
778 const float flRotationAngle = 0.261799f;
781 pState->unPacketNum++;
782 ucOptionDataMask = ( *pData++ & 0xF0 );
783 ucOptionDataMask |= (
uint32_t)(*pData++) << 8;
784 if ( ucOptionDataMask & k_EBLEButtonChunk1 )
786 memcpy( &pState->ulButtons, pData, 3 );
789 if ( ucOptionDataMask & k_EBLEButtonChunk2 )
792 pState->sTriggerL = (
unsigned short)RemapValClamped( ( pData[ 0 ] << 7 ) | pData[ 0 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0,
SDL_MAX_SINT16 );
793 pState->sTriggerR = (
unsigned short)RemapValClamped( ( pData[ 1 ] << 7 ) | pData[ 1 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0,
SDL_MAX_SINT16 );
796 if ( ucOptionDataMask & k_EBLEButtonChunk3 )
799 pButtonByte[ 5 ] = *pData++;
800 pButtonByte[ 6 ] = *pData++;
801 pButtonByte[ 7 ] = *pData++;
803 if ( ucOptionDataMask & k_EBLELeftJoystickChunk )
807 int nLength =
sizeof( pState->sLeftStickX ) +
sizeof( pState->sLeftStickY );
808 memcpy( &pState->sLeftStickX, pData, nLength );
811 if ( ucOptionDataMask & k_EBLELeftTrackpadChunk )
813 int nLength =
sizeof( pState->sLeftPadX ) +
sizeof( pState->sLeftPadY );
815 memcpy( &pState->sLeftPadX, pData, nLength );
816 if ( pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK )
821 RotatePadShort( &pState->sLeftPadX, &pState->sLeftPadY, -flRotationAngle );
826 if ( ucOptionDataMask & k_EBLERightTrackpadChunk )
828 int nLength =
sizeof( pState->sRightPadX ) +
sizeof( pState->sRightPadY );
831 memcpy( &pState->sRightPadX, pData, nLength );
833 if ( pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK )
838 RotatePadShort( &pState->sRightPadX, &pState->sRightPadY, flRotationAngle );
843 if ( ucOptionDataMask & k_EBLEIMUAccelChunk )
845 int nLength =
sizeof( pState->sAccelX ) +
sizeof( pState->sAccelY ) +
sizeof( pState->sAccelZ );
846 memcpy( &pState->sAccelX, pData, nLength );
849 if ( ucOptionDataMask & k_EBLEIMUGyroChunk )
851 int nLength =
sizeof( pState->sAccelX ) +
sizeof( pState->sAccelY ) +
sizeof( pState->sAccelZ );
852 memcpy( &pState->sGyroX, pData, nLength );
855 if ( ucOptionDataMask & k_EBLEIMUQuatChunk )
857 int nLength =
sizeof( pState->sGyroQuatW ) +
sizeof( pState->sGyroQuatX ) +
sizeof( pState->sGyroQuatY ) +
sizeof( pState->sGyroQuatZ );
858 memcpy( &pState->sGyroQuatW, pData, nLength );
868 static bool UpdateSteamControllerState(
const uint8_t *pData,
int nDataSize, SteamControllerStateInternal_t *pState )
870 ValveInReport_t *pInReport = (ValveInReport_t*)pData;
872 if ( pInReport->header.unReportVersion != k_ValveInReportMsgVersion )
874 if ( ( pData[ 0 ] & 0x0F ) == k_EBLEReportState )
876 return UpdateBLESteamControllerState( pData, nDataSize, pState );
881 if ( ( pInReport->header.ucType != ID_CONTROLLER_STATE ) &&
882 ( pInReport->header.ucType != ID_CONTROLLER_BLE_STATE ) )
887 if ( pInReport->header.ucType == ID_CONTROLLER_STATE )
889 ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
892 if ( pState->unPacketNum == pStatePacket->unPacketNum )
895 FormatStatePacketUntilGyro( pState, pStatePacket );
897 pState->sAccelX = pStatePacket->sAccelX;
898 pState->sAccelY = pStatePacket->sAccelY;
899 pState->sAccelZ = pStatePacket->sAccelZ;
901 pState->sGyroQuatW = pStatePacket->sGyroQuatW;
902 pState->sGyroQuatX = pStatePacket->sGyroQuatX;
903 pState->sGyroQuatY = pStatePacket->sGyroQuatY;
904 pState->sGyroQuatZ = pStatePacket->sGyroQuatZ;
906 pState->sGyroX = pStatePacket->sGyroX;
907 pState->sGyroY = pStatePacket->sGyroY;
908 pState->sGyroZ = pStatePacket->sGyroZ;
911 else if ( pInReport->header.ucType == ID_CONTROLLER_BLE_STATE )
913 ValveControllerBLEStatePacket_t *pBLEStatePacket = &pInReport->payload.controllerBLEState;
914 ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
917 if ( pState->unPacketNum == pStatePacket->unPacketNum )
920 FormatStatePacketUntilGyro( pState, pStatePacket );
922 switch ( pBLEStatePacket->ucGyroDataType )
925 pState->sGyroQuatW = (( float ) pBLEStatePacket->sGyro[0]);
926 pState->sGyroQuatX = (( float ) pBLEStatePacket->sGyro[1]);
927 pState->sGyroQuatY = (( float ) pBLEStatePacket->sGyro[2]);
928 pState->sGyroQuatZ = (( float ) pBLEStatePacket->sGyro[3]);
932 pState->sAccelX = pBLEStatePacket->sGyro[0];
933 pState->sAccelY = pBLEStatePacket->sGyro[1];
934 pState->sAccelZ = pBLEStatePacket->sGyro[2];
938 pState->sGyroX = pBLEStatePacket->sGyro[0];
939 pState->sGyroY = pBLEStatePacket->sGyro[1];
940 pState->sGyroZ = pBLEStatePacket->sGyro[2];
954 SteamControllerPacketAssembler m_assembler;
955 SteamControllerStateInternal_t m_state;
956 SteamControllerStateInternal_t m_last_state;
957 } SDL_DriverSteam_Context;
967 HIDAPI_DriverSteam_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
969 return "Steam Controller";
973 HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *
device)
985 HIDAPI_DriverSteam_SetDevicePlayerIndex(SDL_HIDAPI_Device *
device,
SDL_JoystickID instance_id,
int player_index)
990 HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *
device, SDL_Joystick *joystick)
992 SDL_DriverSteam_Context *
ctx;
1007 if (!ResetSteamController(
device->dev,
false)) {
1011 InitializeSteamControllerPacketAssembler(&
ctx->m_assembler);
1032 HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device *
device, SDL_Joystick *joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble)
1039 HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *
device)
1041 SDL_DriverSteam_Context *
ctx = (SDL_DriverSteam_Context *)
device->context;
1042 SDL_Joystick *joystick =
NULL;
1054 int r, nPacketLength;
1055 const Uint8 *pPacket;
1065 nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&
ctx->m_assembler,
data,
r);
1068 pPacket =
ctx->m_assembler.uBuffer;
1070 if (nPacketLength > 0 && UpdateSteamControllerState(pPacket, nPacketLength, &
ctx->m_state)) {
1071 if (
ctx->m_state.ulButtons !=
ctx->m_last_state.ulButtons) {
1104 const int kPadDeadZone = 10000;
1128 ctx->m_last_state =
ctx->m_state;
1141 HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *
device, SDL_Joystick *joystick)
1143 CloseSteamController(
device->dev);
1152 HIDAPI_DriverSteam_FreeDevice(SDL_HIDAPI_Device *
device)
1160 HIDAPI_DriverSteam_IsSupportedDevice,
1161 HIDAPI_DriverSteam_GetDeviceName,
1162 HIDAPI_DriverSteam_InitDevice,
1163 HIDAPI_DriverSteam_GetDevicePlayerIndex,
1164 HIDAPI_DriverSteam_SetDevicePlayerIndex,
1165 HIDAPI_DriverSteam_UpdateDevice,
1166 HIDAPI_DriverSteam_OpenJoystick,
1167 HIDAPI_DriverSteam_RumbleJoystick,
1168 HIDAPI_DriverSteam_CloseJoystick,
1169 HIDAPI_DriverSteam_FreeDevice