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