Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/joystick/hidapi/SDL_hidapi_ps3.c
9913 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
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_c.h"
26
#include "../SDL_sysjoystick.h"
27
#include "SDL_hidapijoystick_c.h"
28
#include "SDL_hidapi_rumble.h"
29
30
#ifdef SDL_JOYSTICK_HIDAPI_PS3
31
32
// Define this if you want to log all packets from the controller
33
// #define DEBUG_PS3_PROTOCOL
34
35
#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
36
37
typedef enum
38
{
39
k_EPS3ReportIdState = 1,
40
k_EPS3ReportIdEffects = 1,
41
} EPS3ReportId;
42
43
typedef enum
44
{
45
k_EPS3SonySixaxisReportIdState = 0,
46
k_EPS3SonySixaxisReportIdEffects = 0,
47
} EPS3SonySixaxisReportId;
48
49
// Commands for Sony's sixaxis.sys Windows driver
50
// All commands must be sent using 49-byte buffer containing output report
51
// Byte 0 indicates reportId and must always be 0
52
// Byte 1 indicates a command, supported values are specified below:
53
typedef enum
54
{
55
// This command allows to set user LEDs.
56
// Bytes 5,6.7.8 contain mode for corresponding LED: 0 - LED is off, 1 - LED in on, 2 - LED is flashing.
57
// Bytes 9-16 specify 64-bit LED flash period in 100 ns units if some LED is flashing, otherwise not used.
58
k_EPS3SixaxisCommandSetLEDs = 1,
59
60
// This command allows to set left and right motors.
61
// Byte 5 is right motor duration (0-255) and byte 6, if not zero, activates right motor. Zero value disables right motor.
62
// Byte 7 is left motor duration (0-255) and byte 8 is left motor amplitude (0-255).
63
k_EPS3SixaxisCommandSetMotors = 2,
64
65
// This command allows to block/unblock setting device LEDs by applications.
66
// Byte 5 is used as parameter - any non-zero value blocks LEDs, zero value will unblock LEDs.
67
k_EPS3SixaxisCommandBlockLEDs = 3,
68
69
// This command refreshes driver settings. No parameters used.
70
// When sixaxis driver loads it reads 'CurrentDriverSetting' binary value from 'HKLM\System\CurrentControlSet\Services\sixaxis\Parameters' registry key.
71
// If the key is not present then default values are used. Sending this command forces sixaxis driver to re-read the registry and update driver settings.
72
k_EPS3SixaxisCommandRefreshDriverSetting = 9,
73
74
// This command clears current bluetooth pairing. No parameters used.
75
k_EPS3SixaxisCommandClearPairing = 10
76
} EPS3SixaxisDriverCommands;
77
78
typedef struct
79
{
80
SDL_HIDAPI_Device *device;
81
SDL_Joystick *joystick;
82
bool is_shanwan;
83
bool has_analog_buttons;
84
bool report_sensors;
85
bool effects_updated;
86
int player_index;
87
Uint8 rumble_left;
88
Uint8 rumble_right;
89
Uint8 last_state[USB_PACKET_LENGTH];
90
} SDL_DriverPS3_Context;
91
92
static bool HIDAPI_DriverPS3_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size);
93
94
static void HIDAPI_DriverPS3_RegisterHints(SDL_HintCallback callback, void *userdata)
95
{
96
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3, callback, userdata);
97
}
98
99
static void HIDAPI_DriverPS3_UnregisterHints(SDL_HintCallback callback, void *userdata)
100
{
101
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3, callback, userdata);
102
}
103
104
static bool HIDAPI_DriverPS3_IsEnabled(void)
105
{
106
bool default_value;
107
108
#ifdef SDL_PLATFORM_MACOS
109
// This works well on macOS
110
default_value = true;
111
#elif defined(SDL_PLATFORM_WIN32)
112
/* For official Sony driver (sixaxis.sys) use SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER.
113
*
114
* See https://github.com/ViGEm/DsHidMini as an alternative driver
115
*/
116
default_value = false;
117
#elif defined(SDL_PLATFORM_LINUX)
118
/* Linux drivers do a better job of managing the transition between
119
* USB and Bluetooth. There are also some quirks in communicating
120
* with PS3 controllers that have been implemented in SDL's hidapi
121
* for libusb, but are not possible to support using hidraw if the
122
* kernel doesn't already know about them.
123
*/
124
default_value = false;
125
#else
126
// Untested, default off
127
default_value = false;
128
#endif
129
130
if (default_value) {
131
default_value = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT);
132
}
133
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3, default_value);
134
}
135
136
static bool HIDAPI_DriverPS3_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
137
{
138
if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) {
139
return true;
140
}
141
if (vendor_id == USB_VENDOR_SHANWAN && product_id == USB_PRODUCT_SHANWAN_DS3) {
142
return true;
143
}
144
return false;
145
}
146
147
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
148
{
149
SDL_memset(report, 0, length);
150
report[0] = report_id;
151
return SDL_hid_get_feature_report(dev, report, length);
152
}
153
154
static int SendFeatureReport(SDL_hid_device *dev, Uint8 *report, size_t length)
155
{
156
return SDL_hid_send_feature_report(dev, report, length);
157
}
158
159
static bool HIDAPI_DriverPS3_InitDevice(SDL_HIDAPI_Device *device)
160
{
161
SDL_DriverPS3_Context *ctx;
162
bool is_shanwan = false;
163
164
if (device->vendor_id == USB_VENDOR_SONY &&
165
SDL_strncasecmp(device->name, "ShanWan", 7) == 0) {
166
is_shanwan = true;
167
}
168
if (device->vendor_id == USB_VENDOR_SHANWAN ||
169
device->vendor_id == USB_VENDOR_SHANWAN_ALT) {
170
is_shanwan = true;
171
}
172
173
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
174
if (!ctx) {
175
return false;
176
}
177
ctx->device = device;
178
ctx->is_shanwan = is_shanwan;
179
ctx->has_analog_buttons = true;
180
181
device->context = ctx;
182
183
// Set the controller into report mode over Bluetooth
184
if (device->is_bluetooth) {
185
Uint8 data[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
186
187
SendFeatureReport(device->dev, data, sizeof(data));
188
}
189
190
// Set the controller into report mode over USB
191
if (!device->is_bluetooth) {
192
Uint8 data[USB_PACKET_LENGTH];
193
194
int size = ReadFeatureReport(device->dev, 0xf2, data, 17);
195
if (size < 0) {
196
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
197
"HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf2");
198
return false;
199
}
200
#ifdef DEBUG_PS3_PROTOCOL
201
HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size);
202
#endif
203
size = ReadFeatureReport(device->dev, 0xf5, data, 8);
204
if (size < 0) {
205
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
206
"HIDAPI_DriverPS3_InitDevice(): Couldn't read feature report 0xf5");
207
return false;
208
}
209
#ifdef DEBUG_PS3_PROTOCOL
210
HIDAPI_DumpPacket("PS3 0xF5 packet: size = %d", data, size);
211
#endif
212
if (!ctx->is_shanwan) {
213
// An output report could cause ShanWan controllers to rumble non-stop
214
SDL_hid_write(device->dev, data, 1);
215
}
216
}
217
218
device->type = SDL_GAMEPAD_TYPE_PS3;
219
HIDAPI_SetDeviceName(device, "PS3 Controller");
220
221
return HIDAPI_JoystickConnected(device, NULL);
222
}
223
224
static int HIDAPI_DriverPS3_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
225
{
226
return -1;
227
}
228
229
static bool HIDAPI_DriverPS3_UpdateEffects(SDL_HIDAPI_Device *device)
230
{
231
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
232
233
Uint8 effects[] = {
234
0x01, 0xff, 0x00, 0xff, 0x00,
235
0x00, 0x00, 0x00, 0x00, 0x00,
236
0xff, 0x27, 0x10, 0x00, 0x32,
237
0xff, 0x27, 0x10, 0x00, 0x32,
238
0xff, 0x27, 0x10, 0x00, 0x32,
239
0xff, 0x27, 0x10, 0x00, 0x32,
240
0x00, 0x00, 0x00, 0x00, 0x00
241
};
242
243
effects[2] = ctx->rumble_right ? 1 : 0;
244
effects[4] = ctx->rumble_left;
245
246
effects[9] = (0x01 << (1 + (ctx->player_index % 4)));
247
248
return HIDAPI_DriverPS3_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects));
249
}
250
251
static void HIDAPI_DriverPS3_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
252
{
253
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
254
255
if (!ctx) {
256
return;
257
}
258
259
ctx->player_index = player_index;
260
261
// This will set the new LED state based on the new player index
262
HIDAPI_DriverPS3_UpdateEffects(device);
263
}
264
265
static bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
266
{
267
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
268
269
SDL_AssertJoysticksLocked();
270
271
ctx->joystick = joystick;
272
ctx->effects_updated = false;
273
ctx->rumble_left = 0;
274
ctx->rumble_right = 0;
275
SDL_zeroa(ctx->last_state);
276
277
// Initialize player index (needed for setting LEDs)
278
ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
279
280
// Initialize the joystick capabilities
281
joystick->nbuttons = 11;
282
joystick->naxes = 6;
283
if (ctx->has_analog_buttons) {
284
joystick->naxes += 10;
285
}
286
joystick->nhats = 1;
287
288
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f);
289
290
return true;
291
}
292
293
static bool HIDAPI_DriverPS3_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
294
{
295
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
296
297
ctx->rumble_left = (low_frequency_rumble >> 8);
298
ctx->rumble_right = (high_frequency_rumble >> 8);
299
300
return HIDAPI_DriverPS3_UpdateEffects(device);
301
}
302
303
static bool HIDAPI_DriverPS3_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
304
{
305
return SDL_Unsupported();
306
}
307
308
static Uint32 HIDAPI_DriverPS3_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
309
{
310
return SDL_JOYSTICK_CAP_RUMBLE;
311
}
312
313
static bool HIDAPI_DriverPS3_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
314
{
315
return SDL_Unsupported();
316
}
317
318
static bool HIDAPI_DriverPS3_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size)
319
{
320
Uint8 data[49];
321
int report_size, offset;
322
323
SDL_zeroa(data);
324
325
data[0] = k_EPS3ReportIdEffects;
326
report_size = sizeof(data);
327
offset = 1;
328
SDL_memcpy(&data[offset], effect, SDL_min((sizeof(data) - offset), (size_t)size));
329
330
if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) {
331
return SDL_SetError("Couldn't send rumble packet");
332
}
333
return true;
334
}
335
336
static bool HIDAPI_DriverPS3_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
337
{
338
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
339
340
ctx->report_sensors = enabled;
341
342
return true;
343
}
344
345
static float HIDAPI_DriverPS3_ScaleAccel(Sint16 value)
346
{
347
// Accelerometer values are in big endian order
348
value = SDL_Swap16BE(value);
349
return ((float)(value - 511) / 113.0f) * SDL_STANDARD_GRAVITY;
350
}
351
352
static void HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size)
353
{
354
Sint16 axis;
355
Uint64 timestamp = SDL_GetTicksNS();
356
357
if (ctx->last_state[4] != data[4]) {
358
Uint8 hat;
359
360
switch (data[4] & 0x0f) {
361
case 0:
362
hat = SDL_HAT_UP;
363
break;
364
case 1:
365
hat = SDL_HAT_RIGHTUP;
366
break;
367
case 2:
368
hat = SDL_HAT_RIGHT;
369
break;
370
case 3:
371
hat = SDL_HAT_RIGHTDOWN;
372
break;
373
case 4:
374
hat = SDL_HAT_DOWN;
375
break;
376
case 5:
377
hat = SDL_HAT_LEFTDOWN;
378
break;
379
case 6:
380
hat = SDL_HAT_LEFT;
381
break;
382
case 7:
383
hat = SDL_HAT_LEFTUP;
384
break;
385
default:
386
hat = SDL_HAT_CENTERED;
387
break;
388
}
389
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
390
391
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[4] & 0x10) != 0));
392
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[4] & 0x20) != 0));
393
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[4] & 0x40) != 0));
394
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[4] & 0x80) != 0));
395
}
396
397
if (ctx->last_state[5] != data[5]) {
398
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[5] & 0x01) != 0));
399
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[5] & 0x02) != 0));
400
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (data[5] & 0x04) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN);
401
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, (data[5] & 0x08) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN);
402
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[5] & 0x10) != 0));
403
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[5] & 0x20) != 0));
404
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[5] & 0x40) != 0));
405
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[5] & 0x80) != 0));
406
}
407
408
axis = ((int)data[2] * 257) - 32768;
409
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
410
axis = ((int)data[3] * 257) - 32768;
411
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
412
axis = ((int)data[0] * 257) - 32768;
413
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
414
axis = ((int)data[1] * 257) - 32768;
415
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
416
417
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
418
}
419
420
static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size)
421
{
422
Sint16 axis;
423
Uint64 timestamp = SDL_GetTicksNS();
424
425
if (ctx->last_state[2] != data[2]) {
426
Uint8 hat = 0;
427
428
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[2] & 0x01) != 0));
429
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[2] & 0x02) != 0));
430
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[2] & 0x04) != 0));
431
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[2] & 0x08) != 0));
432
433
if (data[2] & 0x10) {
434
hat |= SDL_HAT_UP;
435
}
436
if (data[2] & 0x20) {
437
hat |= SDL_HAT_RIGHT;
438
}
439
if (data[2] & 0x40) {
440
hat |= SDL_HAT_DOWN;
441
}
442
if (data[2] & 0x80) {
443
hat |= SDL_HAT_LEFT;
444
}
445
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
446
}
447
448
if (ctx->last_state[3] != data[3]) {
449
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[3] & 0x04) != 0));
450
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[3] & 0x08) != 0));
451
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[3] & 0x10) != 0));
452
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[3] & 0x20) != 0));
453
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[3] & 0x40) != 0));
454
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[3] & 0x80) != 0));
455
}
456
457
if (ctx->last_state[4] != data[4]) {
458
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[4] & 0x01) != 0));
459
}
460
461
axis = ((int)data[18] * 257) - 32768;
462
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
463
axis = ((int)data[19] * 257) - 32768;
464
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
465
axis = ((int)data[6] * 257) - 32768;
466
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
467
axis = ((int)data[7] * 257) - 32768;
468
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
469
axis = ((int)data[8] * 257) - 32768;
470
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
471
axis = ((int)data[9] * 257) - 32768;
472
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
473
474
// Buttons are mapped as axes in the order they appear in the button enumeration
475
if (ctx->has_analog_buttons) {
476
static int button_axis_offsets[] = {
477
24, // SDL_GAMEPAD_BUTTON_SOUTH
478
23, // SDL_GAMEPAD_BUTTON_EAST
479
25, // SDL_GAMEPAD_BUTTON_WEST
480
22, // SDL_GAMEPAD_BUTTON_NORTH
481
0, // SDL_GAMEPAD_BUTTON_BACK
482
0, // SDL_GAMEPAD_BUTTON_GUIDE
483
0, // SDL_GAMEPAD_BUTTON_START
484
0, // SDL_GAMEPAD_BUTTON_LEFT_STICK
485
0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
486
20, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
487
21, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
488
14, // SDL_GAMEPAD_BUTTON_DPAD_UP
489
16, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
490
17, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
491
15, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
492
};
493
Uint8 i, axis_index = 6;
494
495
for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) {
496
int offset = button_axis_offsets[i];
497
if (!offset) {
498
// This button doesn't report as an axis
499
continue;
500
}
501
502
axis = ((int)data[offset] * 257) - 32768;
503
SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis);
504
++axis_index;
505
}
506
}
507
508
if (ctx->report_sensors) {
509
float sensor_data[3];
510
511
sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42]));
512
sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46]));
513
sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44]));
514
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
515
}
516
517
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
518
}
519
520
static bool HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device)
521
{
522
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
523
SDL_Joystick *joystick = NULL;
524
Uint8 data[USB_PACKET_LENGTH];
525
int size;
526
527
if (device->num_joysticks > 0) {
528
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
529
} else {
530
return false;
531
}
532
533
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
534
#ifdef DEBUG_PS3_PROTOCOL
535
HIDAPI_DumpPacket("PS3 packet: size = %d", data, size);
536
#endif
537
if (!joystick) {
538
continue;
539
}
540
541
if (size == 7) {
542
// Seen on a ShanWan PS2 -> PS3 USB converter
543
HIDAPI_DriverPS3_HandleMiniStatePacket(joystick, ctx, data, size);
544
545
// Wait for the first report to set the LED state after the controller stops blinking
546
if (!ctx->effects_updated) {
547
HIDAPI_DriverPS3_UpdateEffects(device);
548
ctx->effects_updated = true;
549
}
550
continue;
551
}
552
553
switch (data[0]) {
554
case k_EPS3ReportIdState:
555
if (data[1] == 0xFF) {
556
// Invalid data packet, ignore
557
break;
558
}
559
HIDAPI_DriverPS3_HandleStatePacket(joystick, ctx, data, size);
560
561
// Wait for the first report to set the LED state after the controller stops blinking
562
if (!ctx->effects_updated) {
563
HIDAPI_DriverPS3_UpdateEffects(device);
564
ctx->effects_updated = true;
565
}
566
break;
567
default:
568
#ifdef DEBUG_JOYSTICK
569
SDL_Log("Unknown PS3 packet: 0x%.2x", data[0]);
570
#endif
571
break;
572
}
573
}
574
575
if (size < 0) {
576
// Read error, device is disconnected
577
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
578
}
579
return (size >= 0);
580
}
581
582
static void HIDAPI_DriverPS3_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
583
{
584
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
585
586
ctx->joystick = NULL;
587
}
588
589
static void HIDAPI_DriverPS3_FreeDevice(SDL_HIDAPI_Device *device)
590
{
591
}
592
593
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3 = {
594
SDL_HINT_JOYSTICK_HIDAPI_PS3,
595
true,
596
HIDAPI_DriverPS3_RegisterHints,
597
HIDAPI_DriverPS3_UnregisterHints,
598
HIDAPI_DriverPS3_IsEnabled,
599
HIDAPI_DriverPS3_IsSupportedDevice,
600
HIDAPI_DriverPS3_InitDevice,
601
HIDAPI_DriverPS3_GetDevicePlayerIndex,
602
HIDAPI_DriverPS3_SetDevicePlayerIndex,
603
HIDAPI_DriverPS3_UpdateDevice,
604
HIDAPI_DriverPS3_OpenJoystick,
605
HIDAPI_DriverPS3_RumbleJoystick,
606
HIDAPI_DriverPS3_RumbleJoystickTriggers,
607
HIDAPI_DriverPS3_GetJoystickCapabilities,
608
HIDAPI_DriverPS3_SetJoystickLED,
609
HIDAPI_DriverPS3_SendJoystickEffect,
610
HIDAPI_DriverPS3_SetJoystickSensorsEnabled,
611
HIDAPI_DriverPS3_CloseJoystick,
612
HIDAPI_DriverPS3_FreeDevice,
613
};
614
615
static bool HIDAPI_DriverPS3ThirdParty_IsEnabled(void)
616
{
617
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3,
618
SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI,
619
SDL_HIDAPI_DEFAULT));
620
}
621
622
static bool HIDAPI_DriverPS3ThirdParty_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
623
{
624
Uint8 data[USB_PACKET_LENGTH];
625
int size;
626
627
if (vendor_id == USB_VENDOR_LOGITECH &&
628
product_id == USB_PRODUCT_LOGITECH_CHILLSTREAM) {
629
return true;
630
}
631
632
if ((type == SDL_GAMEPAD_TYPE_PS3 && vendor_id != USB_VENDOR_SONY) ||
633
HIDAPI_SupportsPlaystationDetection(vendor_id, product_id)) {
634
if (device && device->dev) {
635
size = ReadFeatureReport(device->dev, 0x03, data, sizeof(data));
636
if (size == 8 && data[2] == 0x26) {
637
// Supported third party controller
638
return true;
639
} else {
640
return false;
641
}
642
} else {
643
// Might be supported by this driver, enumerate and find out
644
return true;
645
}
646
}
647
return false;
648
}
649
650
static bool HIDAPI_DriverPS3ThirdParty_InitDevice(SDL_HIDAPI_Device *device)
651
{
652
SDL_DriverPS3_Context *ctx;
653
654
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
655
if (!ctx) {
656
return false;
657
}
658
ctx->device = device;
659
if (device->vendor_id == USB_VENDOR_SWITCH && device->product_id == USB_PRODUCT_SWITCH_RETROBIT_CONTROLLER) {
660
ctx->has_analog_buttons = false;
661
} else {
662
ctx->has_analog_buttons = true;
663
}
664
665
device->context = ctx;
666
667
device->type = SDL_GAMEPAD_TYPE_PS3;
668
669
if (device->vendor_id == USB_VENDOR_LOGITECH &&
670
device->product_id == USB_PRODUCT_LOGITECH_CHILLSTREAM) {
671
HIDAPI_SetDeviceName(device, "Logitech ChillStream");
672
}
673
674
return HIDAPI_JoystickConnected(device, NULL);
675
}
676
677
static int HIDAPI_DriverPS3ThirdParty_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
678
{
679
return -1;
680
}
681
682
static void HIDAPI_DriverPS3ThirdParty_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
683
{
684
}
685
686
static bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
687
{
688
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
689
690
SDL_AssertJoysticksLocked();
691
692
ctx->joystick = joystick;
693
SDL_zeroa(ctx->last_state);
694
695
// Initialize the joystick capabilities
696
joystick->nbuttons = 11;
697
joystick->naxes = 6;
698
if (ctx->has_analog_buttons) {
699
joystick->naxes += 10;
700
}
701
joystick->nhats = 1;
702
703
if (device->vendor_id == USB_VENDOR_SWITCH && device->product_id == USB_PRODUCT_SWITCH_RETROBIT_CONTROLLER) {
704
// This is a wireless controller using a USB dongle
705
joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
706
}
707
708
return true;
709
}
710
711
static bool HIDAPI_DriverPS3ThirdParty_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
712
{
713
return SDL_Unsupported();
714
}
715
716
static bool HIDAPI_DriverPS3ThirdParty_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
717
{
718
return SDL_Unsupported();
719
}
720
721
static Uint32 HIDAPI_DriverPS3ThirdParty_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
722
{
723
return 0;
724
}
725
726
static bool HIDAPI_DriverPS3ThirdParty_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
727
{
728
return SDL_Unsupported();
729
}
730
731
static bool HIDAPI_DriverPS3ThirdParty_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size)
732
{
733
return SDL_Unsupported();
734
}
735
736
static bool HIDAPI_DriverPS3ThirdParty_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
737
{
738
return SDL_Unsupported();
739
}
740
741
static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size)
742
{
743
Sint16 axis;
744
Uint64 timestamp = SDL_GetTicksNS();
745
746
if (ctx->last_state[0] != data[0]) {
747
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x01) != 0));
748
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x02) != 0));
749
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x04) != 0));
750
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x08) != 0));
751
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0));
752
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0));
753
}
754
755
if (ctx->last_state[1] != data[1]) {
756
Uint8 hat;
757
758
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0));
759
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0));
760
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0));
761
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0));
762
763
switch (data[1] >> 4) {
764
case 0:
765
hat = SDL_HAT_UP;
766
break;
767
case 1:
768
hat = SDL_HAT_RIGHTUP;
769
break;
770
case 2:
771
hat = SDL_HAT_RIGHT;
772
break;
773
case 3:
774
hat = SDL_HAT_RIGHTDOWN;
775
break;
776
case 4:
777
hat = SDL_HAT_DOWN;
778
break;
779
case 5:
780
hat = SDL_HAT_LEFTDOWN;
781
break;
782
case 6:
783
hat = SDL_HAT_LEFT;
784
break;
785
case 7:
786
hat = SDL_HAT_LEFTUP;
787
break;
788
default:
789
hat = SDL_HAT_CENTERED;
790
break;
791
}
792
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
793
}
794
795
axis = ((int)data[16] * 257) - 32768;
796
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
797
axis = ((int)data[17] * 257) - 32768;
798
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
799
axis = ((int)data[2] * 257) - 32768;
800
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
801
axis = ((int)data[3] * 257) - 32768;
802
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
803
axis = ((int)data[4] * 257) - 32768;
804
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
805
axis = ((int)data[5] * 257) - 32768;
806
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
807
808
// Buttons are mapped as axes in the order they appear in the button enumeration
809
if (ctx->has_analog_buttons) {
810
static int button_axis_offsets[] = {
811
12, // SDL_GAMEPAD_BUTTON_SOUTH
812
11, // SDL_GAMEPAD_BUTTON_EAST
813
13, // SDL_GAMEPAD_BUTTON_WEST
814
10, // SDL_GAMEPAD_BUTTON_NORTH
815
0, // SDL_GAMEPAD_BUTTON_BACK
816
0, // SDL_GAMEPAD_BUTTON_GUIDE
817
0, // SDL_GAMEPAD_BUTTON_START
818
0, // SDL_GAMEPAD_BUTTON_LEFT_STICK
819
0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
820
14, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
821
15, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
822
8, // SDL_GAMEPAD_BUTTON_DPAD_UP
823
9, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
824
7, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
825
6, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
826
};
827
Uint8 i, axis_index = 6;
828
829
for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) {
830
int offset = button_axis_offsets[i];
831
if (!offset) {
832
// This button doesn't report as an axis
833
continue;
834
}
835
836
axis = ((int)data[offset] * 257) - 32768;
837
SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis);
838
++axis_index;
839
}
840
}
841
842
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
843
}
844
845
static void HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size)
846
{
847
Sint16 axis;
848
Uint64 timestamp = SDL_GetTicksNS();
849
850
if (ctx->last_state[0] != data[0]) {
851
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[0] & 0x01) != 0));
852
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[0] & 0x02) != 0));
853
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[0] & 0x04) != 0));
854
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[0] & 0x08) != 0));
855
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[0] & 0x10) != 0));
856
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[0] & 0x20) != 0));
857
}
858
859
if (ctx->last_state[1] != data[1]) {
860
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[1] & 0x01) != 0));
861
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[1] & 0x02) != 0));
862
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[1] & 0x04) != 0));
863
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[1] & 0x08) != 0));
864
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[1] & 0x10) != 0));
865
}
866
867
if (ctx->device->vendor_id == USB_VENDOR_SAITEK && ctx->device->product_id == USB_PRODUCT_SAITEK_CYBORG_V3) {
868
// Cyborg V.3 Rumble Pad doesn't set the dpad bits as expected, so use the axes instead
869
Uint8 hat = 0;
870
871
if (data[7]) {
872
hat |= SDL_HAT_RIGHT;
873
}
874
if (data[8]) {
875
hat |= SDL_HAT_LEFT;
876
}
877
if (data[9]) {
878
hat |= SDL_HAT_UP;
879
}
880
if (data[10]) {
881
hat |= SDL_HAT_DOWN;
882
}
883
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
884
} else {
885
if (ctx->last_state[2] != data[2]) {
886
Uint8 hat;
887
888
switch (data[2] & 0x0f) {
889
case 0:
890
hat = SDL_HAT_UP;
891
break;
892
case 1:
893
hat = SDL_HAT_RIGHTUP;
894
break;
895
case 2:
896
hat = SDL_HAT_RIGHT;
897
break;
898
case 3:
899
hat = SDL_HAT_RIGHTDOWN;
900
break;
901
case 4:
902
hat = SDL_HAT_DOWN;
903
break;
904
case 5:
905
hat = SDL_HAT_LEFTDOWN;
906
break;
907
case 6:
908
hat = SDL_HAT_LEFT;
909
break;
910
case 7:
911
hat = SDL_HAT_LEFTUP;
912
break;
913
default:
914
hat = SDL_HAT_CENTERED;
915
break;
916
}
917
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
918
}
919
}
920
921
if (data[0] & 0x40) {
922
axis = 32767;
923
} else {
924
axis = ((int)data[17] * 257) - 32768;
925
}
926
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
927
if (data[0] & 0x80) {
928
axis = 32767;
929
} else {
930
axis = ((int)data[18] * 257) - 32768;
931
}
932
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
933
axis = ((int)data[3] * 257) - 32768;
934
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
935
axis = ((int)data[4] * 257) - 32768;
936
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
937
axis = ((int)data[5] * 257) - 32768;
938
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
939
axis = ((int)data[6] * 257) - 32768;
940
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
941
942
// Buttons are mapped as axes in the order they appear in the button enumeration
943
if (ctx->has_analog_buttons) {
944
static int button_axis_offsets[] = {
945
13, // SDL_GAMEPAD_BUTTON_SOUTH
946
12, // SDL_GAMEPAD_BUTTON_EAST
947
14, // SDL_GAMEPAD_BUTTON_WEST
948
11, // SDL_GAMEPAD_BUTTON_NORTH
949
0, // SDL_GAMEPAD_BUTTON_BACK
950
0, // SDL_GAMEPAD_BUTTON_GUIDE
951
0, // SDL_GAMEPAD_BUTTON_START
952
0, // SDL_GAMEPAD_BUTTON_LEFT_STICK
953
0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
954
15, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
955
16, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
956
9, // SDL_GAMEPAD_BUTTON_DPAD_UP
957
10, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
958
8, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
959
7, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
960
};
961
Uint8 i, axis_index = 6;
962
963
for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) {
964
int offset = button_axis_offsets[i];
965
if (!offset) {
966
// This button doesn't report as an axis
967
continue;
968
}
969
970
axis = ((int)data[offset] * 257) - 32768;
971
SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis);
972
++axis_index;
973
}
974
}
975
976
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
977
}
978
979
static bool HIDAPI_DriverPS3ThirdParty_UpdateDevice(SDL_HIDAPI_Device *device)
980
{
981
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
982
SDL_Joystick *joystick = NULL;
983
Uint8 data[USB_PACKET_LENGTH];
984
int size;
985
986
if (device->num_joysticks > 0) {
987
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
988
} else {
989
return false;
990
}
991
992
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
993
#ifdef DEBUG_PS3_PROTOCOL
994
HIDAPI_DumpPacket("PS3 packet: size = %d", data, size);
995
#endif
996
if (!joystick) {
997
continue;
998
}
999
1000
if (size >= 19) {
1001
HIDAPI_DriverPS3ThirdParty_HandleStatePacket19(joystick, ctx, data, size);
1002
} else if (size == 18) {
1003
// This packet format was seen with the Logitech ChillStream
1004
HIDAPI_DriverPS3ThirdParty_HandleStatePacket18(joystick, ctx, data, size);
1005
} else {
1006
#ifdef DEBUG_JOYSTICK
1007
SDL_Log("Unknown PS3 packet, size %d", size);
1008
#endif
1009
}
1010
}
1011
1012
if (size < 0) {
1013
// Read error, device is disconnected
1014
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
1015
}
1016
return (size >= 0);
1017
}
1018
1019
static void HIDAPI_DriverPS3ThirdParty_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1020
{
1021
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1022
1023
ctx->joystick = NULL;
1024
}
1025
1026
static void HIDAPI_DriverPS3ThirdParty_FreeDevice(SDL_HIDAPI_Device *device)
1027
{
1028
}
1029
1030
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3ThirdParty = {
1031
SDL_HINT_JOYSTICK_HIDAPI_PS3,
1032
true,
1033
HIDAPI_DriverPS3_RegisterHints,
1034
HIDAPI_DriverPS3_UnregisterHints,
1035
HIDAPI_DriverPS3ThirdParty_IsEnabled,
1036
HIDAPI_DriverPS3ThirdParty_IsSupportedDevice,
1037
HIDAPI_DriverPS3ThirdParty_InitDevice,
1038
HIDAPI_DriverPS3ThirdParty_GetDevicePlayerIndex,
1039
HIDAPI_DriverPS3ThirdParty_SetDevicePlayerIndex,
1040
HIDAPI_DriverPS3ThirdParty_UpdateDevice,
1041
HIDAPI_DriverPS3ThirdParty_OpenJoystick,
1042
HIDAPI_DriverPS3ThirdParty_RumbleJoystick,
1043
HIDAPI_DriverPS3ThirdParty_RumbleJoystickTriggers,
1044
HIDAPI_DriverPS3ThirdParty_GetJoystickCapabilities,
1045
HIDAPI_DriverPS3ThirdParty_SetJoystickLED,
1046
HIDAPI_DriverPS3ThirdParty_SendJoystickEffect,
1047
HIDAPI_DriverPS3ThirdParty_SetJoystickSensorsEnabled,
1048
HIDAPI_DriverPS3ThirdParty_CloseJoystick,
1049
HIDAPI_DriverPS3ThirdParty_FreeDevice,
1050
};
1051
1052
static bool HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device);
1053
static bool HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device);
1054
1055
static void HIDAPI_DriverPS3SonySixaxis_RegisterHints(SDL_HintCallback callback, void *userdata)
1056
{
1057
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata);
1058
}
1059
1060
static void HIDAPI_DriverPS3SonySixaxis_UnregisterHints(SDL_HintCallback callback, void *userdata)
1061
{
1062
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata);
1063
}
1064
1065
static bool HIDAPI_DriverPS3SonySixaxis_IsEnabled(void)
1066
{
1067
#ifdef SDL_PLATFORM_WIN32
1068
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, false);
1069
#else
1070
return false;
1071
#endif
1072
}
1073
1074
static bool HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
1075
{
1076
if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) {
1077
return true;
1078
}
1079
return false;
1080
}
1081
1082
static bool HIDAPI_DriverPS3SonySixaxis_InitDevice(SDL_HIDAPI_Device *device)
1083
{
1084
SDL_DriverPS3_Context *ctx;
1085
1086
ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx));
1087
if (!ctx) {
1088
return false;
1089
}
1090
ctx->device = device;
1091
ctx->has_analog_buttons = true;
1092
1093
device->context = ctx;
1094
1095
Uint8 data[USB_PACKET_LENGTH];
1096
1097
int size = ReadFeatureReport(device->dev, 0xf2, data, sizeof(data));
1098
if (size < 0) {
1099
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
1100
"HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0xf2. Trying again with 0x0.");
1101
SDL_zeroa(data);
1102
size = ReadFeatureReport(device->dev, 0x00, data, sizeof(data));
1103
if (size < 0) {
1104
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
1105
"HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0x00.");
1106
return false;
1107
}
1108
#ifdef DEBUG_PS3_PROTOCOL
1109
HIDAPI_DumpPacket("PS3 0x0 packet: size = %d", data, size);
1110
#endif
1111
}
1112
#ifdef DEBUG_PS3_PROTOCOL
1113
HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size);
1114
#endif
1115
1116
device->type = SDL_GAMEPAD_TYPE_PS3;
1117
HIDAPI_SetDeviceName(device, "PS3 Controller");
1118
1119
return HIDAPI_JoystickConnected(device, NULL);
1120
}
1121
1122
static int HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
1123
{
1124
return -1;
1125
}
1126
1127
static void HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
1128
{
1129
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1130
1131
if (!ctx) {
1132
return;
1133
}
1134
1135
ctx->player_index = player_index;
1136
1137
// This will set the new LED state based on the new player index
1138
HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device);
1139
}
1140
1141
static bool HIDAPI_DriverPS3SonySixaxis_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1142
{
1143
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1144
1145
SDL_AssertJoysticksLocked();
1146
1147
ctx->joystick = joystick;
1148
ctx->effects_updated = false;
1149
ctx->rumble_left = 0;
1150
ctx->rumble_right = 0;
1151
SDL_zeroa(ctx->last_state);
1152
1153
// Initialize player index (needed for setting LEDs)
1154
ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
1155
1156
// Initialize the joystick capabilities
1157
joystick->nbuttons = 11;
1158
joystick->naxes = 6;
1159
if (ctx->has_analog_buttons) {
1160
joystick->naxes += 10;
1161
}
1162
joystick->nhats = 1;
1163
1164
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f);
1165
1166
return true;
1167
}
1168
1169
static bool HIDAPI_DriverPS3SonySixaxis_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
1170
{
1171
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1172
1173
ctx->rumble_left = (low_frequency_rumble >> 8);
1174
ctx->rumble_right = (high_frequency_rumble >> 8);
1175
1176
return HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(device);
1177
}
1178
1179
static bool HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
1180
{
1181
return SDL_Unsupported();
1182
}
1183
1184
static Uint32 HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1185
{
1186
return 0;
1187
}
1188
1189
static bool HIDAPI_DriverPS3SonySixaxis_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
1190
{
1191
return SDL_Unsupported();
1192
}
1193
1194
static bool HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size)
1195
{
1196
Uint8 data[49];
1197
int report_size;
1198
1199
SDL_zeroa(data);
1200
1201
data[0] = k_EPS3SonySixaxisReportIdEffects;
1202
report_size = sizeof(data);
1203
1204
// No offset with Sony sixaxis.sys driver
1205
SDL_memcpy(&data, effect, SDL_min(sizeof(data), (size_t)size));
1206
1207
if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) {
1208
return SDL_SetError("Couldn't send rumble packet");
1209
}
1210
return true;
1211
}
1212
1213
static bool HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
1214
{
1215
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1216
1217
ctx->report_sensors = enabled;
1218
1219
return true;
1220
}
1221
1222
static void HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size)
1223
{
1224
Sint16 axis;
1225
Uint64 timestamp = SDL_GetTicksNS();
1226
1227
if (ctx->last_state[2] != data[2]) {
1228
Uint8 hat = 0;
1229
1230
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[2] & 0x01) != 0));
1231
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[2] & 0x02) != 0));
1232
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[2] & 0x04) != 0));
1233
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[2] & 0x08) != 0));
1234
1235
if (data[2] & 0x10) {
1236
hat |= SDL_HAT_UP;
1237
}
1238
if (data[2] & 0x20) {
1239
hat |= SDL_HAT_RIGHT;
1240
}
1241
if (data[2] & 0x40) {
1242
hat |= SDL_HAT_DOWN;
1243
}
1244
if (data[2] & 0x80) {
1245
hat |= SDL_HAT_LEFT;
1246
}
1247
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
1248
}
1249
1250
if (ctx->last_state[3] != data[3]) {
1251
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[3] & 0x04) != 0));
1252
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[3] & 0x08) != 0));
1253
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[3] & 0x10) != 0));
1254
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[3] & 0x20) != 0));
1255
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[3] & 0x40) != 0));
1256
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[3] & 0x80) != 0));
1257
}
1258
1259
if (ctx->last_state[4] != data[4]) {
1260
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[4] & 0x01) != 0));
1261
}
1262
1263
axis = ((int)data[18] * 257) - 32768;
1264
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
1265
axis = ((int)data[19] * 257) - 32768;
1266
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
1267
axis = ((int)data[6] * 257) - 32768;
1268
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
1269
axis = ((int)data[7] * 257) - 32768;
1270
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
1271
axis = ((int)data[8] * 257) - 32768;
1272
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
1273
axis = ((int)data[9] * 257) - 32768;
1274
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
1275
1276
// Buttons are mapped as axes in the order they appear in the button enumeration
1277
if (ctx->has_analog_buttons) {
1278
static int button_axis_offsets[] = {
1279
24, // SDL_GAMEPAD_BUTTON_SOUTH
1280
23, // SDL_GAMEPAD_BUTTON_EAST
1281
25, // SDL_GAMEPAD_BUTTON_WEST
1282
22, // SDL_GAMEPAD_BUTTON_NORTH
1283
0, // SDL_GAMEPAD_BUTTON_BACK
1284
0, // SDL_GAMEPAD_BUTTON_GUIDE
1285
0, // SDL_GAMEPAD_BUTTON_START
1286
0, // SDL_GAMEPAD_BUTTON_LEFT_STICK
1287
0, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
1288
20, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
1289
21, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
1290
14, // SDL_GAMEPAD_BUTTON_DPAD_UP
1291
16, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
1292
17, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
1293
15, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
1294
};
1295
Uint8 i, axis_index = 6;
1296
1297
for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) {
1298
int offset = button_axis_offsets[i];
1299
if (!offset) {
1300
// This button doesn't report as an axis
1301
continue;
1302
}
1303
1304
axis = ((int)data[offset] * 257) - 32768;
1305
SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis);
1306
++axis_index;
1307
}
1308
}
1309
1310
if (ctx->report_sensors) {
1311
float sensor_data[3];
1312
1313
sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42]));
1314
sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46]));
1315
sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44]));
1316
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
1317
}
1318
1319
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
1320
}
1321
1322
static bool HIDAPI_DriverPS3SonySixaxis_UpdateDevice(SDL_HIDAPI_Device *device)
1323
{
1324
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1325
SDL_Joystick *joystick = NULL;
1326
Uint8 data[USB_PACKET_LENGTH];
1327
int size;
1328
1329
if (device->num_joysticks > 0) {
1330
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
1331
} else {
1332
return false;
1333
}
1334
1335
if (!joystick) {
1336
return false;
1337
}
1338
1339
// With sixaxis.sys driver we need to use hid_get_feature_report instead of hid_read
1340
size = ReadFeatureReport(device->dev, 0x0, data, sizeof(data));
1341
if (size < 0) {
1342
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
1343
"HIDAPI_DriverPS3SonySixaxis_UpdateDevice(): Couldn't read feature report 0x00");
1344
return false;
1345
}
1346
1347
switch (data[0]) {
1348
case k_EPS3SonySixaxisReportIdState:
1349
HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(joystick, ctx, &data[1], size - 1); // report data starts in data[1]
1350
1351
// Wait for the first report to set the LED state after the controller stops blinking
1352
if (!ctx->effects_updated) {
1353
HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device);
1354
ctx->effects_updated = true;
1355
}
1356
1357
break;
1358
default:
1359
#ifdef DEBUG_JOYSTICK
1360
SDL_Log("Unknown PS3 packet: 0x%.2x", data[0]);
1361
#endif
1362
break;
1363
}
1364
1365
if (size < 0) {
1366
// Read error, device is disconnected
1367
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
1368
}
1369
return (size >= 0);
1370
}
1371
1372
static void HIDAPI_DriverPS3SonySixaxis_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1373
{
1374
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1375
1376
ctx->joystick = NULL;
1377
}
1378
1379
static void HIDAPI_DriverPS3SonySixaxis_FreeDevice(SDL_HIDAPI_Device *device)
1380
{
1381
}
1382
1383
static bool HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device)
1384
{
1385
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1386
1387
Uint8 effects[] = {
1388
0x0, // Report Id
1389
k_EPS3SixaxisCommandSetMotors, // 2 = Set Motors
1390
0x00, 0x00, 0x00, // padding
1391
0xff, // Small Motor duration - 0xff is forever
1392
0x00, // Small Motor off/on (0 or 1)
1393
0xff, // Large Motor duration - 0xff is forever
1394
0x00 // Large Motor force (0 to 255)
1395
};
1396
1397
effects[6] = ctx->rumble_right ? 1 : 0; // Small motor
1398
effects[8] = ctx->rumble_left; // Large motor
1399
1400
return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects));
1401
}
1402
1403
static bool HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device)
1404
{
1405
SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context;
1406
1407
Uint8 effects[] = {
1408
0x0, // Report Id
1409
k_EPS3SixaxisCommandSetLEDs, // 1 = Set LEDs
1410
0x00, 0x00, 0x00, // padding
1411
0x00, 0x00, 0x00, 0x00 // LED #4, LED #3, LED #2, LED #1 (0 = Off, 1 = On, 2 = Flashing)
1412
};
1413
1414
// Turn on LED light on DS3 Controller for relevant player (player_index 0 lights up LED #1, player_index 1 lights up LED #2, etc)
1415
if (ctx->player_index < 4) {
1416
effects[8 - ctx->player_index] = 1;
1417
}
1418
1419
return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects));
1420
}
1421
1422
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3SonySixaxis = {
1423
SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER,
1424
true,
1425
HIDAPI_DriverPS3SonySixaxis_RegisterHints,
1426
HIDAPI_DriverPS3SonySixaxis_UnregisterHints,
1427
HIDAPI_DriverPS3SonySixaxis_IsEnabled,
1428
HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice,
1429
HIDAPI_DriverPS3SonySixaxis_InitDevice,
1430
HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex,
1431
HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex,
1432
HIDAPI_DriverPS3SonySixaxis_UpdateDevice,
1433
HIDAPI_DriverPS3SonySixaxis_OpenJoystick,
1434
HIDAPI_DriverPS3SonySixaxis_RumbleJoystick,
1435
HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers,
1436
HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities,
1437
HIDAPI_DriverPS3SonySixaxis_SetJoystickLED,
1438
HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect,
1439
HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled,
1440
HIDAPI_DriverPS3SonySixaxis_CloseJoystick,
1441
HIDAPI_DriverPS3SonySixaxis_FreeDevice,
1442
};
1443
1444
#endif // SDL_JOYSTICK_HIDAPI_PS3
1445
1446
#endif // SDL_JOYSTICK_HIDAPI
1447
1448