1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22
23 #ifdef SDL_JOYSTICK_HIDAPI
24
25 #include "SDL_hints.h"
26 #include "SDL_events.h"
27 #include "SDL_timer.h"
28 #include "SDL_joystick.h"
29 #include "SDL_gamecontroller.h"
30 #include "../SDL_sysjoystick.h"
31 #include "SDL_hidapijoystick_c.h"
32 #include "SDL_hidapi_rumble.h"
33
34
35 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
36
37 /* Define this if you want to log all packets from the controller */
38 /*#define DEBUG_XBOX_PROTOCOL*/
39
40 /* The amount of time to wait after hotplug to send controller init sequence */
41 #define CONTROLLER_INIT_DELAY_MS 1500 /* 475 for Xbox One S, 1275 for the PDP Battlefield 1 */
42
43 /* The amount of time to wait after init for valid input */
44 #define CONTROLLER_INPUT_DELAY_MS 50 /* 42 for Razer Wolverine Ultimate */
45
46 /* Connect controller */
47 static const Uint8 xboxone_init0[] = {
48 0x04, 0x20, 0x00, 0x00
49 };
50 /* Initial ack */
51 static const Uint8 xboxone_init1[] = {
52 0x01, 0x20, 0x01, 0x09, 0x00, 0x04, 0x20, 0x3a,
53 0x00, 0x00, 0x00, 0x80, 0x00
54 };
55 /* Start controller - extended? */
56 static const Uint8 xboxone_init2[] = {
57 0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00
60 };
61 /* Start controller with input */
62 static const Uint8 xboxone_init3[] = {
63 0x05, 0x20, 0x03, 0x01, 0x00
64 };
65 /* Enable LED */
66 static const Uint8 xboxone_init4[] = {
67 0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
68 };
69 /* Start input reports? */
70 static const Uint8 xboxone_init5[] = {
71 0x06, 0x20, 0x00, 0x02, 0x01, 0x00
72 };
73 /* Start rumble? */
74 static const Uint8 xboxone_init6[] = {
75 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
76 0x00, 0x00, 0xFF, 0x00, 0xEB
77 };
78
79 /*
80 * This specifies the selection of init packets that a gamepad
81 * will be sent on init *and* the order in which they will be
82 * sent. The correct sequence number will be added when the
83 * packet is going to be sent.
84 */
85 typedef struct {
86 Uint16 vendor_id;
87 Uint16 product_id;
88 Uint16 exclude_vendor_id;
89 Uint16 exclude_product_id;
90 const Uint8 *data;
91 int size;
92 const Uint8 response[2];
93 } SDL_DriverXboxOne_InitPacket;
94
95
96 static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
97 { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x04, 0xf0 } },
98 { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init1, sizeof(xboxone_init1), { 0x04, 0xb0 } },
99 { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init2, sizeof(xboxone_init2), { 0x00, 0x00 } },
100 { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init3, sizeof(xboxone_init3), { 0x00, 0x00 } },
101 { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
102
103 /* These next packets are required for third party controllers (PowerA, PDP, HORI),
104 but aren't the correct protocol for Microsoft Xbox controllers.
105 */
106 { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
107 { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init6, sizeof(xboxone_init6), { 0x00, 0x00 } },
108 };
109
110 typedef enum {
111 XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN,
112 XBOX_ONE_WIRELESS_PROTOCOL_V1,
113 XBOX_ONE_WIRELESS_PROTOCOL_V2,
114 } SDL_XboxOneWirelessProtocol;
115
116 typedef struct {
117 Uint16 vendor_id;
118 Uint16 product_id;
119 SDL_bool bluetooth;
120 SDL_XboxOneWirelessProtocol wireless_protocol;
121 SDL_bool initialized;
122 SDL_bool input_ready;
123 Uint32 start_time;
124 Uint32 initialized_time;
125 Uint8 sequence;
126 Uint8 last_state[USB_PACKET_LENGTH];
127 SDL_bool has_paddles;
128 } SDL_DriverXboxOne_Context;
129
130
131 #ifdef DEBUG_XBOX_PROTOCOL
132 static void
DumpPacket(const char * prefix,Uint8 * data,int size)133 DumpPacket(const char *prefix, Uint8 *data, int size)
134 {
135 int i;
136 char *buffer;
137 size_t length = SDL_strlen(prefix) + 11*(USB_PACKET_LENGTH/8) + (5*USB_PACKET_LENGTH) + 1 + 1;
138
139 buffer = (char *)SDL_malloc(length);
140 SDL_snprintf(buffer, length, prefix, size);
141 for (i = 0; i < size; ++i) {
142 if ((i % 8) == 0) {
143 SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), "\n%.2d: ", i);
144 }
145 SDL_snprintf(&buffer[SDL_strlen(buffer)], length - SDL_strlen(buffer), " 0x%.2x", data[i]);
146 }
147 SDL_strlcat(buffer, "\n", length);
148 SDL_Log("%s", buffer);
149 SDL_free(buffer);
150 }
151 #endif /* DEBUG_XBOX_PROTOCOL */
152
153 static SDL_bool
IsBluetoothXboxOneController(Uint16 vendor_id,Uint16 product_id)154 IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
155 {
156 /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
157 if (vendor_id == USB_VENDOR_MICROSOFT) {
158 if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
159 product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
160 product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
161 return SDL_TRUE;
162 }
163 }
164 return SDL_FALSE;
165 }
166
167 static SDL_bool
ControllerHasPaddles(Uint16 vendor_id,Uint16 product_id)168 ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
169 {
170 if (vendor_id == USB_VENDOR_MICROSOFT) {
171 if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
172 product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
173 return SDL_TRUE;
174 }
175 }
176 return SDL_FALSE;
177 }
178
179 /* Return true if this controller sends the 0x02 "waiting for init" packet */
180 static SDL_bool
ControllerSendsWaitingForInit(Uint16 vendor_id,Uint16 product_id)181 ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
182 {
183 if (vendor_id == USB_VENDOR_HYPERKIN) {
184 /* The Hyperkin controllers always send 0x02 when waiting for init,
185 and the Hyperkin Duke plays an Xbox startup animation, so we want
186 to make sure we don't send the init sequence if it isn't needed.
187 */
188 return SDL_TRUE;
189 }
190 if (vendor_id == USB_VENDOR_PDP) {
191 /* The PDP Rock Candy (PID 0x0246) doesn't send 0x02 on Linux for some reason */
192 return SDL_FALSE;
193 }
194
195 /* It doesn't hurt to reinit, especially if a driver has misconfigured the controller */
196 /*return SDL_TRUE;*/
197 return SDL_FALSE;
198 }
199
200 static SDL_bool
SendControllerInit(SDL_HIDAPI_Device * device,SDL_DriverXboxOne_Context * ctx)201 SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
202 {
203 Uint16 vendor_id = ctx->vendor_id;
204 Uint16 product_id = ctx->product_id;
205 int i;
206 Uint8 init_packet[USB_PACKET_LENGTH];
207
208 for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
209 const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
210
211 if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
212 continue;
213 }
214
215 if (packet->product_id && (product_id != packet->product_id)) {
216 continue;
217 }
218
219 if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
220 continue;
221 }
222
223 if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
224 continue;
225 }
226
227 SDL_memcpy(init_packet, packet->data, packet->size);
228 if (init_packet[0] != 0x01) {
229 init_packet[2] = ctx->sequence++;
230 }
231 if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
232 SDL_SetError("Couldn't write Xbox One initialization packet");
233 return SDL_FALSE;
234 }
235
236 if (packet->response[0]) {
237 const Uint32 RESPONSE_TIMEOUT_MS = 100;
238 Uint32 start = SDL_GetTicks();
239 SDL_bool got_response = SDL_FALSE;
240
241 while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
242 Uint8 data[USB_PACKET_LENGTH];
243 int size;
244
245 while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
246 #ifdef DEBUG_XBOX_PROTOCOL
247 DumpPacket("Xbox One INIT packet: size = %d", data, size);
248 #endif
249 if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
250 got_response = SDL_TRUE;
251 }
252 }
253 }
254 #ifdef DEBUG_XBOX_PROTOCOL
255 SDL_Log("Init sequence %d got response after %u ms: %s\n", i, (SDL_GetTicks() - start), got_response ? "TRUE" : "FALSE");
256 #endif
257 }
258 }
259 return SDL_TRUE;
260 }
261
262 static SDL_bool
HIDAPI_DriverXboxOne_IsSupportedDevice(const char * name,SDL_GameControllerType type,Uint16 vendor_id,Uint16 product_id,Uint16 version,int interface_number,int interface_class,int interface_subclass,int interface_protocol)263 HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
264 {
265 #ifdef __LINUX__
266 if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
267 /* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
268 return SDL_FALSE;
269 }
270 #endif
271 #ifdef __MACOSX__
272 /* Wired Xbox One controllers are handled by the 360Controller driver */
273 if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
274 return SDL_FALSE;
275 }
276 #endif
277 return (type == SDL_CONTROLLER_TYPE_XBOXONE);
278 }
279
280 static const char *
HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id,Uint16 product_id)281 HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
282 {
283 return NULL;
284 }
285
286 static SDL_bool
HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device * device)287 HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
288 {
289 return HIDAPI_JoystickConnected(device, NULL, SDL_FALSE);
290 }
291
292 static int
HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id)293 HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
294 {
295 return -1;
296 }
297
298 static void
HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device * device,SDL_JoystickID instance_id,int player_index)299 HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
300 {
301 }
302
303 static SDL_bool
HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)304 HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
305 {
306 SDL_DriverXboxOne_Context *ctx;
307
308 ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
309 if (!ctx) {
310 SDL_OutOfMemory();
311 return SDL_FALSE;
312 }
313
314 device->dev = hid_open_path(device->path, 0);
315 if (!device->dev) {
316 SDL_free(ctx);
317 SDL_SetError("Couldn't open %s", device->path);
318 return SDL_FALSE;
319 }
320 device->context = ctx;
321
322 ctx->vendor_id = device->vendor_id;
323 ctx->product_id = device->product_id;
324 ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
325 ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
326 ctx->start_time = SDL_GetTicks();
327 ctx->input_ready = SDL_TRUE;
328 ctx->sequence = 1;
329 ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
330
331 /* Initialize the joystick capabilities */
332 joystick->nbuttons = ctx->has_paddles ? SDL_CONTROLLER_BUTTON_MAX : (SDL_CONTROLLER_BUTTON_MAX + 4);
333 joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
334 joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
335
336 return SDL_TRUE;
337 }
338
339 static int
HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick,Uint16 low_frequency_rumble,Uint16 high_frequency_rumble)340 HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
341 {
342 SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
343
344 if (ctx->bluetooth) {
345 Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
346
347 rumble_packet[4] = (low_frequency_rumble >> 8);
348 rumble_packet[5] = (high_frequency_rumble >> 8);
349
350 if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
351 return SDL_SetError("Couldn't send rumble packet");
352 }
353 } else {
354 Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
355
356 /* Magnitude is 1..100 so scale the 16-bit input here */
357 rumble_packet[8] = low_frequency_rumble / 655;
358 rumble_packet[9] = high_frequency_rumble / 655;
359
360 if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
361 return SDL_SetError("Couldn't send rumble packet");
362 }
363 }
364 return 0;
365 }
366
367 static void
HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick * joystick,hid_device * dev,SDL_DriverXboxOne_Context * ctx,Uint8 * data,int size)368 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
369 {
370 Sint16 axis;
371
372 if (ctx->last_state[4] != data[4]) {
373 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[4] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
374 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[4] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
375 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
376 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
377 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
378 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
379 }
380
381 if (ctx->last_state[5] != data[5]) {
382 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data[5] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
383 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data[5] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
384 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data[5] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
385 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data[5] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
386 if (ctx->vendor_id == USB_VENDOR_RAZER && ctx->product_id == USB_PRODUCT_RAZER_ATROX) {
387 /* The Razer Atrox has the right and left shoulder bits reversed */
388 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
389 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
390 } else {
391 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
392 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
393 }
394 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[5] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
395 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[5] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
396 }
397
398 /* Xbox One S report is 18 bytes
399 Xbox One Elite Series 1 report is 33 bytes, paddles in data[32], mode in data[32] & 0x10, both modes have mapped paddles by default
400 Paddle bits:
401 UL: 0x01 (A) UR: 0x02 (B)
402 LL: 0x04 (X) LR: 0x08 (Y)
403 Xbox One Elite Series 2 report is 38 bytes, paddles in data[18], mode in data[19], mode 0 has no mapped paddles by default
404 Paddle bits:
405 UL: 0x04 (A) UR: 0x01 (B)
406 LL: 0x08 (X) LR: 0x02 (Y)
407 */
408 if (ctx->has_paddles && (size == 33 || size == 38)) {
409 int paddle_index;
410 int button1_bit;
411 int button2_bit;
412 int button3_bit;
413 int button4_bit;
414 SDL_bool paddles_mapped;
415
416 if (size == 33) {
417 /* XBox One Elite Series 1 */
418 paddle_index = 32;
419 button1_bit = 0x01;
420 button2_bit = 0x02;
421 button3_bit = 0x04;
422 button4_bit = 0x08;
423
424 /* The mapped controller state is at offset 4, the raw state is at offset 18, compare them to see if the paddles are mapped */
425 paddles_mapped = (SDL_memcmp(&data[4], &data[18], 14) != 0);
426
427 } else /* if (size == 38) */ {
428 /* XBox One Elite Series 2 */
429 paddle_index = 18;
430 button1_bit = 0x04;
431 button2_bit = 0x01;
432 button3_bit = 0x08;
433 button4_bit = 0x02;
434 paddles_mapped = (data[19] != 0);
435 }
436 #ifdef DEBUG_XBOX_PROTOCOL
437 SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
438 (data[paddle_index] & button1_bit) ? 1 : 0,
439 (data[paddle_index] & button2_bit) ? 1 : 0,
440 (data[paddle_index] & button3_bit) ? 1 : 0,
441 (data[paddle_index] & button4_bit) ? 1 : 0,
442 paddles_mapped ? "TRUE" : "FALSE"
443 );
444 #endif
445
446 if (paddles_mapped) {
447 /* Respect that the paddles are being used for other controls and don't pass them on to the app */
448 data[paddle_index] = 0;
449 }
450
451 if (ctx->last_state[paddle_index] != data[paddle_index]) {
452 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+0, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
453 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+1, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
454 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+2, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
455 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+3, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
456 }
457 }
458
459 axis = ((int)*(Sint16*)(&data[6]) * 64) - 32768;
460 if (axis == 32704) {
461 axis = 32767;
462 }
463 if (axis == -32768 && size == 30 && (data[22] & 0x80) != 0) {
464 axis = 32767;
465 }
466 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
467
468 axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
469 if (axis == -32768 && size == 30 && (data[22] & 0x40) != 0) {
470 axis = 32767;
471 }
472 if (axis == 32704) {
473 axis = 32767;
474 }
475 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
476
477 axis = *(Sint16*)(&data[10]);
478 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
479 axis = *(Sint16*)(&data[12]);
480 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
481 axis = *(Sint16*)(&data[14]);
482 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
483 axis = *(Sint16*)(&data[16]);
484 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
485
486 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
487 }
488
489 static void
HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick * joystick,hid_device * dev,SDL_DriverXboxOne_Context * ctx,Uint8 * data,int size)490 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
491 {
492 if (data[1] == 0x30) {
493 /* The Xbox One S controller needs acks for mode reports */
494 const Uint8 seqnum = data[2];
495 const Uint8 ack[] = { 0x01, 0x20, seqnum, 0x09, 0x00, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
496 hid_write(dev, ack, sizeof(ack));
497 }
498
499 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
500 }
501
502 static void
HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV1(SDL_Joystick * joystick,hid_device * dev,SDL_DriverXboxOne_Context * ctx,Uint8 * data,int size)503 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV1(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
504 {
505 Sint16 axis;
506
507 if (ctx->last_state[14] != data[14]) {
508 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
509 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
510 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
511 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
512 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
513 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
514 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
515 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
516 }
517
518 if (ctx->last_state[15] != data[15]) {
519 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
520 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
521 }
522
523 if (ctx->last_state[13] != data[13]) {
524 SDL_bool dpad_up = SDL_FALSE;
525 SDL_bool dpad_down = SDL_FALSE;
526 SDL_bool dpad_left = SDL_FALSE;
527 SDL_bool dpad_right = SDL_FALSE;
528
529 switch (data[13]) {
530 case 1:
531 dpad_up = SDL_TRUE;
532 break;
533 case 2:
534 dpad_up = SDL_TRUE;
535 dpad_right = SDL_TRUE;
536 break;
537 case 3:
538 dpad_right = SDL_TRUE;
539 break;
540 case 4:
541 dpad_right = SDL_TRUE;
542 dpad_down = SDL_TRUE;
543 break;
544 case 5:
545 dpad_down = SDL_TRUE;
546 break;
547 case 6:
548 dpad_left = SDL_TRUE;
549 dpad_down = SDL_TRUE;
550 break;
551 case 7:
552 dpad_left = SDL_TRUE;
553 break;
554 case 8:
555 dpad_up = SDL_TRUE;
556 dpad_left = SDL_TRUE;
557 break;
558 default:
559 break;
560 }
561 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
562 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
563 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
564 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
565 }
566
567 axis = (int)*(Uint16*)(&data[1]) - 0x8000;
568 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
569 axis = (int)*(Uint16*)(&data[3]) - 0x8000;
570 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
571 axis = (int)*(Uint16*)(&data[5]) - 0x8000;
572 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
573 axis = (int)*(Uint16*)(&data[7]) - 0x8000;
574 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
575
576 axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
577 if (axis == 32704) {
578 axis = 32767;
579 }
580 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
581
582 axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
583 if (axis == 32704) {
584 axis = 32767;
585 }
586 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
587
588 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
589 }
590
591 static void
HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV2(SDL_Joystick * joystick,hid_device * dev,SDL_DriverXboxOne_Context * ctx,Uint8 * data,int size)592 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV2(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
593 {
594 Sint16 axis;
595
596 if (ctx->last_state[14] != data[14]) {
597 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
598 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
599 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
600 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
601 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
602 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
603 }
604
605 if (ctx->last_state[15] != data[15]) {
606 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
607 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
608 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
609 if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN)
610 {
611 if (data[15] & 0x10) {
612 ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V2;
613 }
614 }
615 if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_V2)
616 {
617 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
618 }
619 }
620
621 if (ctx->last_state[16] != data[16]) {
622 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
623 }
624
625 if (ctx->last_state[13] != data[13]) {
626 SDL_bool dpad_up = SDL_FALSE;
627 SDL_bool dpad_down = SDL_FALSE;
628 SDL_bool dpad_left = SDL_FALSE;
629 SDL_bool dpad_right = SDL_FALSE;
630
631 switch (data[13]) {
632 case 1:
633 dpad_up = SDL_TRUE;
634 break;
635 case 2:
636 dpad_up = SDL_TRUE;
637 dpad_right = SDL_TRUE;
638 break;
639 case 3:
640 dpad_right = SDL_TRUE;
641 break;
642 case 4:
643 dpad_right = SDL_TRUE;
644 dpad_down = SDL_TRUE;
645 break;
646 case 5:
647 dpad_down = SDL_TRUE;
648 break;
649 case 6:
650 dpad_left = SDL_TRUE;
651 dpad_down = SDL_TRUE;
652 break;
653 case 7:
654 dpad_left = SDL_TRUE;
655 break;
656 case 8:
657 dpad_up = SDL_TRUE;
658 dpad_left = SDL_TRUE;
659 break;
660 default:
661 break;
662 }
663 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
664 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
665 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
666 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
667 }
668
669 axis = (int)*(Uint16*)(&data[1]) - 0x8000;
670 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
671 axis = (int)*(Uint16*)(&data[3]) - 0x8000;
672 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
673 axis = (int)*(Uint16*)(&data[5]) - 0x8000;
674 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
675 axis = (int)*(Uint16*)(&data[7]) - 0x8000;
676 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
677
678 axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
679 if (axis == 32704) {
680 axis = 32767;
681 }
682 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
683
684 axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
685 if (axis == 32704) {
686 axis = 32767;
687 }
688 SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
689
690 SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
691 }
692
693 static void
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick * joystick,hid_device * dev,SDL_DriverXboxOne_Context * ctx,Uint8 * data,int size)694 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
695 {
696 ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V1;
697 SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
698 }
699
700 static SDL_bool
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device * device)701 HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
702 {
703 SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
704 SDL_Joystick *joystick = NULL;
705 Uint8 data[USB_PACKET_LENGTH];
706 int size;
707
708 if (device->num_joysticks > 0) {
709 joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
710 }
711 if (!joystick) {
712 return SDL_FALSE;
713 }
714
715 if (!ctx->initialized &&
716 !ControllerSendsWaitingForInit(device->vendor_id, device->product_id)) {
717 if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
718 if (!SendControllerInit(device, ctx)) {
719 HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
720 return SDL_FALSE;
721 }
722 ctx->initialized = SDL_TRUE;
723 ctx->initialized_time = SDL_GetTicks();
724 ctx->input_ready = SDL_FALSE;
725 }
726 }
727
728 while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
729 #ifdef DEBUG_XBOX_PROTOCOL
730 DumpPacket("Xbox One packet: size = %d", data, size);
731 #endif
732 if (ctx->bluetooth) {
733 switch (data[0]) {
734 case 0x01:
735 switch (size) {
736 case 16:
737 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV1(joystick, device->dev, ctx, data, size);
738 break;
739 case 17:
740 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV2(joystick, device->dev, ctx, data, size);
741 break;
742 default:
743 break;
744 }
745 break;
746 case 0x02:
747 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
748 break;
749 default:
750 #ifdef DEBUG_JOYSTICK
751 SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
752 #endif
753 break;
754 }
755 } else {
756 switch (data[0]) {
757 case 0x02:
758 /* Controller is connected and waiting for initialization */
759 if (!ctx->initialized) {
760 #ifdef DEBUG_XBOX_PROTOCOL
761 SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
762 #endif
763 if (!SendControllerInit(device, ctx)) {
764 HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
765 return SDL_FALSE;
766 }
767 ctx->initialized = SDL_TRUE;
768 ctx->initialized_time = SDL_GetTicks();
769 ctx->input_ready = SDL_FALSE;
770 }
771 break;
772 case 0x03:
773 /* Controller heartbeat */
774 break;
775 case 0x20:
776 if (!ctx->input_ready) {
777 if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->initialized_time + CONTROLLER_INPUT_DELAY_MS)) {
778 #ifdef DEBUG_XBOX_PROTOCOL
779 SDL_Log("Spurious input at %ums\n", SDL_GetTicks() - ctx->initialized_time);
780 #endif
781 break;
782 }
783 ctx->input_ready = SDL_TRUE;
784 }
785 HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
786 break;
787 case 0x07:
788 HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
789 break;
790 default:
791 #ifdef DEBUG_JOYSTICK
792 SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
793 #endif
794 break;
795 }
796 }
797 }
798
799 if (size < 0) {
800 /* Read error, device is disconnected */
801 HIDAPI_JoystickDisconnected(device, joystick->instance_id, SDL_FALSE);
802 }
803 return (size >= 0);
804 }
805
806 static void
HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device * device,SDL_Joystick * joystick)807 HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
808 {
809 hid_close(device->dev);
810 device->dev = NULL;
811
812 SDL_free(device->context);
813 device->context = NULL;
814 }
815
816 static void
HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device * device)817 HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device *device)
818 {
819 }
820
821 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
822 {
823 SDL_HINT_JOYSTICK_HIDAPI_XBOX,
824 SDL_TRUE,
825 HIDAPI_DriverXboxOne_IsSupportedDevice,
826 HIDAPI_DriverXboxOne_GetDeviceName,
827 HIDAPI_DriverXboxOne_InitDevice,
828 HIDAPI_DriverXboxOne_GetDevicePlayerIndex,
829 HIDAPI_DriverXboxOne_SetDevicePlayerIndex,
830 HIDAPI_DriverXboxOne_UpdateDevice,
831 HIDAPI_DriverXboxOne_OpenJoystick,
832 HIDAPI_DriverXboxOne_RumbleJoystick,
833 HIDAPI_DriverXboxOne_CloseJoystick,
834 HIDAPI_DriverXboxOne_FreeDevice,
835 NULL
836 };
837
838 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
839
840 #endif /* SDL_JOYSTICK_HIDAPI */
841
842 /* vi: set ts=4 sw=4 expandtab: */
843