SDL_hidapi_steam.c (43268B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20 */ 21 #include "../../SDL_internal.h" 22 23 #ifdef SDL_JOYSTICK_HIDAPI 24 25 #include "SDL_hints.h" 26 #include "SDL_events.h" 27 #include "SDL_timer.h" 28 #include "SDL_joystick.h" 29 #include "SDL_gamecontroller.h" 30 #include "../SDL_sysjoystick.h" 31 #include "SDL_hidapijoystick_c.h" 32 33 34 35 #ifdef SDL_JOYSTICK_HIDAPI_STEAM 36 37 /*****************************************************************************************************/ 38 39 #include <stdint.h> 40 41 typedef enum 42 { 43 false, 44 true 45 } bool; 46 47 typedef uint32_t uint32; 48 typedef uint64_t uint64; 49 50 #include "steam/controller_constants.h" 51 #include "steam/controller_structs.h" 52 53 typedef struct SteamControllerStateInternal_t 54 { 55 // Controller Type for this Controller State 56 uint32 eControllerType; 57 58 // If packet num matches that on your prior call, then the controller state hasn't been changed since 59 // your last call and there is no need to process it 60 uint32 unPacketNum; 61 62 // bit flags for each of the buttons 63 uint64 ulButtons; 64 65 // Left pad coordinates 66 short sLeftPadX; 67 short sLeftPadY; 68 69 // Right pad coordinates 70 short sRightPadX; 71 short sRightPadY; 72 73 // Center pad coordinates 74 short sCenterPadX; 75 short sCenterPadY; 76 77 // Left analog stick coordinates 78 short sLeftStickX; 79 short sLeftStickY; 80 81 // Right analog stick coordinates 82 short sRightStickX; 83 short sRightStickY; 84 85 unsigned short sTriggerL; 86 unsigned short sTriggerR; 87 88 short sAccelX; 89 short sAccelY; 90 short sAccelZ; 91 92 short sGyroX; 93 short sGyroY; 94 short sGyroZ; 95 96 float sGyroQuatW; 97 float sGyroQuatX; 98 float sGyroQuatY; 99 float sGyroQuatZ; 100 101 short sGyroSteeringAngle; 102 103 unsigned short sBatteryLevel; 104 105 // Pressure sensor data. 106 unsigned short sPressurePadLeft; 107 unsigned short sPressurePadRight; 108 109 unsigned short sPressureBumperLeft; 110 unsigned short sPressureBumperRight; 111 112 // Internal state data 113 short sPrevLeftPad[2]; 114 short sPrevLeftStick[2]; 115 } SteamControllerStateInternal_t; 116 117 118 /* Defines for ulButtons in SteamControllerStateInternal_t */ 119 #define STEAM_RIGHT_TRIGGER_MASK 0x00000001 120 #define STEAM_LEFT_TRIGGER_MASK 0x00000002 121 #define STEAM_RIGHT_BUMPER_MASK 0x00000004 122 #define STEAM_LEFT_BUMPER_MASK 0x00000008 123 #define STEAM_BUTTON_0_MASK 0x00000010 /* Y */ 124 #define STEAM_BUTTON_1_MASK 0x00000020 /* B */ 125 #define STEAM_BUTTON_2_MASK 0x00000040 /* X */ 126 #define STEAM_BUTTON_3_MASK 0x00000080 /* A */ 127 #define STEAM_TOUCH_0_MASK 0x00000100 /* DPAD UP */ 128 #define STEAM_TOUCH_1_MASK 0x00000200 /* DPAD RIGHT */ 129 #define STEAM_TOUCH_2_MASK 0x00000400 /* DPAD LEFT */ 130 #define STEAM_TOUCH_3_MASK 0x00000800 /* DPAD DOWN */ 131 #define STEAM_BUTTON_MENU_MASK 0x00001000 /* SELECT */ 132 #define STEAM_BUTTON_STEAM_MASK 0x00002000 /* GUIDE */ 133 #define STEAM_BUTTON_ESCAPE_MASK 0x00004000 /* START */ 134 #define STEAM_BUTTON_BACK_LEFT_MASK 0x00008000 135 #define STEAM_BUTTON_BACK_RIGHT_MASK 0x00010000 136 #define STEAM_BUTTON_LEFTPAD_CLICKED_MASK 0x00020000 137 #define STEAM_BUTTON_RIGHTPAD_CLICKED_MASK 0x00040000 138 #define STEAM_LEFTPAD_FINGERDOWN_MASK 0x00080000 139 #define STEAM_RIGHTPAD_FINGERDOWN_MASK 0x00100000 140 #define STEAM_JOYSTICK_BUTTON_MASK 0x00400000 141 #define STEAM_LEFTPAD_AND_JOYSTICK_MASK 0x00800000 142 143 144 // Look for report version 0x0001, type WIRELESS (3), length >= 1 byte 145 #define D0G_IS_VALID_WIRELESS_EVENT(data, len) ((len) >= 5 && (data)[0] == 1 && (data)[1] == 0 && (data)[2] == 3 && (data)[3] >= 1) 146 #define D0G_GET_WIRELESS_EVENT_TYPE(data) ((data)[4]) 147 #define D0G_WIRELESS_DISCONNECTED 1 148 #define D0G_WIRELESS_ESTABLISHED 2 149 #define D0G_WIRELESS_NEWLYPAIRED 3 150 151 #define D0G_IS_WIRELESS_DISCONNECT(data, len) ( D0G_IS_VALID_WIRELESS_EVENT(data,len) && D0G_GET_WIRELESS_EVENT_TYPE(data) == D0G_WIRELESS_DISCONNECTED ) 152 153 #define MAX_REPORT_SEGMENT_PAYLOAD_SIZE 18 154 /* 155 * SteamControllerPacketAssembler has to be used when reading output repots from controllers. 156 */ 157 typedef struct 158 { 159 uint8_t uBuffer[ MAX_REPORT_SEGMENT_PAYLOAD_SIZE * 8 + 1 ]; 160 int nExpectedSegmentNumber; 161 bool bIsBle; 162 } SteamControllerPacketAssembler; 163 164 165 #undef clamp 166 #define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val))) 167 168 #undef offsetof 169 #define offsetof(s,m) (size_t)&(((s *)0)->m) 170 171 #ifdef DEBUG_STEAM_CONTROLLER 172 #define DPRINTF(format, ...) printf(format, ##__VA_ARGS__) 173 #define HEXDUMP(ptr, len) hexdump(ptr, len) 174 #else 175 #define DPRINTF(format, ...) 176 #define HEXDUMP(ptr, len) 177 #endif 178 #define printf SDL_Log 179 180 #define MAX_REPORT_SEGMENT_SIZE ( MAX_REPORT_SEGMENT_PAYLOAD_SIZE + 2 ) 181 #define CALC_REPORT_SEGMENT_NUM(index) ( ( index / MAX_REPORT_SEGMENT_PAYLOAD_SIZE ) & 0x07 ) 182 #define REPORT_SEGMENT_DATA_FLAG 0x80 183 #define REPORT_SEGMENT_LAST_FLAG 0x40 184 #define BLE_REPORT_NUMBER 0x03 185 186 #define STEAMCONTROLLER_TRIGGER_MAX_ANALOG 26000 187 188 // Enable mouse mode when using the Steam Controller locally 189 #undef ENABLE_MOUSE_MODE 190 191 192 // Wireless firmware quirk: the firmware intentionally signals "failure" when performing 193 // SET_FEATURE / GET_FEATURE when it actually means "pending radio round-trip". The only 194 // way to make SET_FEATURE / GET_FEATURE work is to loop several times with a sleep. If 195 // it takes more than 50ms to get the response for SET_FEATURE / GET_FEATURE, we assume 196 // that the controller has failed. 197 #define RADIO_WORKAROUND_SLEEP_ATTEMPTS 50 198 #define RADIO_WORKAROUND_SLEEP_DURATION_US 500 199 200 // This was defined by experimentation. 2000 seemed to work but to give that extra bit of margin, set to 3ms. 201 #define CONTROLLER_CONFIGURATION_DELAY_US 3000 202 203 static uint8_t GetSegmentHeader( int nSegmentNumber, bool bLastPacket ) 204 { 205 uint8_t header = REPORT_SEGMENT_DATA_FLAG; 206 header |= nSegmentNumber; 207 if ( bLastPacket ) 208 header |= REPORT_SEGMENT_LAST_FLAG; 209 210 return header; 211 } 212 213 static void hexdump( const uint8_t *ptr, int len ) 214 { 215 int i; 216 for ( i = 0; i < len ; ++i ) 217 printf("%02x ", ptr[i]); 218 printf("\n"); 219 } 220 221 static void ResetSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler ) 222 { 223 memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) ); 224 pAssembler->nExpectedSegmentNumber = 0; 225 } 226 227 static void InitializeSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler ) 228 { 229 /* We only support BLE devices right now */ 230 pAssembler->bIsBle = true; 231 ResetSteamControllerPacketAssembler( pAssembler ); 232 } 233 234 // Returns: 235 // <0 on error 236 // 0 on not ready 237 // Complete packet size on completion 238 static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler, const uint8_t *pSegment, int nSegmentLength ) 239 { 240 if ( pAssembler->bIsBle ) 241 { 242 HEXDUMP( pSegment, nSegmentLength ); 243 244 if ( pSegment[ 0 ] != BLE_REPORT_NUMBER ) 245 { 246 // We may get keyboard/mouse input events until controller stops sending them 247 return 0; 248 } 249 250 if ( nSegmentLength != MAX_REPORT_SEGMENT_SIZE ) 251 { 252 printf( "Bad segment size! %d\n", (int)nSegmentLength ); 253 hexdump( pSegment, nSegmentLength ); 254 ResetSteamControllerPacketAssembler( pAssembler ); 255 return -1; 256 } 257 258 uint8_t uSegmentHeader = pSegment[ 1 ]; 259 DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader); 260 261 if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 ) 262 { 263 // We get empty segments, just ignore them 264 return 0; 265 } 266 267 int nSegmentNumber = uSegmentHeader & 0x07; 268 if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber ) 269 { 270 ResetSteamControllerPacketAssembler( pAssembler ); 271 272 if ( nSegmentNumber ) 273 { 274 // This happens occasionally 275 DPRINTF("Bad segment number, got %d, expected %d\n", 276 nSegmentNumber, pAssembler->nExpectedSegmentNumber ); 277 return -1; 278 } 279 } 280 281 memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE, 282 pSegment + 2, // ignore header and report number 283 MAX_REPORT_SEGMENT_PAYLOAD_SIZE ); 284 285 if ( uSegmentHeader & REPORT_SEGMENT_LAST_FLAG ) 286 { 287 pAssembler->nExpectedSegmentNumber = 0; 288 return ( nSegmentNumber + 1 ) * MAX_REPORT_SEGMENT_PAYLOAD_SIZE; 289 } 290 291 pAssembler->nExpectedSegmentNumber++; 292 } 293 else 294 { 295 // Just pass through 296 memcpy( pAssembler->uBuffer, 297 pSegment, 298 nSegmentLength ); 299 return nSegmentLength; 300 } 301 302 return 0; 303 } 304 305 #define BLE_MAX_READ_RETRIES 8 306 307 static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nActualDataLen ) 308 { 309 DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen); 310 int nRet = -1; 311 bool bBle = true; // only wireless/BLE for now, though macOS could do wired in the future 312 313 if ( bBle ) 314 { 315 if ( nActualDataLen < 1 ) 316 return -1; 317 318 int nSegmentNumber = 0; 319 uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ]; 320 321 // Skip report number in data 322 unsigned char *pBufferPtr = uBuffer + 1; 323 nActualDataLen--; 324 325 while ( nActualDataLen > 0 ) 326 { 327 int nBytesInPacket = nActualDataLen > MAX_REPORT_SEGMENT_PAYLOAD_SIZE ? MAX_REPORT_SEGMENT_PAYLOAD_SIZE : nActualDataLen; 328 329 nActualDataLen -= nBytesInPacket; 330 331 // Construct packet 332 memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) ); 333 uPacketBuffer[ 0 ] = BLE_REPORT_NUMBER; 334 uPacketBuffer[ 1 ] = GetSegmentHeader( nSegmentNumber, nActualDataLen == 0 ); 335 memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket ); 336 337 pBufferPtr += nBytesInPacket; 338 nSegmentNumber++; 339 340 nRet = hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) ); 341 DPRINTF("SetFeatureReport() ret = %d\n", nRet); 342 } 343 } 344 345 return nRet; 346 } 347 348 static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] ) 349 { 350 DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer ); 351 int nRet = -1; 352 bool bBle = true; 353 354 if ( bBle ) 355 { 356 SteamControllerPacketAssembler assembler; 357 InitializeSteamControllerPacketAssembler( &assembler ); 358 359 int nRetries = 0; 360 uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ]; 361 while( nRetries < BLE_MAX_READ_RETRIES ) 362 { 363 memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) ); 364 uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER; 365 nRet = hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) ); 366 DPRINTF( "GetFeatureReport ble ret=%d\n", nRet ); 367 HEXDUMP( uSegmentBuffer, nRet ); 368 369 // Zero retry counter if we got data 370 if ( nRet > 2 && ( uSegmentBuffer[ 1 ] & REPORT_SEGMENT_DATA_FLAG ) ) 371 nRetries = 0; 372 else 373 nRetries++; 374 375 if ( nRet > 0 ) 376 { 377 int nPacketLength = WriteSegmentToSteamControllerPacketAssembler( &assembler, 378 uSegmentBuffer, 379 nRet ); 380 381 if ( nPacketLength > 0 && nPacketLength < 65 ) 382 { 383 // Leave space for "report number" 384 uBuffer[ 0 ] = 0; 385 memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength ); 386 return nPacketLength; 387 } 388 } 389 390 391 } 392 printf("Could not get a full ble packet after %d retries\n", nRetries ); 393 return -1; 394 } 395 396 return nRet; 397 } 398 399 static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse ) 400 { 401 DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse ); 402 int nRet = GetFeatureReport( dev, uBuffer ); 403 404 if ( nRet < 0 ) 405 return nRet; 406 407 DPRINTF("ReadResponse got %d bytes of data: ", nRet ); 408 HEXDUMP( uBuffer, nRet ); 409 410 if ( uBuffer[1] != nExpectedResponse ) 411 return -1; 412 413 return nRet; 414 } 415 416 //--------------------------------------------------------------------------- 417 // Reset steam controller (unmap buttons and pads) and re-fetch capability bits 418 //--------------------------------------------------------------------------- 419 static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew ) 420 { 421 DPRINTF( "ResetSteamController hid=%p\n", dev ); 422 // Firmware quirk: Set Feature and Get Feature requests always require a 65-byte buffer. 423 unsigned char buf[65]; 424 int res = -1; 425 426 buf[0] = 0; 427 buf[1] = ID_GET_ATTRIBUTES_VALUES; 428 res = SetFeatureReport( dev, buf, 2 ); 429 if ( res < 0 ) 430 { 431 if ( !bSuppressErrorSpew ) 432 printf( "GET_ATTRIBUTES_VALUES failed for controller %p\n", dev ); 433 return false; 434 } 435 436 // Retrieve GET_ATTRIBUTES_VALUES result 437 // Wireless controller endpoints without a connected controller will return nAttrs == 0 438 res = ReadResponse( dev, buf, ID_GET_ATTRIBUTES_VALUES ); 439 if ( res < 0 || buf[1] != ID_GET_ATTRIBUTES_VALUES ) 440 { 441 HEXDUMP(buf, res); 442 if ( !bSuppressErrorSpew ) 443 printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev ); 444 return false; 445 } 446 447 int nAttributesLength = buf[ 2 ]; 448 if ( nAttributesLength > res ) 449 { 450 if ( !bSuppressErrorSpew ) 451 printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev ); 452 return false; 453 } 454 455 // Clear digital button mappings 456 buf[0] = 0; 457 buf[1] = ID_CLEAR_DIGITAL_MAPPINGS; 458 res = SetFeatureReport( dev, buf, 2 ); 459 if ( res < 0 ) 460 { 461 if ( !bSuppressErrorSpew ) 462 printf( "CLEAR_DIGITAL_MAPPINGS failed for controller %p\n", dev ); 463 return false; 464 } 465 466 // Reset the default settings 467 memset( buf, 0, 65 ); 468 buf[1] = ID_LOAD_DEFAULT_SETTINGS; 469 buf[2] = 0; 470 res = SetFeatureReport( dev, buf, 3 ); 471 if ( res < 0 ) 472 { 473 if ( !bSuppressErrorSpew ) 474 printf( "LOAD_DEFAULT_SETTINGS failed for controller %p\n", dev ); 475 return false; 476 } 477 478 // Apply custom settings - clear trackpad modes (cancel mouse emulation), etc 479 int nSettings = 0; 480 #define ADD_SETTING(SETTING, VALUE) \ 481 buf[3+nSettings*3] = SETTING; \ 482 buf[3+nSettings*3+1] = ((uint16_t)VALUE)&0xFF; \ 483 buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \ 484 ++nSettings; 485 486 memset( buf, 0, 65 ); 487 buf[1] = ID_SET_SETTINGS_VALUES; 488 ADD_SETTING( SETTING_WIRELESS_PACKET_VERSION, 2 ); 489 ADD_SETTING( SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE ); 490 #ifdef ENABLE_MOUSE_MODE 491 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE ); 492 ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 1 ); 493 ADD_SETTING( SETTING_MOMENTUM_MAXIMUM_VELOCITY, 20000 ); // [0-20000] default 8000 494 ADD_SETTING( SETTING_MOMENTUM_DECAY_AMMOUNT, 50 ); // [0-50] default 5 495 #else 496 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE ); 497 ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 0 ); 498 #endif 499 buf[2] = nSettings*3; 500 501 res = SetFeatureReport( dev, buf, 3+nSettings*3 ); 502 if ( res < 0 ) 503 { 504 if ( !bSuppressErrorSpew ) 505 printf( "SET_SETTINGS failed for controller %p\n", dev ); 506 return false; 507 } 508 509 #ifdef ENABLE_MOUSE_MODE 510 // Wait for ID_CLEAR_DIGITAL_MAPPINGS to be processed on the controller 511 bool bMappingsCleared = false; 512 int iRetry; 513 for ( iRetry = 0; iRetry < 2; ++iRetry ) 514 { 515 memset( buf, 0, 65 ); 516 buf[1] = ID_GET_DIGITAL_MAPPINGS; 517 buf[2] = 1; // one byte - requesting from index 0 518 buf[3] = 0; 519 res = SetFeatureReport( dev, buf, 4 ); 520 if ( res < 0 ) 521 { 522 printf( "GET_DIGITAL_MAPPINGS failed for controller %p\n", dev ); 523 return false; 524 } 525 526 res = ReadResponse( dev, buf, ID_GET_DIGITAL_MAPPINGS ); 527 if ( res < 0 || buf[1] != ID_GET_DIGITAL_MAPPINGS ) 528 { 529 printf( "Bad GET_DIGITAL_MAPPINGS response for controller %p\n", dev ); 530 return false; 531 } 532 533 // If the length of the digital mappings result is not 1 (index byte, no mappings) then clearing hasn't executed 534 if ( buf[2] == 1 && buf[3] == 0xFF ) 535 { 536 bMappingsCleared = true; 537 break; 538 } 539 usleep( CONTROLLER_CONFIGURATION_DELAY_US ); 540 } 541 542 if ( !bMappingsCleared && !bSuppressErrorSpew ) 543 { 544 printf( "Warning: CLEAR_DIGITAL_MAPPINGS never completed for controller %p\n", dev ); 545 } 546 547 // Set our new mappings 548 memset( buf, 0, 65 ); 549 buf[1] = ID_SET_DIGITAL_MAPPINGS; 550 buf[2] = 6; // 2 settings x 3 bytes 551 buf[3] = IO_DIGITAL_BUTTON_RIGHT_TRIGGER; 552 buf[4] = DEVICE_MOUSE; 553 buf[5] = MOUSE_BTN_LEFT; 554 buf[6] = IO_DIGITAL_BUTTON_LEFT_TRIGGER; 555 buf[7] = DEVICE_MOUSE; 556 buf[8] = MOUSE_BTN_RIGHT; 557 558 res = SetFeatureReport( dev, buf, 9 ); 559 if ( res < 0 ) 560 { 561 if ( !bSuppressErrorSpew ) 562 printf( "SET_DIGITAL_MAPPINGS failed for controller %p\n", dev ); 563 return false; 564 } 565 #endif // ENABLE_MOUSE_MODE 566 567 return true; 568 } 569 570 571 //--------------------------------------------------------------------------- 572 // Read from a Steam Controller 573 //--------------------------------------------------------------------------- 574 static int ReadSteamController( hid_device *dev, uint8_t *pData, int nDataSize ) 575 { 576 memset( pData, 0, nDataSize ); 577 pData[ 0 ] = BLE_REPORT_NUMBER; // hid_read will also overwrite this with the same value, 0x03 578 return hid_read( dev, pData, nDataSize ); 579 } 580 581 582 //--------------------------------------------------------------------------- 583 // Close a Steam Controller 584 //--------------------------------------------------------------------------- 585 static void CloseSteamController( hid_device *dev ) 586 { 587 // Switch the Steam Controller back to lizard mode so it works with the OS 588 unsigned char buf[65]; 589 int nSettings = 0; 590 591 // Reset digital button mappings 592 memset( buf, 0, 65 ); 593 buf[1] = ID_SET_DEFAULT_DIGITAL_MAPPINGS; 594 SetFeatureReport( dev, buf, 2 ); 595 596 // Reset the default settings 597 memset( buf, 0, 65 ); 598 buf[1] = ID_LOAD_DEFAULT_SETTINGS; 599 buf[2] = 0; 600 SetFeatureReport( dev, buf, 3 ); 601 602 // Reset mouse mode for lizard mode 603 memset( buf, 0, 65 ); 604 buf[1] = ID_SET_SETTINGS_VALUES; 605 ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE ); 606 buf[2] = nSettings*3; 607 SetFeatureReport( dev, buf, 3+nSettings*3 ); 608 } 609 610 611 //--------------------------------------------------------------------------- 612 // Scale and clamp values to a range 613 //--------------------------------------------------------------------------- 614 static float RemapValClamped( float val, float A, float B, float C, float D) 615 { 616 if ( A == B ) 617 { 618 return ( val - B ) >= 0.0f ? D : C; 619 } 620 else 621 { 622 float cVal = (val - A) / (B - A); 623 cVal = clamp( cVal, 0.0f, 1.0f ); 624 625 return C + (D - C) * cVal; 626 } 627 } 628 629 630 //--------------------------------------------------------------------------- 631 // Rotate the pad coordinates 632 //--------------------------------------------------------------------------- 633 static void RotatePad( int *pX, int *pY, float flAngleInRad ) 634 { 635 short int origX = *pX, origY = *pY; 636 637 *pX = (int)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY ); 638 *pY = (int)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY ); 639 } 640 static void RotatePadShort( short *pX, short *pY, float flAngleInRad ) 641 { 642 short int origX = *pX, origY = *pY; 643 644 *pX = (short)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY ); 645 *pY = (short)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY ); 646 } 647 648 649 //--------------------------------------------------------------------------- 650 // Format the first part of the state packet 651 //--------------------------------------------------------------------------- 652 static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState, ValveControllerStatePacket_t *pStatePacket ) 653 { 654 memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel)); 655 656 //pState->eControllerType = m_eControllerType; 657 pState->eControllerType = 2; // k_eControllerType_SteamController; 658 pState->unPacketNum = pStatePacket->unPacketNum; 659 660 // We have a chunk of trigger data in the packet format here, so zero it out afterwards 661 memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8); 662 pState->ulButtons &= ~0xFFFF000000LL; 663 664 // The firmware uses this bit to tell us what kind of data is packed into the left two axises 665 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK) 666 { 667 // Finger-down bit not set; "left pad" is actually trackpad 668 pState->sLeftPadX = pState->sPrevLeftPad[0] = pStatePacket->sLeftPadX; 669 pState->sLeftPadY = pState->sPrevLeftPad[1] = pStatePacket->sLeftPadY; 670 671 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) 672 { 673 // The controller is interleaving both stick and pad data, both are active 674 pState->sLeftStickX = pState->sPrevLeftStick[0]; 675 pState->sLeftStickY = pState->sPrevLeftStick[1]; 676 } 677 else 678 { 679 // The stick is not active 680 pState->sPrevLeftStick[0] = 0; 681 pState->sPrevLeftStick[1] = 0; 682 } 683 } 684 else 685 { 686 // Finger-down bit not set; "left pad" is actually joystick 687 688 // XXX there's a firmware bug where sometimes padX is 0 and padY is a large number (acutally the battery voltage) 689 // If that happens skip this packet and report last frames stick 690 /* 691 if ( m_eControllerType == k_eControllerType_SteamControllerV2 && pStatePacket->sLeftPadY > 900 ) 692 { 693 pState->sLeftStickX = pState->sPrevLeftStick[0]; 694 pState->sLeftStickY = pState->sPrevLeftStick[1]; 695 } 696 else 697 */ 698 { 699 pState->sPrevLeftStick[0] = pState->sLeftStickX = pStatePacket->sLeftPadX; 700 pState->sPrevLeftStick[1] = pState->sLeftStickY = pStatePacket->sLeftPadY; 701 } 702 /* 703 if (m_eControllerType == k_eControllerType_SteamControllerV2) 704 { 705 UpdateV2JoystickCap(&state); 706 } 707 */ 708 709 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) 710 { 711 // The controller is interleaving both stick and pad data, both are active 712 pState->sLeftPadX = pState->sPrevLeftPad[0]; 713 pState->sLeftPadY = pState->sPrevLeftPad[1]; 714 } 715 else 716 { 717 // The trackpad is not active 718 pState->sPrevLeftPad[0] = 0; 719 pState->sPrevLeftPad[1] = 0; 720 721 // Old controllers send trackpad click for joystick button when trackpad is not active 722 if (pState->ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK) 723 { 724 pState->ulButtons &= ~STEAM_BUTTON_LEFTPAD_CLICKED_MASK; 725 pState->ulButtons |= STEAM_JOYSTICK_BUTTON_MASK; 726 } 727 } 728 } 729 730 // Fingerdown bit indicates if the packed left axis data was joystick or pad, 731 // but if we are interleaving both, the left finger is definitely on the pad. 732 if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK) 733 pState->ulButtons |= STEAM_LEFTPAD_FINGERDOWN_MASK; 734 735 pState->sRightPadX = pStatePacket->sRightPadX; 736 pState->sRightPadY = pStatePacket->sRightPadY; 737 738 int nLeftPadX = pState->sLeftPadX; 739 int nLeftPadY = pState->sLeftPadY; 740 int nRightPadX = pState->sRightPadX; 741 int nRightPadY = pState->sRightPadY; 742 743 // 15 degrees in rad 744 const float flRotationAngle = 0.261799f; 745 746 RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle); 747 RotatePad(&nRightPadX, &nRightPadY, flRotationAngle); 748 749 int nPadOffset; 750 if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK) 751 nPadOffset = 1000; 752 else 753 nPadOffset = 0; 754 755 pState->sLeftPadX = clamp(nLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); 756 pState->sLeftPadY = clamp(nLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); 757 758 nPadOffset = 0; 759 if (pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK) 760 nPadOffset = 1000; 761 else 762 nPadOffset = 0; 763 764 pState->sRightPadX = clamp(nRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); 765 pState->sRightPadY = clamp(nRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16); 766 767 pState->sTriggerL = (unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nLeft << 7) | pStatePacket->ButtonTriggerData.Triggers.nLeft, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 ); 768 pState->sTriggerR = (unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nRight << 7) | pStatePacket->ButtonTriggerData.Triggers.nRight, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 ); 769 } 770 771 772 //--------------------------------------------------------------------------- 773 // Update Steam Controller state from a BLE data packet, returns true if it parsed data 774 //--------------------------------------------------------------------------- 775 static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize, SteamControllerStateInternal_t *pState ) 776 { 777 const float flRotationAngle = 0.261799f; 778 uint32_t ucOptionDataMask; 779 780 pState->unPacketNum++; 781 ucOptionDataMask = ( *pData++ & 0xF0 ); 782 ucOptionDataMask |= (uint32_t)(*pData++) << 8; 783 if ( ucOptionDataMask & k_EBLEButtonChunk1 ) 784 { 785 memcpy( &pState->ulButtons, pData, 3 ); 786 pData += 3; 787 } 788 if ( ucOptionDataMask & k_EBLEButtonChunk2 ) 789 { 790 // 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 791 pState->sTriggerL = (unsigned short)RemapValClamped( ( pData[ 0 ] << 7 ) | pData[ 0 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 ); 792 pState->sTriggerR = (unsigned short)RemapValClamped( ( pData[ 1 ] << 7 ) | pData[ 1 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 ); 793 pData += 2; 794 } 795 if ( ucOptionDataMask & k_EBLEButtonChunk3 ) 796 { 797 uint8_t *pButtonByte = (uint8_t *)&pState->ulButtons; 798 pButtonByte[ 5 ] = *pData++; 799 pButtonByte[ 6 ] = *pData++; 800 pButtonByte[ 7 ] = *pData++; 801 } 802 if ( ucOptionDataMask & k_EBLELeftJoystickChunk ) 803 { 804 // This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support 805 // this protocol yet either 806 int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY ); 807 memcpy( &pState->sLeftStickX, pData, nLength ); 808 pData += nLength; 809 } 810 if ( ucOptionDataMask & k_EBLELeftTrackpadChunk ) 811 { 812 int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY ); 813 int nPadOffset; 814 memcpy( &pState->sLeftPadX, pData, nLength ); 815 if ( pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK ) 816 nPadOffset = 1000; 817 else 818 nPadOffset = 0; 819 820 RotatePadShort( &pState->sLeftPadX, &pState->sLeftPadY, -flRotationAngle ); 821 pState->sLeftPadX = clamp( pState->sLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 ); 822 pState->sLeftPadY = clamp( pState->sLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 ); 823 pData += nLength; 824 } 825 if ( ucOptionDataMask & k_EBLERightTrackpadChunk ) 826 { 827 int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY ); 828 int nPadOffset = 0; 829 830 memcpy( &pState->sRightPadX, pData, nLength ); 831 832 if ( pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK ) 833 nPadOffset = 1000; 834 else 835 nPadOffset = 0; 836 837 RotatePadShort( &pState->sRightPadX, &pState->sRightPadY, flRotationAngle ); 838 pState->sRightPadX = clamp( pState->sRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 ); 839 pState->sRightPadY = clamp( pState->sRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 ); 840 pData += nLength; 841 } 842 if ( ucOptionDataMask & k_EBLEIMUAccelChunk ) 843 { 844 int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ ); 845 memcpy( &pState->sAccelX, pData, nLength ); 846 pData += nLength; 847 } 848 if ( ucOptionDataMask & k_EBLEIMUGyroChunk ) 849 { 850 int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ ); 851 memcpy( &pState->sGyroX, pData, nLength ); 852 pData += nLength; 853 } 854 if ( ucOptionDataMask & k_EBLEIMUQuatChunk ) 855 { 856 int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ ); 857 memcpy( &pState->sGyroQuatW, pData, nLength ); 858 pData += nLength; 859 } 860 return true; 861 } 862 863 864 //--------------------------------------------------------------------------- 865 // Update Steam Controller state from a data packet, returns true if it parsed data 866 //--------------------------------------------------------------------------- 867 static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, SteamControllerStateInternal_t *pState ) 868 { 869 ValveInReport_t *pInReport = (ValveInReport_t*)pData; 870 871 if ( pInReport->header.unReportVersion != k_ValveInReportMsgVersion ) 872 { 873 if ( ( pData[ 0 ] & 0x0F ) == k_EBLEReportState ) 874 { 875 return UpdateBLESteamControllerState( pData, nDataSize, pState ); 876 } 877 return false; 878 } 879 880 if ( ( pInReport->header.ucType != ID_CONTROLLER_STATE ) && 881 ( pInReport->header.ucType != ID_CONTROLLER_BLE_STATE ) ) 882 { 883 return false; 884 } 885 886 if ( pInReport->header.ucType == ID_CONTROLLER_STATE ) 887 { 888 ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState; 889 890 // No new data to process; indicate that we received a state packet, but otherwise do nothing. 891 if ( pState->unPacketNum == pStatePacket->unPacketNum ) 892 return true; 893 894 FormatStatePacketUntilGyro( pState, pStatePacket ); 895 896 pState->sAccelX = pStatePacket->sAccelX; 897 pState->sAccelY = pStatePacket->sAccelY; 898 pState->sAccelZ = pStatePacket->sAccelZ; 899 900 pState->sGyroQuatW = pStatePacket->sGyroQuatW; 901 pState->sGyroQuatX = pStatePacket->sGyroQuatX; 902 pState->sGyroQuatY = pStatePacket->sGyroQuatY; 903 pState->sGyroQuatZ = pStatePacket->sGyroQuatZ; 904 905 pState->sGyroX = pStatePacket->sGyroX; 906 pState->sGyroY = pStatePacket->sGyroY; 907 pState->sGyroZ = pStatePacket->sGyroZ; 908 909 } 910 else if ( pInReport->header.ucType == ID_CONTROLLER_BLE_STATE ) 911 { 912 ValveControllerBLEStatePacket_t *pBLEStatePacket = &pInReport->payload.controllerBLEState; 913 ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState; 914 915 // No new data to process; indicate that we received a state packet, but otherwise do nothing. 916 if ( pState->unPacketNum == pStatePacket->unPacketNum ) 917 return true; 918 919 FormatStatePacketUntilGyro( pState, pStatePacket ); 920 921 switch ( pBLEStatePacket->ucGyroDataType ) 922 { 923 case 1: 924 pState->sGyroQuatW = (( float ) pBLEStatePacket->sGyro[0]); 925 pState->sGyroQuatX = (( float ) pBLEStatePacket->sGyro[1]); 926 pState->sGyroQuatY = (( float ) pBLEStatePacket->sGyro[2]); 927 pState->sGyroQuatZ = (( float ) pBLEStatePacket->sGyro[3]); 928 break; 929 930 case 2: 931 pState->sAccelX = pBLEStatePacket->sGyro[0]; 932 pState->sAccelY = pBLEStatePacket->sGyro[1]; 933 pState->sAccelZ = pBLEStatePacket->sGyro[2]; 934 break; 935 936 case 3: 937 pState->sGyroX = pBLEStatePacket->sGyro[0]; 938 pState->sGyroY = pBLEStatePacket->sGyro[1]; 939 pState->sGyroZ = pBLEStatePacket->sGyro[2]; 940 break; 941 942 default: 943 break; 944 } 945 } 946 947 return true; 948 } 949 950 /*****************************************************************************************************/ 951 952 typedef struct { 953 SteamControllerPacketAssembler m_assembler; 954 SteamControllerStateInternal_t m_state; 955 SteamControllerStateInternal_t m_last_state; 956 } SDL_DriverSteam_Context; 957 958 959 static SDL_bool 960 HIDAPI_DriverSteam_IsSupportedDevice(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) 961 { 962 return SDL_IsJoystickSteamController(vendor_id, product_id); 963 } 964 965 static const char * 966 HIDAPI_DriverSteam_GetDeviceName(Uint16 vendor_id, Uint16 product_id) 967 { 968 return "Steam Controller"; 969 } 970 971 static SDL_bool 972 HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device) 973 { 974 return HIDAPI_JoystickConnected(device, NULL); 975 } 976 977 static int 978 HIDAPI_DriverSteam_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) 979 { 980 return -1; 981 } 982 983 static void 984 HIDAPI_DriverSteam_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) 985 { 986 } 987 988 static SDL_bool 989 HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 990 { 991 SDL_DriverSteam_Context *ctx; 992 993 ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx)); 994 if (!ctx) { 995 SDL_OutOfMemory(); 996 goto error; 997 } 998 device->context = ctx; 999 1000 device->dev = hid_open_path(device->path, 0); 1001 if (!device->dev) { 1002 SDL_SetError("Couldn't open %s", device->path); 1003 goto error; 1004 } 1005 1006 if (!ResetSteamController(device->dev, false)) { 1007 goto error; 1008 } 1009 1010 InitializeSteamControllerPacketAssembler(&ctx->m_assembler); 1011 1012 /* Initialize the joystick capabilities */ 1013 joystick->nbuttons = 17; 1014 joystick->naxes = SDL_CONTROLLER_AXIS_MAX; 1015 1016 return SDL_TRUE; 1017 1018 error: 1019 if (device->dev) { 1020 hid_close(device->dev); 1021 device->dev = NULL; 1022 } 1023 if (device->context) { 1024 SDL_free(device->context); 1025 device->context = NULL; 1026 } 1027 return SDL_FALSE; 1028 } 1029 1030 static int 1031 HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 1032 { 1033 /* You should use the full Steam Input API for rumble support */ 1034 return SDL_Unsupported(); 1035 } 1036 1037 static int 1038 HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) 1039 { 1040 return SDL_Unsupported(); 1041 } 1042 1043 static SDL_bool 1044 HIDAPI_DriverSteam_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1045 { 1046 /* You should use the full Steam Input API for LED support */ 1047 return SDL_FALSE; 1048 } 1049 1050 static int 1051 HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) 1052 { 1053 /* You should use the full Steam Input API for LED support */ 1054 return SDL_Unsupported(); 1055 } 1056 1057 static int 1058 HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled) 1059 { 1060 /* You should use the full Steam Input API for sensor support */ 1061 return SDL_Unsupported(); 1062 } 1063 1064 static SDL_bool 1065 HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) 1066 { 1067 SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context; 1068 SDL_Joystick *joystick = NULL; 1069 1070 if (device->num_joysticks > 0) { 1071 joystick = SDL_JoystickFromInstanceID(device->joysticks[0]); 1072 } 1073 if (!joystick) { 1074 return SDL_FALSE; 1075 } 1076 1077 for (;;) 1078 { 1079 uint8_t data[128]; 1080 int r, nPacketLength; 1081 const Uint8 *pPacket; 1082 1083 r = ReadSteamController(device->dev, data, sizeof(data)); 1084 if (r == 0) 1085 { 1086 break; 1087 } 1088 1089 nPacketLength = 0; 1090 if (r > 0) { 1091 nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&ctx->m_assembler, data, r); 1092 } 1093 1094 pPacket = ctx->m_assembler.uBuffer; 1095 1096 if (nPacketLength > 0 && UpdateSteamControllerState(pPacket, nPacketLength, &ctx->m_state)) { 1097 if (ctx->m_state.ulButtons != ctx->m_last_state.ulButtons) { 1098 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, 1099 (ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED); 1100 1101 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, 1102 (ctx->m_state.ulButtons & STEAM_BUTTON_1_MASK) ? SDL_PRESSED : SDL_RELEASED); 1103 1104 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, 1105 (ctx->m_state.ulButtons & STEAM_BUTTON_2_MASK) ? SDL_PRESSED : SDL_RELEASED); 1106 1107 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, 1108 (ctx->m_state.ulButtons & STEAM_BUTTON_0_MASK) ? SDL_PRESSED : SDL_RELEASED); 1109 1110 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 1111 (ctx->m_state.ulButtons & STEAM_LEFT_BUMPER_MASK) ? SDL_PRESSED : SDL_RELEASED); 1112 1113 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 1114 (ctx->m_state.ulButtons & STEAM_RIGHT_BUMPER_MASK) ? SDL_PRESSED : SDL_RELEASED); 1115 1116 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, 1117 (ctx->m_state.ulButtons & STEAM_BUTTON_MENU_MASK) ? SDL_PRESSED : SDL_RELEASED); 1118 1119 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, 1120 (ctx->m_state.ulButtons & STEAM_BUTTON_ESCAPE_MASK) ? SDL_PRESSED : SDL_RELEASED); 1121 1122 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, 1123 (ctx->m_state.ulButtons & STEAM_BUTTON_STEAM_MASK) ? SDL_PRESSED : SDL_RELEASED); 1124 1125 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, 1126 (ctx->m_state.ulButtons & STEAM_JOYSTICK_BUTTON_MASK) ? SDL_PRESSED : SDL_RELEASED); 1127 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 0, 1128 (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED); 1129 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 1, 1130 (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED); 1131 } 1132 { 1133 /* Minimum distance from center of pad to register a direction */ 1134 const int kPadDeadZone = 10000; 1135 1136 /* Pad coordinates are like math grid coordinates: negative is bottom left */ 1137 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, 1138 (ctx->m_state.sLeftPadY > kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED); 1139 1140 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, 1141 (ctx->m_state.sLeftPadY < -kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED); 1142 1143 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 1144 (ctx->m_state.sLeftPadX < -kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED); 1145 1146 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 1147 (ctx->m_state.sLeftPadX > kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED); 1148 } 1149 1150 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, (int)ctx->m_state.sTriggerL * 2 - 32768); 1151 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, (int)ctx->m_state.sTriggerR * 2 - 32768); 1152 1153 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, ctx->m_state.sLeftStickX); 1154 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~ctx->m_state.sLeftStickY); 1155 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, ctx->m_state.sRightPadX); 1156 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~ctx->m_state.sRightPadY); 1157 1158 ctx->m_last_state = ctx->m_state; 1159 } 1160 1161 if (r <= 0) { 1162 /* Failed to read from controller */ 1163 HIDAPI_JoystickDisconnected(device, device->joysticks[0]); 1164 return SDL_FALSE; 1165 } 1166 } 1167 return SDL_TRUE; 1168 } 1169 1170 static void 1171 HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) 1172 { 1173 CloseSteamController(device->dev); 1174 hid_close(device->dev); 1175 device->dev = NULL; 1176 1177 SDL_free(device->context); 1178 device->context = NULL; 1179 } 1180 1181 static void 1182 HIDAPI_DriverSteam_FreeDevice(SDL_HIDAPI_Device *device) 1183 { 1184 } 1185 1186 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam = 1187 { 1188 SDL_HINT_JOYSTICK_HIDAPI_STEAM, 1189 SDL_TRUE, 1190 HIDAPI_DriverSteam_IsSupportedDevice, 1191 HIDAPI_DriverSteam_GetDeviceName, 1192 HIDAPI_DriverSteam_InitDevice, 1193 HIDAPI_DriverSteam_GetDevicePlayerIndex, 1194 HIDAPI_DriverSteam_SetDevicePlayerIndex, 1195 HIDAPI_DriverSteam_UpdateDevice, 1196 HIDAPI_DriverSteam_OpenJoystick, 1197 HIDAPI_DriverSteam_RumbleJoystick, 1198 HIDAPI_DriverSteam_RumbleJoystickTriggers, 1199 HIDAPI_DriverSteam_HasJoystickLED, 1200 HIDAPI_DriverSteam_SetJoystickLED, 1201 HIDAPI_DriverSteam_SetSensorsEnabled, 1202 HIDAPI_DriverSteam_CloseJoystick, 1203 HIDAPI_DriverSteam_FreeDevice, 1204 }; 1205 1206 #endif /* SDL_JOYSTICK_HIDAPI_STEAM */ 1207 1208 #endif /* SDL_JOYSTICK_HIDAPI */ 1209 1210 /* vi: set ts=4 sw=4 expandtab: */