1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2021 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 roundtrip". 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 
GetSegmentHeader(int nSegmentNumber,bool bLastPacket)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 
hexdump(const uint8_t * ptr,int len)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 
ResetSteamControllerPacketAssembler(SteamControllerPacketAssembler * pAssembler)221 static void ResetSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler )
222 {
223     SDL_memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) );
224     pAssembler->nExpectedSegmentNumber = 0;
225 }
226 
InitializeSteamControllerPacketAssembler(SteamControllerPacketAssembler * pAssembler)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
WriteSegmentToSteamControllerPacketAssembler(SteamControllerPacketAssembler * pAssembler,const uint8_t * pSegment,int nSegmentLength)238 static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler, const uint8_t *pSegment, int nSegmentLength )
239 {
240     if ( pAssembler->bIsBle )
241     {
242         uint8_t uSegmentHeader = pSegment[ 1 ];
243         int nSegmentNumber = uSegmentHeader & 0x07;
244 
245         HEXDUMP( pSegment, nSegmentLength );
246 
247         if ( pSegment[ 0 ] != BLE_REPORT_NUMBER )
248         {
249             // We may get keyboard/mouse input events until controller stops sending them
250             return 0;
251         }
252 
253         if ( nSegmentLength != MAX_REPORT_SEGMENT_SIZE )
254         {
255             printf( "Bad segment size! %d\n", (int)nSegmentLength );
256             hexdump( pSegment, nSegmentLength );
257             ResetSteamControllerPacketAssembler( pAssembler );
258             return -1;
259         }
260 
261         DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
262 
263         if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 )
264         {
265             // We get empty segments, just ignore them
266             return 0;
267         }
268 
269         if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber )
270         {
271             ResetSteamControllerPacketAssembler( pAssembler );
272 
273             if ( nSegmentNumber )
274             {
275                 // This happens occasionally
276                 DPRINTF("Bad segment number, got %d, expected %d\n",
277                     nSegmentNumber, pAssembler->nExpectedSegmentNumber );
278                 return -1;
279             }
280         }
281 
282         SDL_memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
283                pSegment + 2, // ignore header and report number
284                MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
285 
286         if ( uSegmentHeader & REPORT_SEGMENT_LAST_FLAG )
287         {
288             pAssembler->nExpectedSegmentNumber = 0;
289             return ( nSegmentNumber + 1 ) * MAX_REPORT_SEGMENT_PAYLOAD_SIZE;
290         }
291 
292         pAssembler->nExpectedSegmentNumber++;
293     }
294     else
295     {
296         // Just pass through
297         SDL_memcpy( pAssembler->uBuffer,
298                pSegment,
299                nSegmentLength );
300         return nSegmentLength;
301     }
302 
303     return 0;
304 }
305 
306 #define BLE_MAX_READ_RETRIES    8
307 
SetFeatureReport(SDL_hid_device * dev,unsigned char uBuffer[65],int nActualDataLen)308 static int SetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65], int nActualDataLen )
309 {
310     int nRet = -1;
311     bool bBle = true; // only wireless/BLE for now, though macOS could do wired in the future
312 
313     DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
314 
315     if ( bBle )
316     {
317         int nSegmentNumber = 0;
318         uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
319         unsigned char *pBufferPtr = uBuffer + 1;
320 
321         if ( nActualDataLen < 1 )
322             return -1;
323 
324         // Skip report number in data
325         nActualDataLen--;
326 
327         while ( nActualDataLen > 0 )
328         {
329             int nBytesInPacket = nActualDataLen > MAX_REPORT_SEGMENT_PAYLOAD_SIZE ? MAX_REPORT_SEGMENT_PAYLOAD_SIZE : nActualDataLen;
330 
331             nActualDataLen -= nBytesInPacket;
332 
333             // Construct packet
334             SDL_memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) );
335             uPacketBuffer[ 0 ] = BLE_REPORT_NUMBER;
336             uPacketBuffer[ 1 ] = GetSegmentHeader( nSegmentNumber, nActualDataLen == 0 );
337             SDL_memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
338 
339             pBufferPtr += nBytesInPacket;
340             nSegmentNumber++;
341 
342             nRet = SDL_hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) );
343             DPRINTF("SetFeatureReport() ret = %d\n", nRet);
344         }
345     }
346 
347     return nRet;
348 }
349 
GetFeatureReport(SDL_hid_device * dev,unsigned char uBuffer[65])350 static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
351 {
352     int nRet = -1;
353     bool bBle = true;
354 
355     DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
356 
357     if ( bBle )
358     {
359         int nRetries = 0;
360         uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
361 
362         SteamControllerPacketAssembler assembler;
363         InitializeSteamControllerPacketAssembler( &assembler );
364 
365         while( nRetries < BLE_MAX_READ_RETRIES )
366         {
367             SDL_memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
368             uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
369             nRet = SDL_hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) );
370             DPRINTF( "GetFeatureReport ble ret=%d\n", nRet );
371             HEXDUMP( uSegmentBuffer, nRet );
372 
373             // Zero retry counter if we got data
374             if ( nRet > 2 && ( uSegmentBuffer[ 1 ] & REPORT_SEGMENT_DATA_FLAG ) )
375                 nRetries = 0;
376             else
377                 nRetries++;
378 
379             if ( nRet > 0 )
380             {
381                 int nPacketLength = WriteSegmentToSteamControllerPacketAssembler( &assembler,
382                                                                                  uSegmentBuffer,
383                                                                                  nRet );
384 
385                 if ( nPacketLength > 0 && nPacketLength < 65 )
386                 {
387                     // Leave space for "report number"
388                     uBuffer[ 0 ] = 0;
389                     SDL_memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
390                     return nPacketLength;
391                 }
392             }
393 
394 
395         }
396         printf("Could not get a full ble packet after %d retries\n", nRetries );
397         return -1;
398     }
399 
400     return nRet;
401 }
402 
ReadResponse(SDL_hid_device * dev,uint8_t uBuffer[65],int nExpectedResponse)403 static int ReadResponse( SDL_hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse )
404 {
405     int nRet = GetFeatureReport( dev, uBuffer );
406 
407     DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
408 
409     if ( nRet < 0 )
410         return nRet;
411 
412     DPRINTF("ReadResponse got %d bytes of data: ", nRet );
413     HEXDUMP( uBuffer, nRet );
414 
415     if ( uBuffer[1] != nExpectedResponse )
416         return -1;
417 
418     return nRet;
419 }
420 
421 //---------------------------------------------------------------------------
422 // Reset steam controller (unmap buttons and pads) and re-fetch capability bits
423 //---------------------------------------------------------------------------
ResetSteamController(SDL_hid_device * dev,bool bSuppressErrorSpew,uint32_t * punUpdateRateUS)424 static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew, uint32_t *punUpdateRateUS )
425 {
426     // Firmware quirk: Set Feature and Get Feature requests always require a 65-byte buffer.
427     unsigned char buf[65];
428     int res = -1, i;
429     int nSettings = 0;
430     int nAttributesLength;
431     FeatureReportMsg *msg;
432     uint32_t unUpdateRateUS = 9000; // Good default rate
433 
434     DPRINTF( "ResetSteamController hid=%p\n", dev );
435 
436     buf[0] = 0;
437     buf[1] = ID_GET_ATTRIBUTES_VALUES;
438     res = SetFeatureReport( dev, buf, 2 );
439     if ( res < 0 )
440     {
441         if ( !bSuppressErrorSpew )
442             printf( "GET_ATTRIBUTES_VALUES failed for controller %p\n", dev );
443         return false;
444     }
445 
446     // Retrieve GET_ATTRIBUTES_VALUES result
447     // Wireless controller endpoints without a connected controller will return nAttrs == 0
448     res = ReadResponse( dev, buf, ID_GET_ATTRIBUTES_VALUES );
449     if ( res < 0 || buf[1] != ID_GET_ATTRIBUTES_VALUES )
450     {
451         HEXDUMP(buf, res);
452         if ( !bSuppressErrorSpew )
453             printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
454         return false;
455     }
456 
457     nAttributesLength = buf[ 2 ];
458     if ( nAttributesLength > res )
459     {
460         if ( !bSuppressErrorSpew )
461             printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
462         return false;
463     }
464 
465     msg = (FeatureReportMsg *)&buf[1];
466     for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i )
467     {
468         uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
469         uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
470 
471         switch ( unAttribute )
472         {
473         case ATTRIB_UNIQUE_ID:
474             break;
475         case ATTRIB_PRODUCT_ID:
476             break;
477         case ATTRIB_CAPABILITIES:
478             break;
479         case ATTRIB_CONNECTION_INTERVAL_IN_US:
480             unUpdateRateUS = unValue;
481             break;
482         default:
483             break;
484         }
485     }
486     if ( punUpdateRateUS )
487     {
488         *punUpdateRateUS = unUpdateRateUS;
489     }
490 
491     // Clear digital button mappings
492     buf[0] = 0;
493     buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
494     res = SetFeatureReport( dev, buf, 2 );
495     if ( res < 0 )
496     {
497         if ( !bSuppressErrorSpew )
498             printf( "CLEAR_DIGITAL_MAPPINGS failed for controller %p\n", dev );
499         return false;
500     }
501 
502     // Reset the default settings
503     SDL_memset( buf, 0, 65 );
504     buf[1] = ID_LOAD_DEFAULT_SETTINGS;
505     buf[2] = 0;
506     res = SetFeatureReport( dev, buf, 3 );
507     if ( res < 0 )
508     {
509         if ( !bSuppressErrorSpew )
510             printf( "LOAD_DEFAULT_SETTINGS failed for controller %p\n", dev );
511         return false;
512     }
513 
514     // Apply custom settings - clear trackpad modes (cancel mouse emulation), etc
515 #define ADD_SETTING(SETTING, VALUE)    \
516 buf[3+nSettings*3] = SETTING;    \
517 buf[3+nSettings*3+1] = ((uint16_t)VALUE)&0xFF; \
518 buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
519 ++nSettings;
520 
521     SDL_memset( buf, 0, 65 );
522     buf[1] = ID_SET_SETTINGS_VALUES;
523     ADD_SETTING( SETTING_WIRELESS_PACKET_VERSION, 2 );
524     ADD_SETTING( SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE );
525 #ifdef ENABLE_MOUSE_MODE
526     ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
527     ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 1 );
528     ADD_SETTING( SETTING_MOMENTUM_MAXIMUM_VELOCITY, 20000 );    // [0-20000] default 8000
529     ADD_SETTING( SETTING_MOMENTUM_DECAY_AMMOUNT, 50 );        // [0-50] default 5
530 #else
531     ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_NONE );
532     ADD_SETTING( SETTING_SMOOTH_ABSOLUTE_MOUSE, 0 );
533 #endif
534     buf[2] = nSettings*3;
535 
536     res = SetFeatureReport( dev, buf, 3+nSettings*3 );
537     if ( res < 0 )
538     {
539         if ( !bSuppressErrorSpew )
540             printf( "SET_SETTINGS failed for controller %p\n", dev );
541         return false;
542     }
543 
544 #ifdef ENABLE_MOUSE_MODE
545     // Wait for ID_CLEAR_DIGITAL_MAPPINGS to be processed on the controller
546     bool bMappingsCleared = false;
547     int iRetry;
548     for ( iRetry = 0; iRetry < 2; ++iRetry )
549     {
550         SDL_memset( buf, 0, 65 );
551         buf[1] = ID_GET_DIGITAL_MAPPINGS;
552         buf[2] = 1; // one byte - requesting from index 0
553         buf[3] = 0;
554         res = SetFeatureReport( dev, buf, 4 );
555         if ( res < 0 )
556         {
557             printf( "GET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
558             return false;
559         }
560 
561         res = ReadResponse( dev, buf, ID_GET_DIGITAL_MAPPINGS );
562         if ( res < 0 || buf[1] != ID_GET_DIGITAL_MAPPINGS )
563         {
564             printf( "Bad GET_DIGITAL_MAPPINGS response for controller %p\n", dev );
565             return false;
566         }
567 
568         // If the length of the digital mappings result is not 1 (index byte, no mappings) then clearing hasn't executed
569         if ( buf[2] == 1 && buf[3] == 0xFF )
570         {
571             bMappingsCleared = true;
572             break;
573         }
574         usleep( CONTROLLER_CONFIGURATION_DELAY_US );
575     }
576 
577     if ( !bMappingsCleared && !bSuppressErrorSpew )
578     {
579         printf( "Warning: CLEAR_DIGITAL_MAPPINGS never completed for controller %p\n", dev );
580     }
581 
582     // Set our new mappings
583     SDL_memset( buf, 0, 65 );
584     buf[1] = ID_SET_DIGITAL_MAPPINGS;
585     buf[2] = 6; // 2 settings x 3 bytes
586     buf[3] = IO_DIGITAL_BUTTON_RIGHT_TRIGGER;
587     buf[4] = DEVICE_MOUSE;
588     buf[5] = MOUSE_BTN_LEFT;
589     buf[6] = IO_DIGITAL_BUTTON_LEFT_TRIGGER;
590     buf[7] = DEVICE_MOUSE;
591     buf[8] = MOUSE_BTN_RIGHT;
592 
593     res = SetFeatureReport( dev, buf, 9 );
594     if ( res < 0 )
595     {
596         if ( !bSuppressErrorSpew )
597             printf( "SET_DIGITAL_MAPPINGS failed for controller %p\n", dev );
598         return false;
599     }
600 #endif // ENABLE_MOUSE_MODE
601 
602     return true;
603 }
604 
605 
606 //---------------------------------------------------------------------------
607 // Read from a Steam Controller
608 //---------------------------------------------------------------------------
ReadSteamController(SDL_hid_device * dev,uint8_t * pData,int nDataSize)609 static int ReadSteamController( SDL_hid_device *dev, uint8_t *pData, int nDataSize )
610 {
611     SDL_memset( pData, 0, nDataSize );
612     pData[ 0 ] = BLE_REPORT_NUMBER; // hid_read will also overwrite this with the same value, 0x03
613     return SDL_hid_read( dev, pData, nDataSize );
614 }
615 
616 
617 //---------------------------------------------------------------------------
618 // Close a Steam Controller
619 //---------------------------------------------------------------------------
CloseSteamController(SDL_hid_device * dev)620 static void CloseSteamController( SDL_hid_device *dev )
621 {
622     // Switch the Steam Controller back to lizard mode so it works with the OS
623     unsigned char buf[65];
624     int nSettings = 0;
625 
626     // Reset digital button mappings
627     SDL_memset( buf, 0, 65 );
628     buf[1] = ID_SET_DEFAULT_DIGITAL_MAPPINGS;
629     SetFeatureReport( dev, buf, 2 );
630 
631     // Reset the default settings
632     SDL_memset( buf, 0, 65 );
633     buf[1] = ID_LOAD_DEFAULT_SETTINGS;
634     buf[2] = 0;
635     SetFeatureReport( dev, buf, 3 );
636 
637     // Reset mouse mode for lizard mode
638     SDL_memset( buf, 0, 65 );
639     buf[1] = ID_SET_SETTINGS_VALUES;
640     ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
641     buf[2] = nSettings*3;
642     SetFeatureReport( dev, buf, 3+nSettings*3 );
643 }
644 
645 
646 //---------------------------------------------------------------------------
647 // Scale and clamp values to a range
648 //---------------------------------------------------------------------------
RemapValClamped(float val,float A,float B,float C,float D)649 static float RemapValClamped( float val, float A, float B, float C, float D)
650 {
651     if ( A == B )
652     {
653         return ( val - B ) >= 0.0f ? D : C;
654     }
655     else
656     {
657         float cVal = (val - A) / (B - A);
658         cVal = clamp( cVal, 0.0f, 1.0f );
659 
660         return C + (D - C) * cVal;
661     }
662 }
663 
664 
665 //---------------------------------------------------------------------------
666 // Rotate the pad coordinates
667 //---------------------------------------------------------------------------
RotatePad(int * pX,int * pY,float flAngleInRad)668 static void RotatePad( int *pX, int *pY, float flAngleInRad )
669 {
670     short int origX = *pX, origY = *pY;
671 
672     *pX = (int)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY );
673     *pY = (int)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY );
674 }
RotatePadShort(short * pX,short * pY,float flAngleInRad)675 static void RotatePadShort( short *pX, short *pY, float flAngleInRad )
676 {
677     short int origX = *pX, origY = *pY;
678 
679     *pX = (short)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY );
680     *pY = (short)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY );
681 }
682 
683 
684 //---------------------------------------------------------------------------
685 // Format the first part of the state packet
686 //---------------------------------------------------------------------------
FormatStatePacketUntilGyro(SteamControllerStateInternal_t * pState,ValveControllerStatePacket_t * pStatePacket)687 static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState, ValveControllerStatePacket_t *pStatePacket )
688 {
689     int nLeftPadX;
690     int nLeftPadY;
691     int nRightPadX;
692     int nRightPadY;
693     int nPadOffset;
694 
695     // 15 degrees in rad
696     const float flRotationAngle = 0.261799f;
697 
698     SDL_memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
699 
700     //pState->eControllerType = m_eControllerType;
701     pState->eControllerType = 2; // k_eControllerType_SteamController;
702     pState->unPacketNum = pStatePacket->unPacketNum;
703 
704     // We have a chunk of trigger data in the packet format here, so zero it out afterwards
705     SDL_memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
706     pState->ulButtons &= ~0xFFFF000000LL;
707 
708     // The firmware uses this bit to tell us what kind of data is packed into the left two axises
709     if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
710     {
711         // Finger-down bit not set; "left pad" is actually trackpad
712         pState->sLeftPadX = pState->sPrevLeftPad[0] = pStatePacket->sLeftPadX;
713         pState->sLeftPadY = pState->sPrevLeftPad[1] = pStatePacket->sLeftPadY;
714 
715         if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
716         {
717             // The controller is interleaving both stick and pad data, both are active
718             pState->sLeftStickX = pState->sPrevLeftStick[0];
719             pState->sLeftStickY = pState->sPrevLeftStick[1];
720         }
721         else
722         {
723             // The stick is not active
724             pState->sPrevLeftStick[0] = 0;
725             pState->sPrevLeftStick[1] = 0;
726         }
727     }
728     else
729     {
730         // Finger-down bit not set; "left pad" is actually joystick
731 
732         // XXX there's a firmware bug where sometimes padX is 0 and padY is a large number (acutally the battery voltage)
733         // If that happens skip this packet and report last frames stick
734 /*
735         if ( m_eControllerType == k_eControllerType_SteamControllerV2 && pStatePacket->sLeftPadY > 900 )
736         {
737             pState->sLeftStickX = pState->sPrevLeftStick[0];
738             pState->sLeftStickY = pState->sPrevLeftStick[1];
739         }
740         else
741 */
742         {
743             pState->sPrevLeftStick[0] = pState->sLeftStickX = pStatePacket->sLeftPadX;
744             pState->sPrevLeftStick[1] = pState->sLeftStickY = pStatePacket->sLeftPadY;
745         }
746 /*
747         if (m_eControllerType == k_eControllerType_SteamControllerV2)
748         {
749             UpdateV2JoystickCap(&state);
750         }
751 */
752 
753         if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
754         {
755             // The controller is interleaving both stick and pad data, both are active
756             pState->sLeftPadX = pState->sPrevLeftPad[0];
757             pState->sLeftPadY = pState->sPrevLeftPad[1];
758         }
759         else
760         {
761             // The trackpad is not active
762             pState->sPrevLeftPad[0] = 0;
763             pState->sPrevLeftPad[1] = 0;
764 
765             // Old controllers send trackpad click for joystick button when trackpad is not active
766             if (pState->ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK)
767             {
768                 pState->ulButtons &= ~STEAM_BUTTON_LEFTPAD_CLICKED_MASK;
769                 pState->ulButtons |= STEAM_JOYSTICK_BUTTON_MASK;
770             }
771         }
772     }
773 
774     // Fingerdown bit indicates if the packed left axis data was joystick or pad,
775     // but if we are interleaving both, the left finger is definitely on the pad.
776     if (pStatePacket->ButtonTriggerData.ulButtons & STEAM_LEFTPAD_AND_JOYSTICK_MASK)
777         pState->ulButtons |= STEAM_LEFTPAD_FINGERDOWN_MASK;
778 
779     pState->sRightPadX = pStatePacket->sRightPadX;
780     pState->sRightPadY = pStatePacket->sRightPadY;
781 
782     nLeftPadX = pState->sLeftPadX;
783     nLeftPadY = pState->sLeftPadY;
784     nRightPadX = pState->sRightPadX;
785     nRightPadY = pState->sRightPadY;
786 
787     RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle);
788     RotatePad(&nRightPadX, &nRightPadY, flRotationAngle);
789 
790     if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
791         nPadOffset = 1000;
792     else
793         nPadOffset = 0;
794 
795     pState->sLeftPadX = clamp(nLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16);
796     pState->sLeftPadY = clamp(nLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16);
797 
798     nPadOffset = 0;
799     if (pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK)
800         nPadOffset = 1000;
801     else
802         nPadOffset = 0;
803 
804     pState->sRightPadX = clamp(nRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16);
805     pState->sRightPadY = clamp(nRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16);
806 
807     pState->sTriggerL = (unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nLeft << 7) | pStatePacket->ButtonTriggerData.Triggers.nLeft, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
808     pState->sTriggerR = (unsigned short)RemapValClamped( (pStatePacket->ButtonTriggerData.Triggers.nRight << 7) | pStatePacket->ButtonTriggerData.Triggers.nRight, 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
809 }
810 
811 
812 //---------------------------------------------------------------------------
813 // Update Steam Controller state from a BLE data packet, returns true if it parsed data
814 //---------------------------------------------------------------------------
UpdateBLESteamControllerState(const uint8_t * pData,int nDataSize,SteamControllerStateInternal_t * pState)815 static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize, SteamControllerStateInternal_t *pState )
816 {
817     const float flRotationAngle = 0.261799f;
818     uint32_t ucOptionDataMask;
819 
820     pState->unPacketNum++;
821     ucOptionDataMask = ( *pData++ & 0xF0 );
822     ucOptionDataMask |= (uint32_t)(*pData++) << 8;
823     if ( ucOptionDataMask & k_EBLEButtonChunk1 )
824     {
825         SDL_memcpy( &pState->ulButtons, pData, 3 );
826         pData += 3;
827     }
828     if ( ucOptionDataMask & k_EBLEButtonChunk2 )
829     {
830         // 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
831         pState->sTriggerL = (unsigned short)RemapValClamped( ( pData[ 0 ] << 7 ) | pData[ 0 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
832         pState->sTriggerR = (unsigned short)RemapValClamped( ( pData[ 1 ] << 7 ) | pData[ 1 ], 0, STEAMCONTROLLER_TRIGGER_MAX_ANALOG, 0, SDL_MAX_SINT16 );
833         pData += 2;
834     }
835     if ( ucOptionDataMask & k_EBLEButtonChunk3 )
836     {
837         uint8_t *pButtonByte = (uint8_t *)&pState->ulButtons;
838         pButtonByte[ 5 ] = *pData++;
839         pButtonByte[ 6 ] = *pData++;
840         pButtonByte[ 7 ] = *pData++;
841     }
842     if ( ucOptionDataMask & k_EBLELeftJoystickChunk )
843     {
844         // This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support
845         // this protocol yet either
846         int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY );
847         SDL_memcpy( &pState->sLeftStickX, pData, nLength );
848         pData += nLength;
849     }
850     if ( ucOptionDataMask & k_EBLELeftTrackpadChunk )
851     {
852         int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY );
853         int nPadOffset;
854         SDL_memcpy( &pState->sLeftPadX, pData, nLength );
855         if ( pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK )
856             nPadOffset = 1000;
857         else
858             nPadOffset = 0;
859 
860         RotatePadShort( &pState->sLeftPadX, &pState->sLeftPadY, -flRotationAngle );
861         pState->sLeftPadX = clamp( pState->sLeftPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
862         pState->sLeftPadY = clamp( pState->sLeftPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
863         pData += nLength;
864     }
865     if ( ucOptionDataMask & k_EBLERightTrackpadChunk )
866     {
867         int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY );
868         int nPadOffset = 0;
869 
870         SDL_memcpy( &pState->sRightPadX, pData, nLength );
871 
872         if ( pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK )
873             nPadOffset = 1000;
874         else
875             nPadOffset = 0;
876 
877         RotatePadShort( &pState->sRightPadX, &pState->sRightPadY, flRotationAngle );
878         pState->sRightPadX = clamp( pState->sRightPadX + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
879         pState->sRightPadY = clamp( pState->sRightPadY + nPadOffset, SDL_MIN_SINT16, SDL_MAX_SINT16 );
880         pData += nLength;
881     }
882     if ( ucOptionDataMask & k_EBLEIMUAccelChunk )
883     {
884         int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
885         SDL_memcpy( &pState->sAccelX, pData, nLength );
886         pData += nLength;
887     }
888     if ( ucOptionDataMask & k_EBLEIMUGyroChunk )
889     {
890         int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
891         SDL_memcpy( &pState->sGyroX, pData, nLength );
892         pData += nLength;
893     }
894     if ( ucOptionDataMask & k_EBLEIMUQuatChunk )
895     {
896         int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ );
897         SDL_memcpy( &pState->sGyroQuatW, pData, nLength );
898         pData += nLength;
899     }
900     return true;
901 }
902 
903 
904 //---------------------------------------------------------------------------
905 // Update Steam Controller state from a data packet, returns true if it parsed data
906 //---------------------------------------------------------------------------
UpdateSteamControllerState(const uint8_t * pData,int nDataSize,SteamControllerStateInternal_t * pState)907 static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, SteamControllerStateInternal_t *pState )
908 {
909     ValveInReport_t *pInReport = (ValveInReport_t*)pData;
910 
911     if ( pInReport->header.unReportVersion != k_ValveInReportMsgVersion )
912     {
913         if ( ( pData[ 0 ] & 0x0F ) == k_EBLEReportState )
914         {
915             return UpdateBLESteamControllerState( pData, nDataSize, pState );
916         }
917         return false;
918     }
919 
920     if ( ( pInReport->header.ucType != ID_CONTROLLER_STATE ) &&
921          ( pInReport->header.ucType != ID_CONTROLLER_BLE_STATE ) )
922     {
923         return false;
924     }
925 
926     if ( pInReport->header.ucType == ID_CONTROLLER_STATE )
927     {
928         ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
929 
930         // No new data to process; indicate that we received a state packet, but otherwise do nothing.
931         if ( pState->unPacketNum == pStatePacket->unPacketNum )
932             return true;
933 
934         FormatStatePacketUntilGyro( pState, pStatePacket );
935 
936         pState->sAccelX = pStatePacket->sAccelX;
937         pState->sAccelY = pStatePacket->sAccelY;
938         pState->sAccelZ = pStatePacket->sAccelZ;
939 
940         pState->sGyroQuatW = pStatePacket->sGyroQuatW;
941         pState->sGyroQuatX = pStatePacket->sGyroQuatX;
942         pState->sGyroQuatY = pStatePacket->sGyroQuatY;
943         pState->sGyroQuatZ = pStatePacket->sGyroQuatZ;
944 
945         pState->sGyroX = pStatePacket->sGyroX;
946         pState->sGyroY = pStatePacket->sGyroY;
947         pState->sGyroZ = pStatePacket->sGyroZ;
948 
949     }
950     else if ( pInReport->header.ucType == ID_CONTROLLER_BLE_STATE )
951     {
952         ValveControllerBLEStatePacket_t *pBLEStatePacket = &pInReport->payload.controllerBLEState;
953         ValveControllerStatePacket_t *pStatePacket = &pInReport->payload.controllerState;
954 
955         // No new data to process; indicate that we received a state packet, but otherwise do nothing.
956         if ( pState->unPacketNum == pStatePacket->unPacketNum )
957             return true;
958 
959         FormatStatePacketUntilGyro( pState, pStatePacket );
960 
961         switch ( pBLEStatePacket->ucGyroDataType )
962         {
963         case 1:
964             pState->sGyroQuatW = (( float ) pBLEStatePacket->sGyro[0]);
965             pState->sGyroQuatX = (( float ) pBLEStatePacket->sGyro[1]);
966             pState->sGyroQuatY = (( float ) pBLEStatePacket->sGyro[2]);
967             pState->sGyroQuatZ = (( float ) pBLEStatePacket->sGyro[3]);
968             break;
969 
970         case 2:
971             pState->sAccelX = pBLEStatePacket->sGyro[0];
972             pState->sAccelY = pBLEStatePacket->sGyro[1];
973             pState->sAccelZ = pBLEStatePacket->sGyro[2];
974             break;
975 
976         case 3:
977             pState->sGyroX = pBLEStatePacket->sGyro[0];
978             pState->sGyroY = pBLEStatePacket->sGyro[1];
979             pState->sGyroZ = pBLEStatePacket->sGyro[2];
980             break;
981 
982         default:
983             break;
984         }
985     }
986 
987     return true;
988 }
989 
990 /*****************************************************************************************************/
991 
992 typedef struct {
993     SDL_bool report_sensors;
994     SteamControllerPacketAssembler m_assembler;
995     SteamControllerStateInternal_t m_state;
996     SteamControllerStateInternal_t m_last_state;
997 } SDL_DriverSteam_Context;
998 
999 
1000 static SDL_bool
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)1001 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)
1002 {
1003     return SDL_IsJoystickSteamController(vendor_id, product_id);
1004 }
1005 
1006 static const char *
HIDAPI_DriverSteam_GetDeviceName(Uint16 vendor_id,Uint16 product_id)1007 HIDAPI_DriverSteam_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
1008 {
1009     return "Steam Controller";
1010 }
1011 
1012 static SDL_bool
HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device * device)1013 HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device)
1014 {
1015     return HIDAPI_JoystickConnected(device, NULL);
1016 }
1017 
1018 static int
HIDAPI_DriverSteam_GetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id)1019 HIDAPI_DriverSteam_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
1020 {
1021     return -1;
1022 }
1023 
1024 static void
HIDAPI_DriverSteam_SetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id,int player_index)1025 HIDAPI_DriverSteam_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
1026 {
1027 }
1028 
1029 static SDL_bool
HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)1030 HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1031 {
1032     SDL_DriverSteam_Context *ctx;
1033     uint32_t update_rate_in_us = 0;
1034     float update_rate_in_hz = 0.0f;
1035 
1036     ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
1037     if (!ctx) {
1038         SDL_OutOfMemory();
1039         goto error;
1040     }
1041     device->context = ctx;
1042 
1043     device->dev = SDL_hid_open_path(device->path, 0);
1044     if (!device->dev) {
1045         SDL_SetError("Couldn't open %s", device->path);
1046         goto error;
1047     }
1048     SDL_hid_set_nonblocking(device->dev, 1);
1049 
1050     if (!ResetSteamController(device->dev, false, &update_rate_in_us)) {
1051         SDL_SetError("Couldn't reset controller");
1052         goto error;
1053     }
1054     if (update_rate_in_us > 0) {
1055         update_rate_in_hz = 1000000.0f / update_rate_in_us;
1056     }
1057 
1058     InitializeSteamControllerPacketAssembler(&ctx->m_assembler);
1059 
1060     /* Initialize the joystick capabilities */
1061     joystick->nbuttons = 17;
1062     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
1063 
1064     SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
1065     SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
1066 
1067     return SDL_TRUE;
1068 
1069 error:
1070     SDL_LockMutex(device->dev_lock);
1071     {
1072         if (device->dev) {
1073             SDL_hid_close(device->dev);
1074             device->dev = NULL;
1075         }
1076         if (device->context) {
1077             SDL_free(device->context);
1078             device->context = NULL;
1079         }
1080     }
1081     SDL_UnlockMutex(device->dev_lock);
1082     return SDL_FALSE;
1083 }
1084 
1085 static int
HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)1086 HIDAPI_DriverSteam_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1087 {
1088     /* You should use the full Steam Input API for rumble support */
1089     return SDL_Unsupported();
1090 }
1091 
1092 static int
HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint16 left_rumble,Uint16 right_rumble)1093 HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
1094 {
1095     return SDL_Unsupported();
1096 }
1097 
1098 static Uint32
HIDAPI_DriverSteam_GetJoystickCapabilities(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)1099 HIDAPI_DriverSteam_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1100 {
1101     /* You should use the full Steam Input API for LED support */
1102     return 0;
1103 }
1104 
1105 static int
HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint8 red,Uint8 green,Uint8 blue)1106 HIDAPI_DriverSteam_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
1107 {
1108     /* You should use the full Steam Input API for LED support */
1109     return SDL_Unsupported();
1110 }
1111 
1112 static int
HIDAPI_DriverSteam_SendJoystickEffect(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,const void * data,int size)1113 HIDAPI_DriverSteam_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
1114 {
1115     return SDL_Unsupported();
1116 }
1117 
1118 static int
HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,SDL_bool enabled)1119 HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
1120 {
1121     SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
1122     unsigned char buf[65];
1123     int nSettings = 0;
1124 
1125     SDL_memset( buf, 0, 65 );
1126     buf[1] = ID_SET_SETTINGS_VALUES;
1127     if (enabled) {
1128         ADD_SETTING( SETTING_GYRO_MODE, 0x18 /* SETTING_GYRO_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO */ );
1129     } else {
1130         ADD_SETTING( SETTING_GYRO_MODE, 0x00 /* SETTING_GYRO_MODE_OFF */ );
1131     }
1132     buf[2] = nSettings*3;
1133     if (SetFeatureReport( device->dev, buf, 3+nSettings*3 ) < 0) {
1134         return SDL_SetError("Couldn't write feature report");
1135     }
1136 
1137     ctx->report_sensors = enabled;
1138 
1139     return 0;
1140 }
1141 
1142 static SDL_bool
HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device * device)1143 HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
1144 {
1145     SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
1146     SDL_Joystick *joystick = NULL;
1147 
1148     if (device->num_joysticks > 0) {
1149         joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
1150     }
1151     if (!joystick) {
1152         return SDL_FALSE;
1153     }
1154 
1155     for (;;)
1156     {
1157         uint8_t data[128];
1158         int r, nPacketLength;
1159         const Uint8 *pPacket;
1160 
1161         r = ReadSteamController(device->dev, data, sizeof(data));
1162         if (r == 0)
1163         {
1164             break;
1165         }
1166 
1167         nPacketLength = 0;
1168         if (r > 0) {
1169             nPacketLength = WriteSegmentToSteamControllerPacketAssembler(&ctx->m_assembler, data, r);
1170         }
1171 
1172         pPacket = ctx->m_assembler.uBuffer;
1173 
1174         if (nPacketLength > 0 && UpdateSteamControllerState(pPacket, nPacketLength, &ctx->m_state)) {
1175             if (ctx->m_state.ulButtons != ctx->m_last_state.ulButtons) {
1176                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A,
1177                     (ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED);
1178 
1179                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B,
1180                     (ctx->m_state.ulButtons & STEAM_BUTTON_1_MASK) ? SDL_PRESSED : SDL_RELEASED);
1181 
1182                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X,
1183                     (ctx->m_state.ulButtons & STEAM_BUTTON_2_MASK) ? SDL_PRESSED : SDL_RELEASED);
1184 
1185                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y,
1186                     (ctx->m_state.ulButtons & STEAM_BUTTON_0_MASK) ? SDL_PRESSED : SDL_RELEASED);
1187 
1188                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
1189                     (ctx->m_state.ulButtons & STEAM_LEFT_BUMPER_MASK) ? SDL_PRESSED : SDL_RELEASED);
1190 
1191                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
1192                     (ctx->m_state.ulButtons & STEAM_RIGHT_BUMPER_MASK) ? SDL_PRESSED : SDL_RELEASED);
1193 
1194                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK,
1195                     (ctx->m_state.ulButtons & STEAM_BUTTON_MENU_MASK) ? SDL_PRESSED : SDL_RELEASED);
1196 
1197                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START,
1198                     (ctx->m_state.ulButtons & STEAM_BUTTON_ESCAPE_MASK) ? SDL_PRESSED : SDL_RELEASED);
1199 
1200                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE,
1201                     (ctx->m_state.ulButtons & STEAM_BUTTON_STEAM_MASK) ? SDL_PRESSED : SDL_RELEASED);
1202 
1203                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK,
1204                     (ctx->m_state.ulButtons & STEAM_JOYSTICK_BUTTON_MASK) ? SDL_PRESSED : SDL_RELEASED);
1205                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 0,
1206                     (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_LEFT_MASK) ? SDL_PRESSED : SDL_RELEASED);
1207                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 1,
1208                     (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED);
1209             }
1210             {
1211                 /* Minimum distance from center of pad to register a direction */
1212                 const int kPadDeadZone = 10000;
1213 
1214                 /* Pad coordinates are like math grid coordinates: negative is bottom left */
1215                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP,
1216                     (ctx->m_state.sLeftPadY > kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED);
1217 
1218                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN,
1219                     (ctx->m_state.sLeftPadY < -kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED);
1220 
1221                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT,
1222                     (ctx->m_state.sLeftPadX < -kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED);
1223 
1224                 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
1225                     (ctx->m_state.sLeftPadX > kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED);
1226             }
1227 
1228             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, (int)ctx->m_state.sTriggerL * 2 - 32768);
1229             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, (int)ctx->m_state.sTriggerR * 2 - 32768);
1230 
1231             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, ctx->m_state.sLeftStickX);
1232             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~ctx->m_state.sLeftStickY);
1233             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, ctx->m_state.sRightPadX);
1234             SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~ctx->m_state.sRightPadY);
1235 
1236             if (ctx->report_sensors) {
1237                 float values[3];
1238 
1239                 values[0] = (ctx->m_state.sGyroX / 32768.0f) * (2000.0f * (M_PI / 180.0f));
1240                 values[1] = (ctx->m_state.sGyroZ / 32768.0f) * (2000.0f * (M_PI / 180.0f));
1241                 values[2] = (ctx->m_state.sGyroY / 32768.0f) * (2000.0f * (M_PI / 180.0f));
1242                 SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3);
1243 
1244                 values[0] = (ctx->m_state.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
1245                 values[1] = (ctx->m_state.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
1246                 values[2] = (-ctx->m_state.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
1247                 SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3);
1248             }
1249 
1250             ctx->m_last_state = ctx->m_state;
1251         }
1252 
1253         if (r <= 0) {
1254             /* Failed to read from controller */
1255             HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
1256             return SDL_FALSE;
1257         }
1258     }
1259     return SDL_TRUE;
1260 }
1261 
1262 static void
HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)1263 HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1264 {
1265     SDL_LockMutex(device->dev_lock);
1266     {
1267         CloseSteamController(device->dev);
1268 
1269         SDL_hid_close(device->dev);
1270         device->dev = NULL;
1271 
1272         SDL_free(device->context);
1273         device->context = NULL;
1274     }
1275     SDL_UnlockMutex(device->dev_lock);
1276 }
1277 
1278 static void
HIDAPI_DriverSteam_FreeDevice(SDL_HIDAPI_Device * device)1279 HIDAPI_DriverSteam_FreeDevice(SDL_HIDAPI_Device *device)
1280 {
1281 }
1282 
1283 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
1284 {
1285     SDL_HINT_JOYSTICK_HIDAPI_STEAM,
1286     SDL_TRUE,
1287     SDL_FALSE,
1288     HIDAPI_DriverSteam_IsSupportedDevice,
1289     HIDAPI_DriverSteam_GetDeviceName,
1290     HIDAPI_DriverSteam_InitDevice,
1291     HIDAPI_DriverSteam_GetDevicePlayerIndex,
1292     HIDAPI_DriverSteam_SetDevicePlayerIndex,
1293     HIDAPI_DriverSteam_UpdateDevice,
1294     HIDAPI_DriverSteam_OpenJoystick,
1295     HIDAPI_DriverSteam_RumbleJoystick,
1296     HIDAPI_DriverSteam_RumbleJoystickTriggers,
1297     HIDAPI_DriverSteam_GetJoystickCapabilities,
1298     HIDAPI_DriverSteam_SetJoystickLED,
1299     HIDAPI_DriverSteam_SendJoystickEffect,
1300     HIDAPI_DriverSteam_SetSensorsEnabled,
1301     HIDAPI_DriverSteam_CloseJoystick,
1302     HIDAPI_DriverSteam_FreeDevice,
1303 };
1304 
1305 #endif /* SDL_JOYSTICK_HIDAPI_STEAM */
1306 
1307 #endif /* SDL_JOYSTICK_HIDAPI */
1308 
1309 /* vi: set ts=4 sw=4 expandtab: */
1310