sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

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: */