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