SDL  2.0
SDL_hidapi_xboxone.c
Go to the documentation of this file.
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_log.h"
27 #include "SDL_events.h"
28 #include "SDL_timer.h"
29 #include "SDL_joystick.h"
30 #include "SDL_gamecontroller.h"
31 #include "../SDL_sysjoystick.h"
32 #include "SDL_hidapijoystick_c.h"
33 #include "SDL_hidapi_rumble.h"
34 
35 
36 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
37 
38 /* Define this if you want to log all packets from the controller */
39 /*#define DEBUG_XBOX_PROTOCOL*/
40 
41 /* The amount of time to wait after hotplug to send controller init sequence */
42 #define CONTROLLER_INIT_DELAY_MS 1500 /* 475 for Xbox One S, 1275 for the PDP Battlefield 1 */
43 
44 /* Connect controller */
45 static const Uint8 xboxone_init0[] = {
46  0x04, 0x20, 0x00, 0x00
47 };
48 /* Initial ack */
49 static const Uint8 xboxone_init1[] = {
50  0x01, 0x20, 0x01, 0x09, 0x00, 0x04, 0x20, 0x3a,
51  0x00, 0x00, 0x00, 0x80, 0x00
52 };
53 /* Start controller - extended? */
54 static const Uint8 xboxone_init2[] = {
55  0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
56  0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
57  0x00, 0x00, 0x00
58 };
59 /* Start controller with input */
60 static const Uint8 xboxone_init3[] = {
61  0x05, 0x20, 0x03, 0x01, 0x00
62 };
63 /* Enable LED */
64 static const Uint8 xboxone_init4[] = {
65  0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
66 };
67 /* Start input reports? */
68 static const Uint8 xboxone_init5[] = {
69  0x06, 0x20, 0x00, 0x02, 0x01, 0x00
70 };
71 /* Start rumble? */
72 static const Uint8 xboxone_init6[] = {
73  0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
74  0x00, 0x00, 0xFF, 0x00, 0xEB
75 };
76 
77 /*
78  * This specifies the selection of init packets that a gamepad
79  * will be sent on init *and* the order in which they will be
80  * sent. The correct sequence number will be added when the
81  * packet is going to be sent.
82  */
83 typedef struct {
84  Uint16 vendor_id;
85  Uint16 product_id;
86  Uint16 exclude_vendor_id;
87  Uint16 exclude_product_id;
88  const Uint8 *data;
89  int size;
90  const Uint8 response[2];
91 } SDL_DriverXboxOne_InitPacket;
92 
93 
94 static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
95  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x04, 0xf0 } },
96  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init1, sizeof(xboxone_init1), { 0x04, 0xb0 } },
97  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init2, sizeof(xboxone_init2), { 0x00, 0x00 } },
98  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init3, sizeof(xboxone_init3), { 0x00, 0x00 } },
99  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
100 
101  /* These next packets are required for third party controllers (PowerA, PDP, HORI),
102  but aren't the correct protocol for Microsoft Xbox controllers.
103  */
104  { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
105  { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init6, sizeof(xboxone_init6), { 0x00, 0x00 } },
106 };
107 
108 typedef enum {
109  XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN,
110  XBOX_ONE_WIRELESS_PROTOCOL_V1,
111  XBOX_ONE_WIRELESS_PROTOCOL_V2,
112 } SDL_XboxOneWirelessProtocol;
113 
114 typedef struct {
115  Uint16 vendor_id;
116  Uint16 product_id;
117  SDL_bool bluetooth;
118  SDL_XboxOneWirelessProtocol wireless_protocol;
119  SDL_bool initialized;
120  Uint32 start_time;
121  Uint8 sequence;
122  Uint8 last_state[USB_PACKET_LENGTH];
123  SDL_bool has_paddles;
124 } SDL_DriverXboxOne_Context;
125 
126 
127 #ifdef DEBUG_XBOX_PROTOCOL
128 static void
129 DumpPacket(const char *prefix, Uint8 *data, int size)
130 {
131  int i;
132  char buffer[5*USB_PACKET_LENGTH];
133 
134  SDL_snprintf(buffer, sizeof(buffer), prefix, size);
135  for (i = 0; i < size; ++i) {
136  if ((i % 8) == 0) {
137  SDL_snprintf(&buffer[SDL_strlen(buffer)], sizeof(buffer) - SDL_strlen(buffer), "\n%.2d: ", i);
138  }
139  SDL_snprintf(&buffer[SDL_strlen(buffer)], sizeof(buffer) - SDL_strlen(buffer), " 0x%.2x", data[i]);
140  }
141  SDL_strlcat(buffer, "\n", sizeof(buffer));
142  SDL_Log("%s", buffer);
143 }
144 #endif /* DEBUG_XBOX_PROTOCOL */
145 
146 static SDL_bool
147 IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
148 {
149  /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
150  if (vendor_id == USB_VENDOR_MICROSOFT) {
151  if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
154  return SDL_TRUE;
155  }
156  }
157  return SDL_FALSE;
158 }
159 
160 static SDL_bool
161 ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
162 {
163  if (vendor_id == USB_VENDOR_MICROSOFT) {
164  if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
165  product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
166  return SDL_TRUE;
167  }
168  }
169  return SDL_FALSE;
170 }
171 
172 /* Return true if this controller sends the 0x02 "waiting for init" packet */
173 static SDL_bool
174 ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
175 {
176  if (vendor_id == USB_VENDOR_HYPERKIN) {
177  /* The Hyperkin controllers always send 0x02 when waiting for init,
178  and the Hyperkin Duke plays an Xbox startup animation, so we want
179  to make sure we don't send the init sequence if it isn't needed.
180  */
181  return SDL_TRUE;
182  }
183  if (vendor_id == USB_VENDOR_PDP) {
184  /* The PDP Rock Candy (PID 0x0246) doesn't send 0x02 on Linux for some reason */
185  return SDL_FALSE;
186  }
187 
188  /* It doesn't hurt to reinit, especially if a driver has misconfigured the controller */
189  /*return SDL_TRUE;*/
190  return SDL_FALSE;
191 }
192 
193 static SDL_bool
194 SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
195 {
196  Uint16 vendor_id = ctx->vendor_id;
197  Uint16 product_id = ctx->product_id;
198  int i;
199  Uint8 init_packet[USB_PACKET_LENGTH];
200 
201  for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
202  const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
203 
204  if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
205  continue;
206  }
207 
208  if (packet->product_id && (product_id != packet->product_id)) {
209  continue;
210  }
211 
212  if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
213  continue;
214  }
215 
216  if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
217  continue;
218  }
219 
220  SDL_memcpy(init_packet, packet->data, packet->size);
221  if (init_packet[0] != 0x01) {
222  init_packet[2] = ctx->sequence++;
223  }
224  if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
225  SDL_SetError("Couldn't write Xbox One initialization packet");
226  return SDL_FALSE;
227  }
228 
229  if (packet->response[0]) {
230  const Uint32 RESPONSE_TIMEOUT_MS = 50;
232  SDL_bool got_response = SDL_FALSE;
233 
234  while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
236  int size;
237 
238  while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
239 #ifdef DEBUG_XBOX_PROTOCOL
240  DumpPacket("Xbox One INIT packet: size = %d", data, size);
241 #endif
242  if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
243  got_response = SDL_TRUE;
244  }
245  }
246  }
247 #ifdef DEBUG_XBOX_PROTOCOL
248  SDL_Log("Init sequence %d got response: %s\n", i, got_response ? "TRUE" : "FALSE");
249 #endif
250  }
251  }
252  return SDL_TRUE;
253 }
254 
255 static SDL_bool
256 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)
257 {
258 #ifdef __LINUX__
259  if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
260  /* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
261  return SDL_FALSE;
262  }
263 #endif
264 #ifdef __MACOSX__
265  /* Wired Xbox One controllers are handled by the 360Controller driver */
266  if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
267  return SDL_FALSE;
268  }
269 #endif
270  return (type == SDL_CONTROLLER_TYPE_XBOXONE);
271 }
272 
273 static const char *
274 HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
275 {
276  return NULL;
277 }
278 
279 static SDL_bool
280 HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
281 {
283 }
284 
285 static int
286 HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
287 {
288  return -1;
289 }
290 
291 static void
292 HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
293 {
294 }
295 
296 static SDL_bool
297 HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
298 {
299  SDL_DriverXboxOne_Context *ctx;
300 
301  ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
302  if (!ctx) {
303  SDL_OutOfMemory();
304  return SDL_FALSE;
305  }
306 
307  device->dev = hid_open_path(device->path, 0);
308  if (!device->dev) {
309  SDL_free(ctx);
310  SDL_SetError("Couldn't open %s", device->path);
311  return SDL_FALSE;
312  }
313  device->context = ctx;
314 
315  ctx->vendor_id = device->vendor_id;
316  ctx->product_id = device->product_id;
317  ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
318  ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
319  ctx->start_time = SDL_GetTicks();
320  ctx->sequence = 1;
321  ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
322 
323  /* Initialize the joystick capabilities */
324  joystick->nbuttons = ctx->has_paddles ? SDL_CONTROLLER_BUTTON_MAX : (SDL_CONTROLLER_BUTTON_MAX + 4);
325  joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
326  joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
327 
328  return SDL_TRUE;
329 }
330 
331 static int
332 HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
333 {
334  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
335 
336  if (ctx->bluetooth) {
337  Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
338 
339  rumble_packet[4] = (low_frequency_rumble >> 8);
340  rumble_packet[5] = (high_frequency_rumble >> 8);
341 
342  if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
343  return SDL_SetError("Couldn't send rumble packet");
344  }
345  } else {
346  Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
347 
348  /* Magnitude is 1..100 so scale the 16-bit input here */
349  rumble_packet[8] = low_frequency_rumble / 655;
350  rumble_packet[9] = high_frequency_rumble / 655;
351 
352  if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
353  return SDL_SetError("Couldn't send rumble packet");
354  }
355  }
356  return 0;
357 }
358 
359 static void
360 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
361 {
362  Sint16 axis;
363 
364  if (ctx->last_state[4] != data[4]) {
371  }
372 
373  if (ctx->last_state[5] != data[5]) {
382  }
383 
384  /* Xbox One S report is 18 bytes
385  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
386  Paddle bits:
387  UL: 0x01 (A) UR: 0x02 (B)
388  LL: 0x04 (X) LR: 0x08 (Y)
389  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
390  Paddle bits:
391  UL: 0x04 (A) UR: 0x01 (B)
392  LL: 0x08 (X) LR: 0x02 (Y)
393  */
394  if (ctx->has_paddles && (size == 33 || size == 38)) {
395  int paddle_index;
396  int button1_bit;
397  int button2_bit;
398  int button3_bit;
399  int button4_bit;
400  SDL_bool paddles_mapped;
401 
402  if (size == 33) {
403  /* XBox One Elite Series 1 */
404  paddle_index = 32;
405  button1_bit = 0x01;
406  button2_bit = 0x02;
407  button3_bit = 0x04;
408  button4_bit = 0x08;
409 
410  /* The mapped controller state is at offset 4, the raw state is at offset 18, compare them to see if the paddles are mapped */
411  paddles_mapped = (SDL_memcmp(&data[4], &data[18], 14) != 0);
412 
413  } else /* if (size == 38) */ {
414  /* XBox One Elite Series 2 */
415  paddle_index = 18;
416  button1_bit = 0x04;
417  button2_bit = 0x01;
418  button3_bit = 0x08;
419  button4_bit = 0x02;
420  paddles_mapped = (data[19] != 0);
421  }
422 #ifdef DEBUG_XBOX_PROTOCOL
423  SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
424  (data[paddle_index] & button1_bit) ? 1 : 0,
425  (data[paddle_index] & button2_bit) ? 1 : 0,
426  (data[paddle_index] & button3_bit) ? 1 : 0,
427  (data[paddle_index] & button4_bit) ? 1 : 0,
428  paddles_mapped ? "TRUE" : "FALSE"
429  );
430 #endif
431 
432  if (paddles_mapped) {
433  /* Respect that the paddles are being used for other controls and don't pass them on to the app */
434  data[paddle_index] = 0;
435  }
436 
437  if (ctx->last_state[paddle_index] != data[paddle_index]) {
438  SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+0, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
439  SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+1, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
440  SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+2, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
441  SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MAX+3, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
442  }
443  }
444 
445  axis = ((int)*(Sint16*)(&data[6]) * 64) - 32768;
446  if (axis == 32704) {
447  axis = 32767;
448  }
450  axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
451  if (axis == 32704) {
452  axis = 32767;
453  }
455  axis = *(Sint16*)(&data[10]);
457  axis = *(Sint16*)(&data[12]);
459  axis = *(Sint16*)(&data[14]);
461  axis = *(Sint16*)(&data[16]);
463 
464  SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
465 }
466 
467 static void
468 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
469 {
470  if (data[1] == 0x30) {
471  /* The Xbox One S controller needs acks for mode reports */
472  const Uint8 seqnum = data[2];
473  const Uint8 ack[] = { 0x01, 0x20, seqnum, 0x09, 0x00, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
474  hid_write(dev, ack, sizeof(ack));
475  }
476 
478 }
479 
480 static void
481 HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
482 {
483  Sint16 axis;
484 
485  if (ctx->last_state[14] != data[14]) {
492  }
493 
494  if (ctx->last_state[15] != data[15]) {
498  if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN)
499  {
500  if (data[15] & 0x10) {
501  ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V2;
502  }
503  }
504  if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_V2)
505  {
507  }
508  }
509 
510  if (ctx->last_state[16] != data[16]) {
512  }
513 
514  if (ctx->last_state[13] != data[13]) {
515  SDL_bool dpad_up = SDL_FALSE;
516  SDL_bool dpad_down = SDL_FALSE;
517  SDL_bool dpad_left = SDL_FALSE;
518  SDL_bool dpad_right = SDL_FALSE;
519 
520  switch (data[13]) {
521  case 1:
522  dpad_up = SDL_TRUE;
523  break;
524  case 2:
525  dpad_up = SDL_TRUE;
526  dpad_right = SDL_TRUE;
527  break;
528  case 3:
529  dpad_right = SDL_TRUE;
530  break;
531  case 4:
532  dpad_right = SDL_TRUE;
533  dpad_down = SDL_TRUE;
534  break;
535  case 5:
536  dpad_down = SDL_TRUE;
537  break;
538  case 6:
539  dpad_left = SDL_TRUE;
540  dpad_down = SDL_TRUE;
541  break;
542  case 7:
543  dpad_left = SDL_TRUE;
544  break;
545  case 8:
546  dpad_up = SDL_TRUE;
547  dpad_left = SDL_TRUE;
548  break;
549  default:
550  break;
551  }
556  }
557 
558  axis = (int)*(Uint16*)(&data[1]) - 0x8000;
560  axis = (int)*(Uint16*)(&data[3]) - 0x8000;
562  axis = (int)*(Uint16*)(&data[5]) - 0x8000;
564  axis = (int)*(Uint16*)(&data[7]) - 0x8000;
566 
567  axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
568  if (axis == 32704) {
569  axis = 32767;
570  }
572 
573  axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
574  if (axis == 32704) {
575  axis = 32767;
576  }
578 
579  SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
580 }
581 
582 static void
583 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
584 {
585  ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V1;
587 }
588 
589 static SDL_bool
590 HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
591 {
592  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
593  SDL_Joystick *joystick = NULL;
595  int size;
596 
597  if (device->num_joysticks > 0) {
598  joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
599  }
600  if (!joystick) {
601  return SDL_FALSE;
602  }
603 
604  if (!ctx->initialized &&
605  !ControllerSendsWaitingForInit(device->vendor_id, device->product_id)) {
606  if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
607  if (!SendControllerInit(device, ctx)) {
608  HIDAPI_JoystickDisconnected(device, joystick->instance_id);
609  return SDL_FALSE;
610  }
611  ctx->initialized = SDL_TRUE;
612  }
613  }
614 
615  while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
616 #ifdef DEBUG_XBOX_PROTOCOL
617  DumpPacket("Xbox One packet: size = %d", data, size);
618 #endif
619  if (ctx->bluetooth) {
620  switch (data[0]) {
621  case 0x01:
622  HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick, device->dev, ctx, data, size);
623  break;
624  case 0x02:
625  HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
626  break;
627  default:
628 #ifdef DEBUG_JOYSTICK
629  SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
630 #endif
631  break;
632  }
633  } else {
634  switch (data[0]) {
635  case 0x02:
636  /* Controller is connected and waiting for initialization */
637  if (!ctx->initialized) {
638 #ifdef DEBUG_XBOX_PROTOCOL
639  SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
640 #endif
641  if (!SendControllerInit(device, ctx)) {
642  HIDAPI_JoystickDisconnected(device, joystick->instance_id);
643  return SDL_FALSE;
644  }
645  ctx->initialized = SDL_TRUE;
646  }
647  break;
648  case 0x03:
649  /* Controller heartbeat */
650  break;
651  case 0x20:
652  HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
653  break;
654  case 0x07:
655  HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
656  break;
657  default:
658 #ifdef DEBUG_JOYSTICK
659  SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
660 #endif
661  break;
662  }
663  }
664  }
665 
666  if (size < 0) {
667  /* Read error, device is disconnected */
668  HIDAPI_JoystickDisconnected(device, joystick->instance_id);
669  }
670  return (size >= 0);
671 }
672 
673 static void
674 HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
675 {
676  hid_close(device->dev);
677  device->dev = NULL;
678 
679  SDL_free(device->context);
680  device->context = NULL;
681 }
682 
683 static void
684 HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device *device)
685 {
686 }
687 
689 {
691  SDL_TRUE,
692  HIDAPI_DriverXboxOne_IsSupportedDevice,
693  HIDAPI_DriverXboxOne_GetDeviceName,
694  HIDAPI_DriverXboxOne_InitDevice,
695  HIDAPI_DriverXboxOne_GetDevicePlayerIndex,
696  HIDAPI_DriverXboxOne_SetDevicePlayerIndex,
697  HIDAPI_DriverXboxOne_UpdateDevice,
698  HIDAPI_DriverXboxOne_OpenJoystick,
699  HIDAPI_DriverXboxOne_RumbleJoystick,
700  HIDAPI_DriverXboxOne_CloseJoystick,
701  HIDAPI_DriverXboxOne_FreeDevice
702 };
703 
704 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
705 
706 #endif /* SDL_JOYSTICK_HIDAPI */
707 
708 /* vi: set ts=4 sw=4 expandtab: */
SDL_CONTROLLER_BUTTON_DPAD_LEFT
@ SDL_CONTROLLER_BUTTON_DPAD_LEFT
Definition: SDL_gamecontroller.h:362
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_RIGHTX
Definition: SDL_gamecontroller.h:307
SDL_strlcat
#define SDL_strlcat
Definition: SDL_dynapi_overrides.h:396
SDL_events.h
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Definition: pixman-arm-neon-asm.h:469
hid_write
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
NULL
#define NULL
Definition: begin_code.h:167
SDL_timer.h
HIDAPI_JoystickConnected
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
SDL_joystick.h
USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH
Definition: usb_ids.h:45
SDL_JoystickID
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
hid_close
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
SDL_log.h
USB_VENDOR_MICROSOFT
#define USB_VENDOR_MICROSOFT
Definition: usb_ids.h:28
SDL_hidapi_rumble.h
SDL_CONTROLLER_BUTTON_RIGHTSTICK
@ SDL_CONTROLLER_BUTTON_RIGHTSTICK
Definition: SDL_gamecontroller.h:357
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH
Definition: usb_ids.h:47
SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_LEFTX
Definition: SDL_gamecontroller.h:305
SDL_HIDAPI_Device
Definition: SDL_hidapijoystick_c.h:64
USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH
Definition: usb_ids.h:46
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
ctx
EGLContext ctx
Definition: eglext.h:208
SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_B
Definition: SDL_gamecontroller.h:350
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_CONTROLLER_BUTTON_MAX
@ SDL_CONTROLLER_BUTTON_MAX
Definition: SDL_gamecontroller.h:364
SDL_PrivateJoystickAxis
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:1023
SDL_hidapijoystick_c.h
SDL_CONTROLLER_BUTTON_BACK
@ SDL_CONTROLLER_BUTTON_BACK
Definition: SDL_gamecontroller.h:353
SDL_CONTROLLER_BUTTON_LEFTSHOULDER
@ SDL_CONTROLLER_BUTTON_LEFTSHOULDER
Definition: SDL_gamecontroller.h:358
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:185
USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2
Definition: usb_ids.h:44
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
buffer
GLuint buffer
Definition: SDL_opengl_glext.h:536
USB_VENDOR_HYPERKIN
#define USB_VENDOR_HYPERKIN
Definition: usb_ids.h:27
SDL_HINT_JOYSTICK_HIDAPI_XBOX
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX
A variable controlling whether the HIDAPI driver for XBox controllers should be used.
Definition: SDL_hints.h:639
SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
Definition: SDL_gamecontroller.h:309
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:31
SDL_JoystickFromInstanceID
#define SDL_JoystickFromInstanceID
Definition: SDL_dynapi_overrides.h:595
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
hid_read_timeout
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
SDL_JOYSTICK_POWER_WIRED
@ SDL_JOYSTICK_POWER_WIRED
Definition: SDL_joystick.h:104
SDL_HIDAPI_DeviceDriver
Definition: SDL_hidapijoystick_c.h:93
SDL_PrivateJoystickButton
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:1162
SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_MAX
Definition: SDL_gamecontroller.h:311
USB_VENDOR_POWERA
#define USB_VENDOR_POWERA
Definition: usb_ids.h:32
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1
Definition: usb_ids.h:43
SDL_gamecontroller.h
SDL_CONTROLLER_BUTTON_START
@ SDL_CONTROLLER_BUTTON_START
Definition: SDL_gamecontroller.h:355
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
hid_open_path
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
start
GLuint start
Definition: SDL_opengl.h:1571
axis
SDL_Texture * axis
Definition: testgamecontroller.c:67
SDL_HIDAPI_DriverXboxOne
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:540
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
@ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
Definition: SDL_gamecontroller.h:359
SDL_CONTROLLER_BUTTON_Y
@ SDL_CONTROLLER_BUTTON_Y
Definition: SDL_gamecontroller.h:352
HIDAPI_JoystickDisconnected
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
USB_VENDOR_PDP
#define USB_VENDOR_PDP
Definition: usb_ids.h:31
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_GameControllerType
SDL_GameControllerType
Definition: SDL_gamecontroller.h:61
USB_PACKET_LENGTH
#define USB_PACKET_LENGTH
Definition: SDL_hidapijoystick_c.h:58
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
SDL_hints.h
SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_AXIS_LEFTY
Definition: SDL_gamecontroller.h:306
SDL_CONTROLLER_BUTTON_LEFTSTICK
@ SDL_CONTROLLER_BUTTON_LEFTSTICK
Definition: SDL_gamecontroller.h:356
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
SDL_TICKS_PASSED
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_CONTROLLER_BUTTON_DPAD_DOWN
@ SDL_CONTROLLER_BUTTON_DPAD_DOWN
Definition: SDL_gamecontroller.h:361
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_CONTROLLER_BUTTON_DPAD_UP
@ SDL_CONTROLLER_BUTTON_DPAD_UP
Definition: SDL_gamecontroller.h:360
SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
Definition: SDL_gamecontroller.h:310
hid_device
struct hid_device_ hid_device
Definition: hidapi.h:54
SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTY
Definition: SDL_gamecontroller.h:308
SDL_CONTROLLER_BUTTON_X
@ SDL_CONTROLLER_BUTTON_X
Definition: SDL_gamecontroller.h:351
device
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_CONTROLLER_BUTTON_A
@ SDL_CONTROLLER_BUTTON_A
Definition: SDL_gamecontroller.h:349
SDL_CONTROLLER_TYPE_XBOXONE
@ SDL_CONTROLLER_TYPE_XBOXONE
Definition: SDL_gamecontroller.h:64
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_CONTROLLER_BUTTON_DPAD_RIGHT
@ SDL_CONTROLLER_BUTTON_DPAD_RIGHT
Definition: SDL_gamecontroller.h:363
SDL_CONTROLLER_BUTTON_GUIDE
@ SDL_CONTROLLER_BUTTON_GUIDE
Definition: SDL_gamecontroller.h:354