|
@@ -203,8 +203,9 @@ static uint8_t GetSegmentHeader( int nSegmentNumber, bool bLastPacket )
|
|
{
|
|
{
|
|
uint8_t header = REPORT_SEGMENT_DATA_FLAG;
|
|
uint8_t header = REPORT_SEGMENT_DATA_FLAG;
|
|
header |= nSegmentNumber;
|
|
header |= nSegmentNumber;
|
|
- if ( bLastPacket )
|
|
|
|
|
|
+ if (bLastPacket) {
|
|
header |= REPORT_SEGMENT_LAST_FLAG;
|
|
header |= REPORT_SEGMENT_LAST_FLAG;
|
|
|
|
+ }
|
|
|
|
|
|
return header;
|
|
return header;
|
|
}
|
|
}
|
|
@@ -212,8 +213,9 @@ static uint8_t GetSegmentHeader( int nSegmentNumber, bool bLastPacket )
|
|
static void hexdump( const uint8_t *ptr, int len )
|
|
static void hexdump( const uint8_t *ptr, int len )
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
- for ( i = 0; i < len ; ++i )
|
|
|
|
|
|
+ for (i = 0; i < len; ++i) {
|
|
printf("%02x ", ptr[i]);
|
|
printf("%02x ", ptr[i]);
|
|
|
|
+ }
|
|
printf("\n");
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -236,21 +238,18 @@ static void InitializeSteamControllerPacketAssembler( SteamControllerPacketAssem
|
|
// Complete packet size on completion
|
|
// Complete packet size on completion
|
|
static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler, const uint8_t *pSegment, int nSegmentLength )
|
|
static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler, const uint8_t *pSegment, int nSegmentLength )
|
|
{
|
|
{
|
|
- if ( pAssembler->bIsBle )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( pAssembler->bIsBle ) {
|
|
uint8_t uSegmentHeader = pSegment[ 1 ];
|
|
uint8_t uSegmentHeader = pSegment[ 1 ];
|
|
int nSegmentNumber = uSegmentHeader & 0x07;
|
|
int nSegmentNumber = uSegmentHeader & 0x07;
|
|
|
|
|
|
HEXDUMP( pSegment, nSegmentLength );
|
|
HEXDUMP( pSegment, nSegmentLength );
|
|
|
|
|
|
- if ( pSegment[ 0 ] != BLE_REPORT_NUMBER )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( pSegment[ 0 ] != BLE_REPORT_NUMBER ) {
|
|
// We may get keyboard/mouse input events until controller stops sending them
|
|
// We may get keyboard/mouse input events until controller stops sending them
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if ( nSegmentLength != MAX_REPORT_SEGMENT_SIZE )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( nSegmentLength != MAX_REPORT_SEGMENT_SIZE ) {
|
|
printf( "Bad segment size! %d\n", (int)nSegmentLength );
|
|
printf( "Bad segment size! %d\n", (int)nSegmentLength );
|
|
hexdump( pSegment, nSegmentLength );
|
|
hexdump( pSegment, nSegmentLength );
|
|
ResetSteamControllerPacketAssembler( pAssembler );
|
|
ResetSteamControllerPacketAssembler( pAssembler );
|
|
@@ -259,18 +258,15 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
|
|
|
|
|
|
DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
|
|
DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
|
|
|
|
|
|
- if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 ) {
|
|
// We get empty segments, just ignore them
|
|
// We get empty segments, just ignore them
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber ) {
|
|
ResetSteamControllerPacketAssembler( pAssembler );
|
|
ResetSteamControllerPacketAssembler( pAssembler );
|
|
|
|
|
|
- if ( nSegmentNumber )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( nSegmentNumber ) {
|
|
// This happens occasionally
|
|
// This happens occasionally
|
|
DPRINTF("Bad segment number, got %d, expected %d\n",
|
|
DPRINTF("Bad segment number, got %d, expected %d\n",
|
|
nSegmentNumber, pAssembler->nExpectedSegmentNumber );
|
|
nSegmentNumber, pAssembler->nExpectedSegmentNumber );
|
|
@@ -282,16 +278,13 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
|
|
pSegment + 2, // ignore header and report number
|
|
pSegment + 2, // ignore header and report number
|
|
MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
|
|
MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
|
|
|
|
|
|
- if ( uSegmentHeader & REPORT_SEGMENT_LAST_FLAG )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( uSegmentHeader & REPORT_SEGMENT_LAST_FLAG ) {
|
|
pAssembler->nExpectedSegmentNumber = 0;
|
|
pAssembler->nExpectedSegmentNumber = 0;
|
|
return ( nSegmentNumber + 1 ) * MAX_REPORT_SEGMENT_PAYLOAD_SIZE;
|
|
return ( nSegmentNumber + 1 ) * MAX_REPORT_SEGMENT_PAYLOAD_SIZE;
|
|
}
|
|
}
|
|
|
|
|
|
pAssembler->nExpectedSegmentNumber++;
|
|
pAssembler->nExpectedSegmentNumber++;
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
// Just pass through
|
|
// Just pass through
|
|
SDL_memcpy( pAssembler->uBuffer,
|
|
SDL_memcpy( pAssembler->uBuffer,
|
|
pSegment,
|
|
pSegment,
|
|
@@ -311,20 +304,19 @@ static int SetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65], int
|
|
|
|
|
|
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
|
|
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
|
|
|
|
|
|
- if ( bBle )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( bBle ) {
|
|
int nSegmentNumber = 0;
|
|
int nSegmentNumber = 0;
|
|
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
|
|
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
|
|
unsigned char *pBufferPtr = uBuffer + 1;
|
|
unsigned char *pBufferPtr = uBuffer + 1;
|
|
|
|
|
|
- if ( nActualDataLen < 1 )
|
|
|
|
|
|
+ if (nActualDataLen < 1) {
|
|
return -1;
|
|
return -1;
|
|
|
|
+ }
|
|
|
|
|
|
// Skip report number in data
|
|
// Skip report number in data
|
|
nActualDataLen--;
|
|
nActualDataLen--;
|
|
|
|
|
|
- while ( nActualDataLen > 0 )
|
|
|
|
- {
|
|
|
|
|
|
+ while ( nActualDataLen > 0 ) {
|
|
int nBytesInPacket = nActualDataLen > MAX_REPORT_SEGMENT_PAYLOAD_SIZE ? MAX_REPORT_SEGMENT_PAYLOAD_SIZE : nActualDataLen;
|
|
int nBytesInPacket = nActualDataLen > MAX_REPORT_SEGMENT_PAYLOAD_SIZE ? MAX_REPORT_SEGMENT_PAYLOAD_SIZE : nActualDataLen;
|
|
|
|
|
|
nActualDataLen -= nBytesInPacket;
|
|
nActualDataLen -= nBytesInPacket;
|
|
@@ -353,8 +345,7 @@ static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
|
|
|
|
|
|
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
|
|
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
|
|
|
|
|
|
- if ( bBle )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( bBle ) {
|
|
int nRetries = 0;
|
|
int nRetries = 0;
|
|
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE + 1 ];
|
|
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE + 1 ];
|
|
uint8_t ucBytesToRead = MAX_REPORT_SEGMENT_SIZE;
|
|
uint8_t ucBytesToRead = MAX_REPORT_SEGMENT_SIZE;
|
|
@@ -371,8 +362,7 @@ static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
|
|
++ucDataStartOffset;
|
|
++ucDataStartOffset;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- while( nRetries < BLE_MAX_READ_RETRIES )
|
|
|
|
- {
|
|
|
|
|
|
+ while ( nRetries < BLE_MAX_READ_RETRIES ) {
|
|
SDL_memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
|
|
SDL_memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
|
|
uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
|
|
uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
|
|
nRet = SDL_hid_get_feature_report( dev, uSegmentBuffer, ucBytesToRead );
|
|
nRet = SDL_hid_get_feature_report( dev, uSegmentBuffer, ucBytesToRead );
|
|
@@ -386,14 +376,12 @@ static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
|
|
else
|
|
else
|
|
nRetries++;
|
|
nRetries++;
|
|
|
|
|
|
- if ( nRet > 0 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( nRet > 0 ) {
|
|
int nPacketLength = WriteSegmentToSteamControllerPacketAssembler( &assembler,
|
|
int nPacketLength = WriteSegmentToSteamControllerPacketAssembler( &assembler,
|
|
uSegmentBuffer + ucDataStartOffset,
|
|
uSegmentBuffer + ucDataStartOffset,
|
|
nRet - ucDataStartOffset );
|
|
nRet - ucDataStartOffset );
|
|
|
|
|
|
- if ( nPacketLength > 0 && nPacketLength < 65 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( nPacketLength > 0 && nPacketLength < 65 ) {
|
|
// Leave space for "report number"
|
|
// Leave space for "report number"
|
|
uBuffer[ 0 ] = 0;
|
|
uBuffer[ 0 ] = 0;
|
|
SDL_memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
|
|
SDL_memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
|
|
@@ -416,14 +404,16 @@ static int ReadResponse( SDL_hid_device *dev, uint8_t uBuffer[65], int nExpected
|
|
|
|
|
|
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
|
|
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
|
|
|
|
|
|
- if ( nRet < 0 )
|
|
|
|
|
|
+ if (nRet < 0) {
|
|
return nRet;
|
|
return nRet;
|
|
|
|
+ }
|
|
|
|
|
|
DPRINTF("ReadResponse got %d bytes of data: ", nRet );
|
|
DPRINTF("ReadResponse got %d bytes of data: ", nRet );
|
|
HEXDUMP( uBuffer, nRet );
|
|
HEXDUMP( uBuffer, nRet );
|
|
|
|
|
|
- if ( uBuffer[1] != nExpectedResponse )
|
|
|
|
|
|
+ if (uBuffer[1] != nExpectedResponse) {
|
|
return -1;
|
|
return -1;
|
|
|
|
+ }
|
|
|
|
|
|
return nRet;
|
|
return nRet;
|
|
}
|
|
}
|
|
@@ -447,35 +437,34 @@ static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew,
|
|
buf[0] = 0;
|
|
buf[0] = 0;
|
|
buf[1] = ID_GET_ATTRIBUTES_VALUES;
|
|
buf[1] = ID_GET_ATTRIBUTES_VALUES;
|
|
res = SetFeatureReport( dev, buf, 2 );
|
|
res = SetFeatureReport( dev, buf, 2 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "GET_ATTRIBUTES_VALUES failed for controller %p\n", dev );
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("GET_ATTRIBUTES_VALUES failed for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
// Retrieve GET_ATTRIBUTES_VALUES result
|
|
// Retrieve GET_ATTRIBUTES_VALUES result
|
|
// Wireless controller endpoints without a connected controller will return nAttrs == 0
|
|
// Wireless controller endpoints without a connected controller will return nAttrs == 0
|
|
res = ReadResponse( dev, buf, ID_GET_ATTRIBUTES_VALUES );
|
|
res = ReadResponse( dev, buf, ID_GET_ATTRIBUTES_VALUES );
|
|
- if ( res < 0 || buf[1] != ID_GET_ATTRIBUTES_VALUES )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( res < 0 || buf[1] != ID_GET_ATTRIBUTES_VALUES ) {
|
|
HEXDUMP(buf, res);
|
|
HEXDUMP(buf, res);
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
|
|
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
nAttributesLength = buf[ 2 ];
|
|
nAttributesLength = buf[ 2 ];
|
|
- if ( nAttributesLength > res )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
|
|
|
|
|
|
+ if ( nAttributesLength > res ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
msg = (FeatureReportMsg *)&buf[1];
|
|
msg = (FeatureReportMsg *)&buf[1];
|
|
- for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i )
|
|
|
|
- {
|
|
|
|
|
|
+ for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i ) {
|
|
uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
|
|
uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
|
|
uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
|
|
uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
|
|
|
|
|
|
@@ -494,8 +483,7 @@ static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if ( punUpdateRateUS )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( punUpdateRateUS ) {
|
|
*punUpdateRateUS = unUpdateRateUS;
|
|
*punUpdateRateUS = unUpdateRateUS;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -503,10 +491,10 @@ static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew,
|
|
buf[0] = 0;
|
|
buf[0] = 0;
|
|
buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
|
|
buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
|
|
res = SetFeatureReport( dev, buf, 2 );
|
|
res = SetFeatureReport( dev, buf, 2 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "CLEAR_DIGITAL_MAPPINGS failed for controller %p\n", dev );
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("CLEAR_DIGITAL_MAPPINGS failed for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -515,10 +503,10 @@ static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew,
|
|
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
|
|
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
|
|
buf[2] = 0;
|
|
buf[2] = 0;
|
|
res = SetFeatureReport( dev, buf, 3 );
|
|
res = SetFeatureReport( dev, buf, 3 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "LOAD_DEFAULT_SETTINGS failed for controller %p\n", dev );
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("LOAD_DEFAULT_SETTINGS failed for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -545,10 +533,10 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
|
|
buf[2] = nSettings*3;
|
|
buf[2] = nSettings*3;
|
|
|
|
|
|
res = SetFeatureReport( dev, buf, 3+nSettings*3 );
|
|
res = SetFeatureReport( dev, buf, 3+nSettings*3 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "SET_SETTINGS failed for controller %p\n", dev );
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("SET_SETTINGS failed for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -556,37 +544,32 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
|
|
// Wait for ID_CLEAR_DIGITAL_MAPPINGS to be processed on the controller
|
|
// Wait for ID_CLEAR_DIGITAL_MAPPINGS to be processed on the controller
|
|
bool bMappingsCleared = false;
|
|
bool bMappingsCleared = false;
|
|
int iRetry;
|
|
int iRetry;
|
|
- for ( iRetry = 0; iRetry < 2; ++iRetry )
|
|
|
|
- {
|
|
|
|
|
|
+ for ( iRetry = 0; iRetry < 2; ++iRetry ) {
|
|
SDL_memset( buf, 0, 65 );
|
|
SDL_memset( buf, 0, 65 );
|
|
buf[1] = ID_GET_DIGITAL_MAPPINGS;
|
|
buf[1] = ID_GET_DIGITAL_MAPPINGS;
|
|
buf[2] = 1; // one byte - requesting from index 0
|
|
buf[2] = 1; // one byte - requesting from index 0
|
|
buf[3] = 0;
|
|
buf[3] = 0;
|
|
res = SetFeatureReport( dev, buf, 4 );
|
|
res = SetFeatureReport( dev, buf, 4 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
printf( "GET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
|
|
printf( "GET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
res = ReadResponse( dev, buf, ID_GET_DIGITAL_MAPPINGS );
|
|
res = ReadResponse( dev, buf, ID_GET_DIGITAL_MAPPINGS );
|
|
- if ( res < 0 || buf[1] != ID_GET_DIGITAL_MAPPINGS )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( res < 0 || buf[1] != ID_GET_DIGITAL_MAPPINGS ) {
|
|
printf( "Bad GET_DIGITAL_MAPPINGS response for controller %p\n", dev );
|
|
printf( "Bad GET_DIGITAL_MAPPINGS response for controller %p\n", dev );
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
// If the length of the digital mappings result is not 1 (index byte, no mappings) then clearing hasn't executed
|
|
// If the length of the digital mappings result is not 1 (index byte, no mappings) then clearing hasn't executed
|
|
- if ( buf[2] == 1 && buf[3] == 0xFF )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( buf[2] == 1 && buf[3] == 0xFF ) {
|
|
bMappingsCleared = true;
|
|
bMappingsCleared = true;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
usleep( CONTROLLER_CONFIGURATION_DELAY_US );
|
|
usleep( CONTROLLER_CONFIGURATION_DELAY_US );
|
|
}
|
|
}
|
|
|
|
|
|
- if ( !bMappingsCleared && !bSuppressErrorSpew )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( !bMappingsCleared && !bSuppressErrorSpew ) {
|
|
printf( "Warning: CLEAR_DIGITAL_MAPPINGS never completed for controller %p\n", dev );
|
|
printf( "Warning: CLEAR_DIGITAL_MAPPINGS never completed for controller %p\n", dev );
|
|
}
|
|
}
|
|
|
|
|
|
@@ -602,10 +585,10 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
|
|
buf[8] = MOUSE_BTN_RIGHT;
|
|
buf[8] = MOUSE_BTN_RIGHT;
|
|
|
|
|
|
res = SetFeatureReport( dev, buf, 9 );
|
|
res = SetFeatureReport( dev, buf, 9 );
|
|
- if ( res < 0 )
|
|
|
|
- {
|
|
|
|
- if ( !bSuppressErrorSpew )
|
|
|
|
- printf( "SET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
|
|
|
|
|
|
+ if ( res < 0 ) {
|
|
|
|
+ if (!bSuppressErrorSpew) {
|
|
|
|
+ printf("SET_DIGITAL_MAPPINGS failed for controller %p\n", dev);
|
|
|
|
+ }
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
#endif // ENABLE_MOUSE_MODE
|
|
#endif // ENABLE_MOUSE_MODE
|
|
@@ -659,12 +642,9 @@ static void CloseSteamController( SDL_hid_device *dev )
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
static float RemapValClamped( float val, float A, float B, float C, float D)
|
|
static float RemapValClamped( float val, float A, float B, float C, float D)
|
|
{
|
|
{
|
|
- if ( A == B )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( A == B ) {
|
|
return ( val - B ) >= 0.0f ? D : C;
|
|
return ( val - B ) >= 0.0f ? D : C;
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
float cVal = (val - A) / (B - A);
|
|
float cVal = (val - A) / (B - A);
|
|
cVal = clamp( cVal, 0.0f, 1.0f );
|
|
cVal = clamp( cVal, 0.0f, 1.0f );
|
|
|
|
|
|
@@ -717,65 +697,52 @@ static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState,
|
|
pState->ulButtons &= ~0xFFFF000000LL;
|
|
pState->ulButtons &= ~0xFFFF000000LL;
|
|
|
|
|
|
// The firmware uses this bit to tell us what kind of data is packed into the left two axises
|
|
// The firmware uses this bit to tell us what kind of data is packed into the left two axises
|
|
- if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
|
|
|
|
- {
|
|
|
|
|
|
+ if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK) {
|
|
// Finger-down bit not set; "left pad" is actually trackpad
|
|
// Finger-down bit not set; "left pad" is actually trackpad
|
|
pState->sLeftPadX = pState->sPrevLeftPad[0] = pStatePacket->sLeftPadX;
|
|
pState->sLeftPadX = pState->sPrevLeftPad[0] = pStatePacket->sLeftPadX;
|
|
pState->sLeftPadY = pState->sPrevLeftPad[1] = pStatePacket->sLeftPadY;
|
|
pState->sLeftPadY = pState->sPrevLeftPad[1] = pStatePacket->sLeftPadY;
|
|
|
|
|
|
- if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
|
|
|
|
- {
|
|
|
|
|
|
+ if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) {
|
|
// The controller is interleaving both stick and pad data, both are active
|
|
// The controller is interleaving both stick and pad data, both are active
|
|
pState->sLeftStickX = pState->sPrevLeftStick[0];
|
|
pState->sLeftStickX = pState->sPrevLeftStick[0];
|
|
pState->sLeftStickY = pState->sPrevLeftStick[1];
|
|
pState->sLeftStickY = pState->sPrevLeftStick[1];
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
// The stick is not active
|
|
// The stick is not active
|
|
pState->sPrevLeftStick[0] = 0;
|
|
pState->sPrevLeftStick[0] = 0;
|
|
pState->sPrevLeftStick[1] = 0;
|
|
pState->sPrevLeftStick[1] = 0;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
// Finger-down bit not set; "left pad" is actually joystick
|
|
// Finger-down bit not set; "left pad" is actually joystick
|
|
|
|
|
|
// XXX there's a firmware bug where sometimes padX is 0 and padY is a large number (acutally the battery voltage)
|
|
// XXX there's a firmware bug where sometimes padX is 0 and padY is a large number (acutally the battery voltage)
|
|
// If that happens skip this packet and report last frames stick
|
|
// If that happens skip this packet and report last frames stick
|
|
/*
|
|
/*
|
|
- if ( m_eControllerType == k_eControllerType_SteamControllerV2 && pStatePacket->sLeftPadY > 900 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( m_eControllerType == k_eControllerType_SteamControllerV2 && pStatePacket->sLeftPadY > 900 ) {
|
|
pState->sLeftStickX = pState->sPrevLeftStick[0];
|
|
pState->sLeftStickX = pState->sPrevLeftStick[0];
|
|
pState->sLeftStickY = pState->sPrevLeftStick[1];
|
|
pState->sLeftStickY = pState->sPrevLeftStick[1];
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+ } else
|
|
*/
|
|
*/
|
|
{
|
|
{
|
|
pState->sPrevLeftStick[0] = pState->sLeftStickX = pStatePacket->sLeftPadX;
|
|
pState->sPrevLeftStick[0] = pState->sLeftStickX = pStatePacket->sLeftPadX;
|
|
pState->sPrevLeftStick[1] = pState->sLeftStickY = pStatePacket->sLeftPadY;
|
|
pState->sPrevLeftStick[1] = pState->sLeftStickY = pStatePacket->sLeftPadY;
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
- if (m_eControllerType == k_eControllerType_SteamControllerV2)
|
|
|
|
- {
|
|
|
|
|
|
+ if (m_eControllerType == k_eControllerType_SteamControllerV2) {
|
|
UpdateV2JoystickCap(&state);
|
|
UpdateV2JoystickCap(&state);
|
|
}
|
|
}
|
|
*/
|
|
*/
|
|
|
|
|
|
- if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
|
|
|
|
- {
|
|
|
|
|
|
+ if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) {
|
|
// The controller is interleaving both stick and pad data, both are active
|
|
// The controller is interleaving both stick and pad data, both are active
|
|
pState->sLeftPadX = pState->sPrevLeftPad[0];
|
|
pState->sLeftPadX = pState->sPrevLeftPad[0];
|
|
pState->sLeftPadY = pState->sPrevLeftPad[1];
|
|
pState->sLeftPadY = pState->sPrevLeftPad[1];
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
// The trackpad is not active
|
|
// The trackpad is not active
|
|
pState->sPrevLeftPad[0] = 0;
|
|
pState->sPrevLeftPad[0] = 0;
|
|
pState->sPrevLeftPad[1] = 0;
|
|
pState->sPrevLeftPad[1] = 0;
|
|
|
|
|
|
// Old controllers send trackpad click for joystick button when trackpad is not active
|
|
// Old controllers send trackpad click for joystick button when trackpad is not active
|
|
- if (pState->ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK)
|
|
|
|
- {
|
|
|
|
|
|
+ if (pState->ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK) {
|
|
pState->ulButtons &= ~STEAM_BUTTON_LEFTPAD_CLICKED_MASK;
|
|
pState->ulButtons &= ~STEAM_BUTTON_LEFTPAD_CLICKED_MASK;
|
|
pState->ulButtons |= STEAM_JOYSTICK_BUTTON_MASK;
|
|
pState->ulButtons |= STEAM_JOYSTICK_BUTTON_MASK;
|
|
}
|
|
}
|
|
@@ -784,8 +751,9 @@ static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState,
|
|
|
|
|
|
// Fingerdown bit indicates if the packed left axis data was joystick or pad,
|
|
// Fingerdown bit indicates if the packed left axis data was joystick or pad,
|
|
// but if we are interleaving both, the left finger is definitely on the pad.
|
|
// but if we are interleaving both, the left finger is definitely on the pad.
|
|
- if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
|
|
|
|
|
|
+ if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) {
|
|
pState->ulButtons |= STEAM_LEFTPAD_FINGERDOWN_MASK;
|
|
pState->ulButtons |= STEAM_LEFTPAD_FINGERDOWN_MASK;
|
|
|
|
+ }
|
|
|
|
|
|
pState->sRightPadX = pStatePacket->sRightPadX;
|
|
pState->sRightPadX = pStatePacket->sRightPadX;
|
|
pState->sRightPadY = pStatePacket->sRightPadY;
|
|
pState->sRightPadY = pStatePacket->sRightPadY;
|
|
@@ -831,35 +799,30 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
|
|
pState->unPacketNum++;
|
|
pState->unPacketNum++;
|
|
ucOptionDataMask = ( *pData++ & 0xF0 );
|
|
ucOptionDataMask = ( *pData++ & 0xF0 );
|
|
ucOptionDataMask |= (uint32_t)(*pData++) << 8;
|
|
ucOptionDataMask |= (uint32_t)(*pData++) << 8;
|
|
- if ( ucOptionDataMask & k_EBLEButtonChunk1 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEButtonChunk1 ) {
|
|
SDL_memcpy( &pState->ulButtons, pData, 3 );
|
|
SDL_memcpy( &pState->ulButtons, pData, 3 );
|
|
pData += 3;
|
|
pData += 3;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLEButtonChunk2 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEButtonChunk2 ) {
|
|
// The middle 2 bytes of the button bits over the wire are triggers when over the wire and non-SC buttons in the internal controller state packet
|
|
// The middle 2 bytes of the button bits over the wire are triggers when over the wire and non-SC buttons in the internal controller state packet
|
|
pState->sTriggerL = (unsigned short)RemapValClamped( (float)(( pData[ 0 ] << 7 ) | pData[ 0 ]), 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
|
|
pState->sTriggerL = (unsigned short)RemapValClamped( (float)(( pData[ 0 ] << 7 ) | pData[ 0 ]), 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
|
|
pState->sTriggerR = (unsigned short)RemapValClamped( (float)(( pData[ 1 ] << 7 ) | pData[ 1 ]), 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
|
|
pState->sTriggerR = (unsigned short)RemapValClamped( (float)(( pData[ 1 ] << 7 ) | pData[ 1 ]), 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
|
|
pData += 2;
|
|
pData += 2;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLEButtonChunk3 )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEButtonChunk3 ) {
|
|
uint8_t *pButtonByte = (uint8_t *)&pState->ulButtons;
|
|
uint8_t *pButtonByte = (uint8_t *)&pState->ulButtons;
|
|
pButtonByte[ 5 ] = *pData++;
|
|
pButtonByte[ 5 ] = *pData++;
|
|
pButtonByte[ 6 ] = *pData++;
|
|
pButtonByte[ 6 ] = *pData++;
|
|
pButtonByte[ 7 ] = *pData++;
|
|
pButtonByte[ 7 ] = *pData++;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLELeftJoystickChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLELeftJoystickChunk ) {
|
|
// This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support
|
|
// This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support
|
|
// this protocol yet either
|
|
// this protocol yet either
|
|
int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY );
|
|
int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY );
|
|
SDL_memcpy( &pState->sLeftStickX, pData, nLength );
|
|
SDL_memcpy( &pState->sLeftStickX, pData, nLength );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLELeftTrackpadChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLELeftTrackpadChunk ) {
|
|
int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY );
|
|
int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY );
|
|
int nPadOffset;
|
|
int nPadOffset;
|
|
SDL_memcpy( &pState->sLeftPadX, pData, nLength );
|
|
SDL_memcpy( &pState->sLeftPadX, pData, nLength );
|
|
@@ -873,8 +836,7 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
|
|
pState->sLeftPadY = clamp( pState->sLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
|
|
pState->sLeftPadY = clamp( pState->sLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLERightTrackpadChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLERightTrackpadChunk ) {
|
|
int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY );
|
|
int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY );
|
|
int nPadOffset = 0;
|
|
int nPadOffset = 0;
|
|
|
|
|
|
@@ -890,20 +852,17 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
|
|
pState->sRightPadY = clamp( pState->sRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
|
|
pState->sRightPadY = clamp( pState->sRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLEIMUAccelChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEIMUAccelChunk ) {
|
|
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
|
|
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
|
|
SDL_memcpy( &pState->sAccelX, pData, nLength );
|
|
SDL_memcpy( &pState->sAccelX, pData, nLength );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLEIMUGyroChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEIMUGyroChunk ) {
|
|
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
|
|
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
|
|
SDL_memcpy( &pState->sGyroX, pData, nLength );
|
|
SDL_memcpy( &pState->sGyroX, pData, nLength );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
}
|
|
}
|
|
- if ( ucOptionDataMask & k_EBLEIMUQuatChunk )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( ucOptionDataMask & k_EBLEIMUQuatChunk ) {
|
|
int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ );
|
|
int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ );
|
|
SDL_memcpy( &pState->sGyroQuatW, pData, nLength );
|
|
SDL_memcpy( &pState->sGyroQuatW, pData, nLength );
|
|
pData += nLength;
|
|
pData += nLength;
|
|
@@ -919,10 +878,8 @@ static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, Ste
|
|
{
|
|
{
|
|
ValveInReport_t *pInReport = (ValveInReport_t*)pData;
|
|
ValveInReport_t *pInReport = (ValveInReport_t*)pData;
|
|
|
|
|
|
- if ( pInReport->header.unReportVersion != k_ValveInReportMsgVersion )
|
|
|
|
- {
|
|
|
|
- if ( ( pData[ 0 ] & 0x0F ) == k_EBLEReportState )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( pInReport->header.unReportVersion != k_ValveInReportMsgVersion ) {
|
|
|
|
+ if ( ( pData[ 0 ] & 0x0F ) == k_EBLEReportState ) {
|
|
return UpdateBLESteamControllerState( pData, nDataSize, pState );
|
|
return UpdateBLESteamControllerState( pData, nDataSize, pState );
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
@@ -934,13 +891,13 @@ static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, Ste
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- if ( pInReport->header.ucType == ID_CONTROLLER_STATE )
|
|
|
|
- {
|
|
|
|
|
|
+ if ( pInReport->header.ucType == ID_CONTROLLER_STATE ) {
|
|
ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
|
|
ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
|
|
|
|
|
|
// No new data to process; indicate that we received a state packet, but otherwise do nothing.
|
|
// No new data to process; indicate that we received a state packet, but otherwise do nothing.
|
|
- if ( pState->unPacketNum == pStatePacket->unPacketNum )
|
|
|
|
|
|
+ if (pState->unPacketNum == pStatePacket->unPacketNum) {
|
|
return true;
|
|
return true;
|
|
|
|
+ }
|
|
|
|
|
|
FormatStatePacketUntilGyro( pState, pStatePacket );
|
|
FormatStatePacketUntilGyro( pState, pStatePacket );
|
|
|
|
|
|
@@ -957,15 +914,14 @@ static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, Ste
|
|
pState->sGyroY = pStatePacket->sGyroY;
|
|
pState->sGyroY = pStatePacket->sGyroY;
|
|
pState->sGyroZ = pStatePacket->sGyroZ;
|
|
pState->sGyroZ = pStatePacket->sGyroZ;
|
|
|
|
|
|
- }
|
|
|
|
- else if ( pInReport->header.ucType == ID_CONTROLLER_BLE_STATE )
|
|
|
|
- {
|
|
|
|
|
|
+ } else if ( pInReport->header.ucType == ID_CONTROLLER_BLE_STATE ) {
|
|
ValveControllerBLEStatePacket_t *pBLEStatePacket = &pInReport->payload.controllerBLEState;
|
|
ValveControllerBLEStatePacket_t *pBLEStatePacket = &pInReport->payload.controllerBLEState;
|
|
ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
|
|
ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
|
|
|
|
|
|
// No new data to process; indicate that we received a state packet, but otherwise do nothing.
|
|
// No new data to process; indicate that we received a state packet, but otherwise do nothing.
|
|
- if ( pState->unPacketNum == pStatePacket->unPacketNum )
|
|
|
|
|
|
+ if (pState->unPacketNum == pStatePacket->unPacketNum) {
|
|
return true;
|
|
return true;
|
|
|
|
+ }
|
|
|
|
|
|
FormatStatePacketUntilGyro( pState, pStatePacket );
|
|
FormatStatePacketUntilGyro( pState, pStatePacket );
|
|
|
|
|
|
@@ -1041,7 +997,7 @@ HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
|
|
SDL_DriverSteam_Context *ctx;
|
|
SDL_DriverSteam_Context *ctx;
|
|
|
|
|
|
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
|
|
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
|
|
- if (!ctx) {
|
|
|
|
|
|
+ if (ctx == NULL) {
|
|
SDL_OutOfMemory();
|
|
SDL_OutOfMemory();
|
|
return SDL_FALSE;
|
|
return SDL_FALSE;
|
|
}
|
|
}
|
|
@@ -1171,8 +1127,7 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
|
|
return SDL_FALSE;
|
|
return SDL_FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
- for (;;)
|
|
|
|
- {
|
|
|
|
|
|
+ for (;;) {
|
|
uint8_t data[128];
|
|
uint8_t data[128];
|
|
int r, nPacketLength;
|
|
int r, nPacketLength;
|
|
const Uint8 *pPacket;
|
|
const Uint8 *pPacket;
|
|
@@ -1182,7 +1137,7 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!joystick) {
|
|
|
|
|
|
+ if (joystick == NULL) {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|