SDL 2.0
SDL_hidapi_ps4.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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"
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
53typedef 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
62typedef enum
63{
64 k_ePS4FeatureReportIdGyroCalibration_USB = 0x02,
65 k_ePS4FeatureReportIdGyroCalibration_BT = 0x05,
66 k_ePS4FeatureReportIdSerialNumber = 0x12,
67} EPS4FeatureReportID;
68
69typedef 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
94typedef 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
110typedef 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;
117 Uint32 rumble_expiration;
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*/
125static 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
134static 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}}
165DEFINE_GUID(SDL_CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
166DEFINE_GUID(SDL_IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
167DEFINE_GUID(SDL_IID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A);
168#endif
169
170
171
172static 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
206static 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
220static SDL_bool
221HIDAPI_DriverPS4_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number)
222{
223 return SDL_IsJoystickPS4(vendor_id, product_id);
224}
225
226static const char *
227HIDAPI_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
235static 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
248static 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
265static 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
275static int HIDAPI_DriverPS4_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
276
277static SDL_bool
278HIDAPI_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) {
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 = 16;
322 joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
323 joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
324
325 return SDL_TRUE;
326}
327
328static int
329HIDAPI_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
401static void
402HIDAPI_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 SDL_PrivateJoystickButton(joystick, 15, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
477 }
478
479 axis = ((int)packet->ucTriggerLeft * 257) - 32768;
481 axis = ((int)packet->ucTriggerRight * 257) - 32768;
483 axis = ((int)packet->ucLeftJoystickX * 257) - 32768;
485 axis = ((int)packet->ucLeftJoystickY * 257) - 32768;
487 axis = ((int)packet->ucRightJoystickX * 257) - 32768;
489 axis = ((int)packet->ucRightJoystickY * 257) - 32768;
491
492 if (packet->ucBatteryLevel & 0x10) {
493 joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
494 } else {
495 /* Battery level ranges from 0 to 10 */
496 int level = (packet->ucBatteryLevel & 0xF);
497 if (level == 0) {
498 joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
499 } else if (level <= 2) {
500 joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
501 } else if (level <= 7) {
502 joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
503 } else {
504 joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
505 }
506 }
507
508 SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
509}
510
511static SDL_bool
512HIDAPI_DriverPS4_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
513{
514 SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)context;
515 Uint8 data[USB_PACKET_LENGTH];
516 int size;
517
518 while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
519 switch (data[0]) {
520 case k_EPS4ReportIdUsbState:
521 HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[1]);
522 break;
523 case k_EPS4ReportIdBluetoothState:
524 /* Bluetooth state packets have two additional bytes at the beginning */
525 HIDAPI_DriverPS4_HandleStatePacket(joystick, dev, ctx, (PS4StatePacket_t *)&data[3]);
526 break;
527 default:
528#ifdef DEBUG_JOYSTICK
529 SDL_Log("Unknown PS4 packet: 0x%.2x\n", data[0]);
530#endif
531 break;
532 }
533 }
534
535 if (ctx->rumble_expiration) {
536 Uint32 now = SDL_GetTicks();
537 if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
538 HIDAPI_DriverPS4_Rumble(joystick, dev, context, 0, 0, 0);
539 }
540 }
541
542 return (size >= 0);
543}
544
545static void
546HIDAPI_DriverPS4_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
547{
549}
550
552{
554 SDL_TRUE,
555 HIDAPI_DriverPS4_IsSupportedDevice,
556 HIDAPI_DriverPS4_GetDeviceName,
557 HIDAPI_DriverPS4_Init,
558 HIDAPI_DriverPS4_Rumble,
559 HIDAPI_DriverPS4_Update,
560 HIDAPI_DriverPS4_Quit
561};
562
563#endif /* SDL_JOYSTICK_HIDAPI_PS4 */
564
565#endif /* SDL_JOYSTICK_HIDAPI */
566
567/* vi: set ts=4 sw=4 expandtab: */
unsigned char uint8_t
#define SUCCEEDED(x)
Definition: SDL_directx.h:51
#define SDL_SetError
#define SDL_memset
#define SDL_logf
#define SDL_free
#define SDL_GetHintBoolean
#define SDL_memcpy
#define SDL_Log
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_PRESSED
Definition: SDL_events.h:50
@ SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_BACK
@ SDL_CONTROLLER_BUTTON_LEFTSTICK
@ SDL_CONTROLLER_BUTTON_START
@ SDL_CONTROLLER_BUTTON_DPAD_LEFT
@ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
@ SDL_CONTROLLER_BUTTON_DPAD_DOWN
@ SDL_CONTROLLER_BUTTON_DPAD_UP
@ SDL_CONTROLLER_BUTTON_LEFTSHOULDER
@ SDL_CONTROLLER_BUTTON_GUIDE
@ SDL_CONTROLLER_BUTTON_DPAD_RIGHT
@ SDL_CONTROLLER_BUTTON_X
@ SDL_CONTROLLER_BUTTON_RIGHTSTICK
@ SDL_CONTROLLER_BUTTON_Y
@ SDL_CONTROLLER_BUTTON_A
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4
#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:533
#define SDL_HINT_JOYSTICK_HIDAPI_PS4
A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
Definition: SDL_hints.h:518
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:833
SDL_bool SDL_IsJoystickPS4(Uint16 vendor, Uint16 product)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:966
@ SDL_JOYSTICK_POWER_FULL
Definition: SDL_joystick.h:103
@ SDL_JOYSTICK_POWER_MEDIUM
Definition: SDL_joystick.h:102
@ SDL_JOYSTICK_POWER_EMPTY
Definition: SDL_joystick.h:100
@ SDL_JOYSTICK_POWER_WIRED
Definition: SDL_joystick.h:104
@ SDL_JOYSTICK_POWER_LOW
Definition: SDL_joystick.h:101
GLint level
Definition: SDL_opengl.h:1572
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLintptr offset
GLsizeiptr size
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
int16_t Sint16
Definition: SDL_stdinc.h:185
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
uint16_t Uint16
Definition: SDL_stdinc.h:191
uint8_t Uint8
Definition: SDL_stdinc.h:179
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
HRESULT WIN_CoInitialize(void)
void WIN_CoUninitialize(void)
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:167
EGLContext ctx
Definition: eglext.h:208
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.
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.
struct hid_device_ hid_device
Definition: hidapi.h:50
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.
SDL_Texture * axis
static screen_context_t context
Definition: video.c:25