SDL  2.0
SDL_hidapi_ps4.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 /* This driver supports both simplified reports and the extended input reports enabled by Steam.
22  Code and logic contributed by Valve Corporation under the SDL zlib license.
23 */
24 #include "../../SDL_internal.h"
25 
26 #ifdef SDL_JOYSTICK_HIDAPI
27 
28 #include "SDL_hints.h"
29 #include "SDL_log.h"
30 #include "SDL_events.h"
31 #include "SDL_timer.h"
32 #include "SDL_joystick.h"
33 #include "SDL_gamecontroller.h"
34 #include "../SDL_sysjoystick.h"
35 #include "SDL_hidapijoystick_c.h"
36 
37 
38 #ifdef SDL_JOYSTICK_HIDAPI_PS4
39 
40 #define SONY_USB_VID 0x054C
41 #define SONY_DS4_PID 0x05C4
42 #define SONY_DS4_DONGLE_PID 0x0BA0
43 #define SONY_DS4_SLIM_PID 0x09CC
44 
45 #define RAZER_USB_VID 0x1532
46 #define RAZER_PANTHERA_PID 0X0401
47 #define RAZER_PANTHERA_EVO_PID 0x1008
48 
49 #define USB_PACKET_LENGTH 64
50 
51 #define VOLUME_CHECK_INTERVAL_MS (10 * 1000)
52 
53 typedef enum
54 {
55  k_EPS4ReportIdUsbState = 1,
56  k_EPS4ReportIdUsbEffects = 5,
57  k_EPS4ReportIdBluetoothState = 17,
58  k_EPS4ReportIdBluetoothEffects = 17,
59  k_EPS4ReportIdDisconnectMessage = 226,
60 } EPS4ReportId;
61 
62 typedef enum
63 {
64  k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
65  k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
66  k_ePS4FeatureReportIdSerialNumber = 0x12,
67 } EPS4FeatureReportID;
68 
69 typedef struct
70 {
71  Uint8 ucLeftJoystickX;
72  Uint8 ucLeftJoystickY;
73  Uint8 ucRightJoystickX;
74  Uint8 ucRightJoystickY;
75  Uint8 rgucButtonsHatAndCounter[ 3 ];
76  Uint8 ucTriggerLeft;
77  Uint8 ucTriggerRight;
78  Uint8 _rgucPad0[ 3 ];
79  Sint16 sGyroX;
80  Sint16 sGyroY;
81  Sint16 sGyroZ;
82  Sint16 sAccelX;
83  Sint16 sAccelY;
84  Sint16 sAccelZ;
85  Uint8 _rgucPad1[ 5 ];
86  Uint8 ucBatteryLevel;
87  Uint8 _rgucPad2[ 4 ];
88  Uint8 ucTrackpadCounter1;
89  Uint8 rgucTrackpadData1[ 3 ];
90  Uint8 ucTrackpadCounter2;
91  Uint8 rgucTrackpadData2[ 3 ];
92 } PS4StatePacket_t;
93 
94 typedef struct
95 {
96  Uint8 ucRumbleRight;
97  Uint8 ucRumbleLeft;
98  Uint8 ucLedRed;
99  Uint8 ucLedGreen;
100  Uint8 ucLedBlue;
101  Uint8 ucLedDelayOn;
102  Uint8 ucLedDelayOff;
103  Uint8 _rgucPad0[ 8 ];
104  Uint8 ucVolumeLeft;
105  Uint8 ucVolumeRight;
106  Uint8 ucVolumeMic;
107  Uint8 ucVolumeSpeaker;
108 } DS4EffectsState_t;
109 
110 typedef struct {
111  SDL_bool is_dongle;
112  SDL_bool is_bluetooth;
113  SDL_bool audio_supported;
114  SDL_bool rumble_supported;
115  Uint8 volume;
116  Uint32 last_volume_check;
118  PS4StatePacket_t last_state;
119 } SDL_DriverPS4_Context;
120 
121 
122 /* Public domain CRC implementation adapted from:
123  http://home.thep.lu.se/~bjorn/crc/crc32_simple.c
124 */
125 static Uint32 crc32_for_byte(Uint32 r)
126 {
127  int i;
128  for(i = 0; i < 8; ++i) {
129  r = (r & 1? 0: (Uint32)0xEDB88320L) ^ r >> 1;
130  }
131  return r ^ (Uint32)0xFF000000L;
132 }
133 
134 static Uint32 crc32(Uint32 crc, const void *data, int count)
135 {
136  int i;
137  for(i = 0; i < count; ++i) {
138  crc = crc32_for_byte((Uint8)crc ^ ((const Uint8*)data)[i]) ^ crc >> 8;
139  }
140  return crc;
141 }
142 
143 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
144 #include "../../core/windows/SDL_windows.h"
145 
146 #ifndef NTDDI_VISTA
147 #define NTDDI_VISTA 0x06000000
148 #endif
149 #ifndef _WIN32_WINNT_VISTA
150 #define _WIN32_WINNT_VISTA 0x0600
151 #endif
152 
153 /* Define Vista for the Audio related includes below to work */
154 #undef NTDDI_VERSION
155 #define NTDDI_VERSION NTDDI_VISTA
156 #undef _WIN32_WINNT
157 #define _WIN32_WINNT _WIN32_WINNT_VISTA
158 #define COBJMACROS
159 #include <mmdeviceapi.h>
160 #include <audioclient.h>
161 #include <endpointvolume.h>
162 
163 #undef DEFINE_GUID
164 #define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) static const GUID n = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
165 DEFINE_GUID(SDL_CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
166 DEFINE_GUID(SDL_IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
167 DEFINE_GUID(SDL_IID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A);
168 #endif
169 
170 
171 
172 static float GetSystemVolume(void)
173 {
174  float volume = -1.0f; /* Return this if we can't get system volume */
175 
176 #if defined(__WIN32__) && defined(HAVE_ENDPOINTVOLUME_H)
177  HRESULT hr = WIN_CoInitialize();
178  if (SUCCEEDED(hr)) {
179  IMMDeviceEnumerator *pEnumerator;
180 
181  /* This should gracefully fail on XP and succeed on everything Vista and above */
182  hr = CoCreateInstance(&SDL_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &SDL_IID_IMMDeviceEnumerator, (LPVOID*)&pEnumerator);
183  if (SUCCEEDED(hr)) {
184  IMMDevice *pDevice;
185 
186  hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, eRender, eConsole, &pDevice);
187  if (SUCCEEDED(hr)) {
188  IAudioEndpointVolume *pEndpointVolume;
189 
190  hr = IMMDevice_Activate(pDevice, &SDL_IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (LPVOID*)&pEndpointVolume);
191  if (SUCCEEDED(hr)) {
192  IAudioEndpointVolume_GetMasterVolumeLevelScalar(pEndpointVolume, &volume);
193  IUnknown_Release(pEndpointVolume);
194  }
195  IUnknown_Release(pDevice);
196  }
197  IUnknown_Release(pEnumerator);
198  }
200  }
201 #endif /* __WIN32__ */
202 
203  return volume;
204 }
205 
206 static uint8_t GetPlaystationVolumeFromFloat(float fVolume)
207 {
208  const int k_nVolumeFitRatio = 15;
209  const int k_nVolumeFitOffset = 9;
210  float fVolLog;
211 
212  if (fVolume > 1.0f || fVolume < 0.0f) {
213  fVolume = 0.30f;
214  }
215  fVolLog = SDL_logf(fVolume * 100);
216 
217  return (Uint8)((fVolLog * k_nVolumeFitRatio) + k_nVolumeFitOffset);
218 }
219 
220 static SDL_bool
221 HIDAPI_DriverPS4_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
222 {
223  return SDL_IsJoystickPS4(vendor_id, product_id);
224 }
225 
226 static const char *
227 HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
228 {
229  if (vendor_id == SONY_USB_VID) {
230  return "PS4 Controller";
231  }
232  return NULL;
233 }
234 
235 static SDL_bool ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *data, size_t size)
236 {
237  Uint8 report[USB_PACKET_LENGTH + 1];
238 
239  SDL_memset(report, 0, sizeof(report));
240  report[0] = report_id;
241  if (hid_get_feature_report(dev, report, sizeof(report)) < 0) {
242  return SDL_FALSE;
243  }
244  SDL_memcpy(data, report, SDL_min(size, sizeof(report)));
245  return SDL_TRUE;
246 }
247 
248 static SDL_bool CheckUSBConnected(hid_device *dev)
249 {
250  int i;
251  Uint8 data[16];
252 
253  /* This will fail if we're on Bluetooth */
254  if (ReadFeatureReport(dev, k_ePS4FeatureReportIdSerialNumber, data, sizeof(data))) {
255  for (i = 0; i < sizeof(data); ++i) {
256  if (data[i] != 0x00) {
257  return SDL_TRUE;
258  }
259  }
260  /* Maybe the dongle without a connected controller? */
261  }
262  return SDL_FALSE;
263 }
264 
265 static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
266 {
267  /* The Razer Panthera fight stick hangs when trying to rumble */
268  if (vendor_id == RAZER_USB_VID &&
269  (product_id == RAZER_PANTHERA_PID || product_id == RAZER_PANTHERA_EVO_PID)) {
270  return SDL_FALSE;
271  }
272  return SDL_TRUE;
273 }
274 
275 static int HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
276 
277 static SDL_bool
278 HIDAPI_DriverPS4_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
279 {
280  SDL_DriverPS4_Context *ctx;
281 
282  ctx = (SDL_DriverPS4_Context *)SDL_calloc(1, sizeof(*ctx));
283  if (!ctx) {
284  SDL_OutOfMemory();
285  return SDL_FALSE;
286  }
287  *context = ctx;
288 
289  /* Check for type of connection */
290  ctx->is_dongle = (vendor_id == SONY_USB_VID && product_id == SONY_DS4_DONGLE_PID);
291  if (ctx->is_dongle) {
292  ctx->is_bluetooth = SDL_FALSE;
293  } else if (vendor_id == SONY_USB_VID) {
294  ctx->is_bluetooth = !CheckUSBConnected(dev);
295  } else {
296  /* Third party controllers appear to all be wired */
297  ctx->is_bluetooth = SDL_FALSE;
298  }
299 #ifdef DEBUG_PS4
300  SDL_Log("PS4 dongle = %s, bluetooth = %s\n", ctx->is_dongle ? "TRUE" : "FALSE", ctx->is_bluetooth ? "TRUE" : "FALSE");
301 #endif
302 
303  /* Check to see if audio is supported */
304  if (vendor_id == SONY_USB_VID &&
305  (product_id == SONY_DS4_SLIM_PID || product_id == SONY_DS4_DONGLE_PID )) {
306  ctx->audio_supported = SDL_TRUE;
307  }
308 
309  if (HIDAPI_DriverPS4_CanRumble(vendor_id, product_id)) {
310  if (ctx->is_bluetooth) {
312  } else {
313  ctx->rumble_supported = SDL_TRUE;
314  }
315  }
316 
317  /* Initialize LED and effect state */
318  HIDAPI_DriverPS4_Rumble(joystick, dev, ctx, 0, 0, 0);
319 
320  /* Initialize the joystick capabilities */
321  joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
322  joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
323  joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
324 
325  return SDL_TRUE;
326 }
327 
328 static int
329 HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
330 {
331  SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
332  DS4EffectsState_t *effects;
333  Uint8 data[78];
334  int report_size, offset;
335 
336  if (!ctx->rumble_supported) {
337  return SDL_Unsupported();
338  }
339 
340  /* In order to send rumble, we have to send a complete effect packet */
341  SDL_memset(data, 0, sizeof(data));
342 
343  if (ctx->is_bluetooth) {
344  data[0] = k_EPS4ReportIdBluetoothEffects;
345  data[1] = 0xC0 | 0x04; /* Magic value HID + CRC, also sets interval to 4ms for samples */
346  data[3] = 0x03; /* 0x1 is rumble, 0x2 is lightbar, 0x4 is the blink interval */
347 
348  report_size = 78;
349  offset = 6;
350  } else {
351  data[0] = k_EPS4ReportIdUsbEffects;
352  data[1] = 0x07; /* Magic value */
353 
354  report_size = 32;
355  offset = 4;
356  }
357  effects = (DS4EffectsState_t *)&data[offset];
358 
359  effects->ucRumbleLeft = (low_frequency_rumble >> 8);
360  effects->ucRumbleRight = (high_frequency_rumble >> 8);
361 
362  effects->ucLedRed = 0;
363  effects->ucLedGreen = 0;
364  effects->ucLedBlue = 80;
365 
366  if (ctx->audio_supported) {
367  Uint32 now = SDL_GetTicks();
368  if (!ctx->last_volume_check ||
369  SDL_TICKS_PASSED(now, ctx->last_volume_check + VOLUME_CHECK_INTERVAL_MS)) {
370  ctx->volume = GetPlaystationVolumeFromFloat(GetSystemVolume());
371  ctx->last_volume_check = now;
372  }
373 
374  effects->ucVolumeRight = ctx->volume;
375  effects->ucVolumeLeft = ctx->volume;
376  effects->ucVolumeSpeaker = ctx->volume;
377  effects->ucVolumeMic = 0xFF;
378  }
379 
380  if (ctx->is_bluetooth) {
381  /* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */
382  Uint8 ubHdr = 0xA2; /* hidp header is part of the CRC calculation */
383  Uint32 unCRC;
384  unCRC = crc32(0, &ubHdr, 1);
385  unCRC = crc32(unCRC, data, (Uint32)(report_size - sizeof(unCRC)));
386  SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC));
387  }
388 
389  if (hid_write(dev, data, report_size) != report_size) {
390  return SDL_SetError("Couldn't send rumble packet");
391  }
392 
393  if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
394  ctx->rumble_expiration = SDL_GetTicks() + duration_ms;
395  } else {
396  ctx->rumble_expiration = 0;
397  }
398  return 0;
399 }
400 
401 static void
402 HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
403 {
404  Sint16 axis;
405 
406  if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
407  {
408  Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
409 
414  }
415  {
416  Uint8 data = (packet->rgucButtonsHatAndCounter[0] & 0x0F);
417  SDL_bool dpad_up = SDL_FALSE;
418  SDL_bool dpad_down = SDL_FALSE;
419  SDL_bool dpad_left = SDL_FALSE;
420  SDL_bool dpad_right = SDL_FALSE;
421 
422  switch (data) {
423  case 0:
424  dpad_up = SDL_TRUE;
425  break;
426  case 1:
427  dpad_up = SDL_TRUE;
428  dpad_right = SDL_TRUE;
429  break;
430  case 2:
431  dpad_right = SDL_TRUE;
432  break;
433  case 3:
434  dpad_right = SDL_TRUE;
435  dpad_down = SDL_TRUE;
436  break;
437  case 4:
438  dpad_down = SDL_TRUE;
439  break;
440  case 5:
441  dpad_left = SDL_TRUE;
442  dpad_down = SDL_TRUE;
443  break;
444  case 6:
445  dpad_left = SDL_TRUE;
446  break;
447  case 7:
448  dpad_up = SDL_TRUE;
449  dpad_left = SDL_TRUE;
450  break;
451  default:
452  break;
453  }
458  }
459  }
460 
461  if (ctx->last_state.rgucButtonsHatAndCounter[1] != packet->rgucButtonsHatAndCounter[1]) {
462  Uint8 data = packet->rgucButtonsHatAndCounter[1];
463 
470  }
471 
472  if (ctx->last_state.rgucButtonsHatAndCounter[2] != packet->rgucButtonsHatAndCounter[2]) {
473  Uint8 data = (packet->rgucButtonsHatAndCounter[2] & 0x03);
474 
476  }
477 
478  axis = ((int)packet->ucTriggerLeft * 257) - 32768;
480  axis = ((int)packet->ucTriggerRight * 257) - 32768;
482  axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
484  axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
486  axis = ((int)packet->ucRightJoystickX * 257) - 32768;
488  axis = ((int)packet->ucRightJoystickY * 257) - 32768;
490 
491  if (packet->ucBatteryLevel & 0x10) {
492  joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
493  } else {
494  /* Battery level ranges from 0 to 10 */
495  int level = (packet->ucBatteryLevel & 0xF);
496  if (level == 0) {
497  joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
498  } else if (level <= 2) {
499  joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
500  } else if (level <= 7) {
501  joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
502  } else {
503  joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
504  }
505  }
506 
507  SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
508 }
509 
510 static SDL_bool
511 HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
512 {
513  SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
514  Uint8 data[USB_PACKET_LENGTH];
515  int size;
516 
517  while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
518  switch (data[0]) {
519  case k_EPS4ReportIdUsbState:
520  HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[1]);
521  break;
522  case k_EPS4ReportIdBluetoothState:
523  /* Bluetooth state packets have two additional bytes at the beginning */
524  HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[3]);
525  break;
526  default:
527 #ifdef DEBUG_JOYSTICK
528  SDL_Log("Unknown PS4 packet: 0x%.2x\n", data[0]);
529 #endif
530  break;
531  }
532  }
533 
534  if (ctx->rumble_expiration) {
535  Uint32 now = SDL_GetTicks();
536  if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
537  HIDAPI_DriverPS4_Rumble(joystick, dev, context, 0, 0, 0);
538  }
539  }
540 
541  return (size >= 0);
542 }
543 
544 static void
545 HIDAPI_DriverPS4_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
546 {
547  SDL_free(context);
548 }
549 
551 {
553  SDL_TRUE,
554  HIDAPI_DriverPS4_IsSupportedDevice,
555  HIDAPI_DriverPS4_GetDeviceName,
556  HIDAPI_DriverPS4_Init,
557  HIDAPI_DriverPS4_Rumble,
558  HIDAPI_DriverPS4_Update,
559  HIDAPI_DriverPS4_Quit
560 };
561 
562 #endif /* SDL_JOYSTICK_HIDAPI_PS4 */
563 
564 #endif /* SDL_JOYSTICK_HIDAPI */
565 
566 /* vi: set ts=4 sw=4 expandtab: */
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4
#define SDL_HINT_JOYSTICK_HIDAPI_PS4
A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
Definition: SDL_hints.h:498
SDL_bool SDL_IsJoystickPS4(Uint16 vendor, Uint16 product)
GLint level
Definition: SDL_opengl.h:1572
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
int16_t Sint16
Definition: SDL_stdinc.h:185
SDL_Joystick * joystick
uint8_t Uint8
Definition: SDL_stdinc.h:179
static screen_context_t context
Definition: video.c:25
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:961
GLfloat f
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLintptr offset
#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE
A variable controlling whether extended input reports should be used for PS4 controllers when using t...
Definition: SDL_hints.h:513
SDL_Texture * axis
uint32_t Uint32
Definition: SDL_stdinc.h:203
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:828
#define SDL_GetHintBoolean
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
#define SDL_Log
#define SDL_memcpy
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
HRESULT WIN_CoInitialize(void)
#define SDL_free
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.
#define SDL_logf
GLsizeiptr size
struct hid_device_ hid_device
Definition: hidapi.h:50
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
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:161
void WIN_CoUninitialize(void)
unsigned char uint8_t
#define SUCCEEDED(x)
Definition: SDL_directx.h:51
#define SDL_SetError
#define SDL_calloc
uint16_t Uint16
Definition: SDL_stdinc.h:191
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_memset
EGLContext ctx
Definition: eglext.h:208