Skip to content

Latest commit

 

History

History
564 lines (481 loc) · 18.3 KB

SDL_hidapi_ps4.c

File metadata and controls

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