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_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 verbose logging of the init sequence */
38 /*#define DEBUG_JOYSTICK*/
39 
40 /* Define this if you want to log all packets from the controller */
41 /*#define DEBUG_XBOX_PROTOCOL*/
42 
43 #define CONTROLLER_NEGOTIATION_TIMEOUT_MS 300
44 #define CONTROLLER_PREPARE_INPUT_TIMEOUT_MS 50
45 
46 
47 /* Connect controller */
48 static const Uint8 xboxone_init0[] = {
49  0x04, 0x20, 0x00, 0x00
50 };
51 /* Start controller - extended? */
52 static const Uint8 xboxone_init1[] = {
53  0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
54  0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
55  0x00, 0x00, 0x00
56 };
57 /* Start controller with input */
58 static const Uint8 xboxone_init2[] = {
59  0x05, 0x20, 0x03, 0x01, 0x00
60 };
61 /* Enable LED */
62 static const Uint8 xboxone_init3[] = {
63  0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
64 };
65 /* Start input reports? */
66 static const Uint8 xboxone_init4[] = {
67  0x06, 0x20, 0x00, 0x02, 0x01, 0x00
68 };
69 /* Start rumble? */
70 static const Uint8 xboxone_init5[] = {
71  0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
72  0x00, 0x00, 0xFF, 0x00, 0xEB
73 };
74 
75 /*
76  * This specifies the selection of init packets that a gamepad
77  * will be sent on init *and* the order in which they will be
78  * sent. The correct sequence number will be added when the
79  * packet is going to be sent.
80  */
81 typedef struct {
82  Uint16 vendor_id;
83  Uint16 product_id;
84  Uint16 exclude_vendor_id;
85  Uint16 exclude_product_id;
86  const Uint8 *data;
87  int size;
88  const Uint8 response[2];
89 } SDL_DriverXboxOne_InitPacket;
90 
91 
92 static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
93  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x04, 0xb0 } },
94  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init1, sizeof(xboxone_init1), { 0x00, 0x00 } },
95  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init2, sizeof(xboxone_init2), { 0x00, 0x00 } },
96  { 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init3, sizeof(xboxone_init3), { 0x00, 0x00 } },
97 
98  /* These next packets are required for third party controllers (PowerA, PDP, HORI),
99  but aren't the correct protocol for Microsoft Xbox controllers.
100  */
101  { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
102  { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
103 };
104 
105 typedef enum {
106  XBOX_ONE_INIT_STATE_START_NEGOTIATING = 0,
107  XBOX_ONE_INIT_STATE_NEGOTIATING = 1,
108  XBOX_ONE_INIT_STATE_PREPARE_INPUT = 2,
109  XBOX_ONE_INIT_STATE_COMPLETE = 3
110 } SDL_XboxOneInitState;
111 
112 typedef struct {
113  Uint16 vendor_id;
114  Uint16 product_id;
115  SDL_bool bluetooth;
116  SDL_XboxOneInitState init_state;
117  int init_packet;
118  Uint32 start_time;
119  Uint8 sequence;
120  Uint32 send_time;
121  Uint8 last_state[USB_PACKET_LENGTH];
122  SDL_bool has_guide_packet;
123  SDL_bool has_paddles;
124  SDL_bool has_trigger_rumble;
125  SDL_bool has_share_button;
126  Uint8 low_frequency_rumble;
127  Uint8 high_frequency_rumble;
128  Uint8 left_trigger_rumble;
129  Uint8 right_trigger_rumble;
130 } SDL_DriverXboxOne_Context;
131 
132 
133 static SDL_bool
134 IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
135 {
136  /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
137  if (vendor_id == USB_VENDOR_MICROSOFT) {
138  if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
142  return SDL_TRUE;
143  }
144  }
145  return SDL_FALSE;
146 }
147 
148 static SDL_bool
149 ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
150 {
151  return SDL_IsJoystickXboxOneElite(vendor_id, product_id);
152 }
153 
154 static SDL_bool
155 ControllerHasTriggerRumble(Uint16 vendor_id, Uint16 product_id)
156 {
157  return SDL_IsJoystickXboxOneElite(vendor_id, product_id);
158 }
159 
160 static SDL_bool
161 ControllerHasShareButton(Uint16 vendor_id, Uint16 product_id)
162 {
163  return SDL_IsJoystickXboxOneSeriesX(vendor_id, product_id);
164 }
165 
166 static void
167 SetInitState(SDL_DriverXboxOne_Context *ctx, SDL_XboxOneInitState state)
168 {
169 #ifdef DEBUG_JOYSTICK
170  SDL_Log("Setting init state %d\n", state);
171 #endif
172  ctx->init_state = state;
173 }
174 
175 static void
176 SendAckIfNeeded(SDL_HIDAPI_Device *device, Uint8 *data, int size)
177 {
178 #ifdef __WIN32__
179  /* The Windows driver is taking care of acks */
180 #else
181  if ((data[1] & 0x30) == 0x30) {
182  Uint8 ack_packet[] = { 0x01, 0x20, data[2], 0x09, 0x00, data[0], 0x20, data[3], 0x00, 0x00, 0x00, 0x00, 0x00 };
183 
184  /* The initial ack needs 0x80 added to the response, for some reason */
185  if (data[0] == 0x04 && data[1] == 0xF0) {
186  ack_packet[11] = 0x80;
187  }
188 
189 #ifdef DEBUG_XBOX_PROTOCOL
190  HIDAPI_DumpPacket("Xbox One sending ACK packet: size = %d", ack_packet, sizeof(ack_packet));
191 #endif
192  hid_write(device->dev, ack_packet, sizeof(ack_packet));
193  }
194 #endif /* __WIN32__ */
195 }
196 
197 #if 0
198 static SDL_bool
199 SendSerialRequest(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
200 {
201  Uint8 serial_packet[] = { 0x1E, 0x30, 0x07, 0x01, 0x04 };
202 
203  ctx->send_time = SDL_GetTicks();
204 
205  /* Request the serial number
206  * Sending this should be done only after the negotiation is complete.
207  * It will cancel the announce packet if sent before that, and will be
208  * ignored if sent during the negotiation.
209  */
210  if (SDL_HIDAPI_LockRumble() < 0 ||
211  SDL_HIDAPI_SendRumbleAndUnlock(device, serial_packet, sizeof(serial_packet)) != sizeof(serial_packet)) {
212  SDL_SetError("Couldn't send serial packet");
213  return SDL_FALSE;
214  }
215  return SDL_TRUE;
216 }
217 #endif
218 
219 static SDL_bool
220 ControllerNeedsNegotiation(SDL_DriverXboxOne_Context *ctx)
221 {
222  if (ctx->vendor_id == USB_VENDOR_PDP && ctx->product_id == 0x0246) {
223  /* The PDP Rock Candy (PID 0x0246) doesn't send the announce packet on Linux for some reason */
224  return SDL_TRUE;
225  }
226  return SDL_FALSE;
227 }
228 
229 static SDL_bool
230 SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
231 {
232  Uint16 vendor_id = ctx->vendor_id;
233  Uint16 product_id = ctx->product_id;
234  Uint8 init_packet[USB_PACKET_LENGTH];
235 
236  for ( ; ctx->init_packet < SDL_arraysize(xboxone_init_packets); ++ctx->init_packet) {
237  const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[ctx->init_packet];
238 
239  if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
240  continue;
241  }
242 
243  if (packet->product_id && (product_id != packet->product_id)) {
244  continue;
245  }
246 
247  if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
248  continue;
249  }
250 
251  if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
252  continue;
253  }
254 
255  SDL_memcpy(init_packet, packet->data, packet->size);
256  if (init_packet[0] != 0x01) {
257  init_packet[2] = ctx->sequence++;
258  }
259 #ifdef DEBUG_XBOX_PROTOCOL
260  HIDAPI_DumpPacket("Xbox One sending INIT packet: size = %d", init_packet, packet->size);
261 #endif
262  ctx->send_time = SDL_GetTicks();
263 
264  if (SDL_HIDAPI_LockRumble() < 0 ||
265  SDL_HIDAPI_SendRumbleAndUnlock(device, init_packet, packet->size) != packet->size) {
266  SDL_SetError("Couldn't write Xbox One initialization packet");
267  return SDL_FALSE;
268  }
269 
270  if (packet->response[0]) {
271  return SDL_TRUE;
272  }
273  }
274 
275  /* All done with the negotiation, prepare for input! */
276  SetInitState(ctx, XBOX_ONE_INIT_STATE_PREPARE_INPUT);
277 
278  return SDL_TRUE;
279 }
280 
281 static SDL_bool
282 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)
283 {
284 #ifdef __LINUX__
285  if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
286  /* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
287  return SDL_FALSE;
288  }
289 #endif
290 #ifdef __MACOSX__
291  /* Wired Xbox One controllers are handled by the 360Controller driver */
292  if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
293  return SDL_FALSE;
294  }
295 #endif
297 }
298 
299 static const char *
300 HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
301 {
302  return NULL;
303 }
304 
305 static SDL_bool
306 HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device)
307 {
309 }
310 
311 static int
312 HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
313 {
314  return -1;
315 }
316 
317 static void
318 HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
319 {
320 }
321 
322 static SDL_bool HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
323 static void HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
324 
325 static SDL_bool
326 HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
327 {
328  SDL_DriverXboxOne_Context *ctx;
329 
330  ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
331  if (!ctx) {
332  SDL_OutOfMemory();
333  return SDL_FALSE;
334  }
335 
336  device->dev = hid_open_path(device->path, 0);
337  if (!device->dev) {
338  SDL_free(ctx);
339  SDL_SetError("Couldn't open %s", device->path);
340  return SDL_FALSE;
341  }
342  device->context = ctx;
343 
344  ctx->vendor_id = device->vendor_id;
345  ctx->product_id = device->product_id;
346  ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
347  ctx->start_time = SDL_GetTicks();
348  ctx->sequence = 1;
349  ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
350  ctx->has_trigger_rumble = ControllerHasTriggerRumble(ctx->vendor_id, ctx->product_id);
351  ctx->has_share_button = ControllerHasShareButton(ctx->vendor_id, ctx->product_id);
352 
353  /* Assume that the controller is correctly initialized when we start */
354  if (ControllerNeedsNegotiation(ctx)) {
355  ctx->init_state = XBOX_ONE_INIT_STATE_START_NEGOTIATING;
356  } else {
357  ctx->init_state = XBOX_ONE_INIT_STATE_COMPLETE;
358  }
359 
360 #ifdef DEBUG_JOYSTICK
361  SDL_Log("Controller version: %d (0x%.4x)\n", device->version, device->version);
362 #endif
363 
364  /* Initialize the joystick capabilities */
365  joystick->nbuttons = 15;
366  if (ctx->has_share_button) {
367  joystick->nbuttons += 1;
368  }
369  if (ctx->has_paddles) {
370  joystick->nbuttons += 4;
371  }
373 
374  if (!ctx->bluetooth) {
375  joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
376  }
377 
378  return SDL_TRUE;
379 }
380 
381 static int
382 HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device)
383 {
384  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
385 
386  if (ctx->bluetooth) {
387  Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB };
388 
389  rumble_packet[2] = ctx->left_trigger_rumble;
390  rumble_packet[3] = ctx->right_trigger_rumble;
391  rumble_packet[4] = ctx->low_frequency_rumble;
392  rumble_packet[5] = ctx->high_frequency_rumble;
393 
394  if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
395  return SDL_SetError("Couldn't send rumble packet");
396  }
397  } else {
398  Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xEB };
399 
400  rumble_packet[6] = ctx->left_trigger_rumble;
401  rumble_packet[7] = ctx->right_trigger_rumble;
402  rumble_packet[8] = ctx->low_frequency_rumble;
403  rumble_packet[9] = ctx->high_frequency_rumble;
404 
405  if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
406  return SDL_SetError("Couldn't send rumble packet");
407  }
408  }
409  return 0;
410 }
411 
412 static int
413 HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
414 {
415  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
416 
417  /* Magnitude is 1..100 so scale the 16-bit input here */
418  ctx->low_frequency_rumble = low_frequency_rumble / 655;
419  ctx->high_frequency_rumble = high_frequency_rumble / 655;
420 
421  return HIDAPI_DriverXboxOne_UpdateRumble(device);
422 }
423 
424 static int
425 HIDAPI_DriverXboxOne_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
426 {
427  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
428 
429  if (!ctx->has_trigger_rumble) {
430  return SDL_Unsupported();
431  }
432 
433  /* Magnitude is 1..100 so scale the 16-bit input here */
434  ctx->left_trigger_rumble = left_rumble / 655;
435  ctx->right_trigger_rumble = right_rumble / 655;
436 
437  return HIDAPI_DriverXboxOne_UpdateRumble(device);
438 }
439 
440 static SDL_bool
441 HIDAPI_DriverXboxOne_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
442 {
443  /* Doesn't have an RGB LED, so don't return true here */
444  return SDL_FALSE;
445 }
446 
447 static int
448 HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
449 {
450  return SDL_Unsupported();
451 }
452 
453 static int
454 HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
455 {
456  return SDL_Unsupported();
457 }
458 
459 static void
460 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
461 {
462  Sint16 axis;
463 
464  if (ctx->last_state[4] != data[4]) {
471  }
472 
473  if (ctx->last_state[5] != data[5]) {
478  if (ctx->vendor_id == USB_VENDOR_RAZER && ctx->product_id == USB_PRODUCT_RAZER_ATROX) {
479  /* The Razer Atrox has the right and left shoulder bits reversed */
482  } else {
485  }
488  }
489 
490  if (ctx->has_share_button) {
491  /* Version 1 of the firmware for Xbox One Series X */
492  if (ctx->last_state[18] != data[18]) {
494  }
495 
496  /* Version 2 of the firmware for Xbox One Series X */
497  if (ctx->last_state[22] != data[22]) {
499  }
500  }
501 
502  /* Xbox One S report is 18 bytes
503  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
504  Paddle bits:
505  P3: 0x01 (A) P1: 0x02 (B)
506  P4: 0x04 (X) P2: 0x08 (Y)
507  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
508  Paddle bits:
509  P3: 0x04 (A) P1: 0x01 (B)
510  P4: 0x08 (X) P2: 0x02 (Y)
511  */
512  if (ctx->has_paddles && (size == 33 || size == 38)) {
513  int paddle_index;
514  int button1_bit;
515  int button2_bit;
516  int button3_bit;
517  int button4_bit;
518  SDL_bool paddles_mapped;
519 
520  if (size == 33) {
521  /* XBox One Elite Series 1 */
522  paddle_index = 32;
523  button1_bit = 0x02;
524  button2_bit = 0x08;
525  button3_bit = 0x01;
526  button4_bit = 0x04;
527 
528  /* The mapped controller state is at offset 4, the raw state is at offset 18, compare them to see if the paddles are mapped */
529  paddles_mapped = (SDL_memcmp(&data[4], &data[18], 14) != 0);
530 
531  } else /* if (size == 38) */ {
532  /* XBox One Elite Series 2 */
533  paddle_index = 18;
534  button1_bit = 0x01;
535  button2_bit = 0x02;
536  button3_bit = 0x04;
537  button4_bit = 0x08;
538  paddles_mapped = (data[19] != 0);
539  }
540 #ifdef DEBUG_XBOX_PROTOCOL
541  SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
542  (data[paddle_index] & button1_bit) ? 1 : 0,
543  (data[paddle_index] & button2_bit) ? 1 : 0,
544  (data[paddle_index] & button3_bit) ? 1 : 0,
545  (data[paddle_index] & button4_bit) ? 1 : 0,
546  paddles_mapped ? "TRUE" : "FALSE"
547  );
548 #endif
549 
550  if (paddles_mapped) {
551  /* Respect that the paddles are being used for other controls and don't pass them on to the app */
552  data[paddle_index] = 0;
553  }
554 
555  if (ctx->last_state[paddle_index] != data[paddle_index]) {
556  int nButton = SDL_CONTROLLER_BUTTON_MISC1 + ctx->has_share_button; /* Next available button */
557  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
558  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
559  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
560  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
561  }
562  }
563 
564  axis = ((int)*(Sint16*)(&data[6]) * 64) - 32768;
565  if (axis == 32704) {
566  axis = 32767;
567  }
568  if (axis == -32768 && size == 30 && (data[22] & 0x80) != 0) {
569  axis = 32767;
570  }
572 
573  axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
574  if (axis == -32768 && size == 30 && (data[22] & 0x40) != 0) {
575  axis = 32767;
576  }
577  if (axis == 32704) {
578  axis = 32767;
579  }
581 
582  axis = *(Sint16*)(&data[10]);
584  axis = *(Sint16*)(&data[12]);
586  axis = *(Sint16*)(&data[14]);
588  axis = *(Sint16*)(&data[16]);
590 
591  SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
592 }
593 
594 static void
595 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
596 {
598 }
599 
600 /*
601  * Xbox One S with firmware 3.1.1221 uses a 16 byte packet and the GUIDE button in a separate packet
602  */
603 static void
604 HIDAPI_DriverXboxOneBluetooth_HandleButtons16(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
605 {
606  if (ctx->last_state[14] != data[14]) {
615  }
616 
617  if (ctx->last_state[15] != data[15]) {
620  }
621 
622 }
623 
624 /*
625  * Xbox One S with firmware 4.8.1923 uses a 17 byte packet with BACK button in byte 16 and the GUIDE button in a separate packet (on Windows), or in byte 15 (on Linux)
626  * Xbox One Elite Series 2 with firmware 4.7.1872 uses a 55 byte packet with BACK button in byte 16, paddles starting at byte 33, and the GUIDE button in a separate packet
627  * Xbox One Elite Series 2 with firmware 4.8.1908 uses a 33 byte packet with BACK button in byte 16, paddles starting at byte 17, and the GUIDE button in a separate packet
628  * Xbox One Series X with firmware 5.5.2641 uses a 17 byte packet with BACK and GUIDE buttons in byte 15, and SHARE button in byte 17
629  */
630 static void
631 HIDAPI_DriverXboxOneBluetooth_HandleButtons(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
632 {
633  if (ctx->last_state[14] != data[14]) {
640  }
641 
642  if (ctx->last_state[15] != data[15]) {
643  if (ctx->has_share_button) {
646  } else if (!ctx->has_guide_packet) {
648  }
652  }
653 
654  if (ctx->last_state[16] != data[16]) {
655  if (ctx->has_share_button) {
657  } else {
659  }
660  }
661 
662  /*
663  Paddle bits:
664  P3: 0x04 (A) P1: 0x01 (B)
665  P4: 0x08 (X) P2: 0x02 (Y)
666  */
667  if (ctx->has_paddles && (size == 39 || size == 55)) {
668  int paddle_index;
669  int button1_bit;
670  int button2_bit;
671  int button3_bit;
672  int button4_bit;
673  SDL_bool paddles_mapped;
674 
675  if (size == 55) {
676  /* Initial firmware for the Xbox Elite Series 2 controller */
677  paddle_index = 33;
678  button1_bit = 0x01;
679  button2_bit = 0x02;
680  button3_bit = 0x04;
681  button4_bit = 0x08;
682  paddles_mapped = (data[35] != 0);
683  } else /* if (size == 39) */ {
684  /* Updated firmware for the Xbox Elite Series 2 controller */
685  paddle_index = 17;
686  button1_bit = 0x01;
687  button2_bit = 0x02;
688  button3_bit = 0x04;
689  button4_bit = 0x08;
690  paddles_mapped = (data[19] != 0);
691  }
692 
693 #ifdef DEBUG_XBOX_PROTOCOL
694  SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
695  (data[paddle_index] & button1_bit) ? 1 : 0,
696  (data[paddle_index] & button2_bit) ? 1 : 0,
697  (data[paddle_index] & button3_bit) ? 1 : 0,
698  (data[paddle_index] & button4_bit) ? 1 : 0,
699  paddles_mapped ? "TRUE" : "FALSE"
700  );
701 #endif
702 
703  if (paddles_mapped) {
704  /* Respect that the paddles are being used for other controls and don't pass them on to the app */
705  data[paddle_index] = 0;
706  }
707 
708  if (ctx->last_state[paddle_index] != data[paddle_index]) {
709  int nButton = SDL_CONTROLLER_BUTTON_MISC1; /* Next available button */
710  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
711  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
712  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
713  SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
714  }
715  }
716 }
717 
718 static void
719 HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
720 {
721  Sint16 axis;
722 
723  if (size == 16) {
724  /* Original Xbox One S, with separate report for guide button */
725  HIDAPI_DriverXboxOneBluetooth_HandleButtons16(joystick, ctx, data, size);
726  } else {
727  HIDAPI_DriverXboxOneBluetooth_HandleButtons(joystick, ctx, data, size);
728  }
729 
730  if (ctx->last_state[13] != data[13]) {
731  SDL_bool dpad_up = SDL_FALSE;
732  SDL_bool dpad_down = SDL_FALSE;
733  SDL_bool dpad_left = SDL_FALSE;
734  SDL_bool dpad_right = SDL_FALSE;
735 
736  switch (data[13]) {
737  case 1:
738  dpad_up = SDL_TRUE;
739  break;
740  case 2:
741  dpad_up = SDL_TRUE;
742  dpad_right = SDL_TRUE;
743  break;
744  case 3:
745  dpad_right = SDL_TRUE;
746  break;
747  case 4:
748  dpad_right = SDL_TRUE;
749  dpad_down = SDL_TRUE;
750  break;
751  case 5:
752  dpad_down = SDL_TRUE;
753  break;
754  case 6:
755  dpad_left = SDL_TRUE;
756  dpad_down = SDL_TRUE;
757  break;
758  case 7:
759  dpad_left = SDL_TRUE;
760  break;
761  case 8:
762  dpad_up = SDL_TRUE;
763  dpad_left = SDL_TRUE;
764  break;
765  default:
766  break;
767  }
772  }
773 
774  axis = (int)*(Uint16*)(&data[1]) - 0x8000;
776  axis = (int)*(Uint16*)(&data[3]) - 0x8000;
778  axis = (int)*(Uint16*)(&data[5]) - 0x8000;
780  axis = (int)*(Uint16*)(&data[7]) - 0x8000;
782 
783  axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
784  if (axis == 32704) {
785  axis = 32767;
786  }
788 
789  axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
790  if (axis == 32704) {
791  axis = 32767;
792  }
794 
795  SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
796 }
797 
798 static void
799 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
800 {
801  ctx->has_guide_packet = SDL_TRUE;
803 }
804 
805 static void
806 HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
807 {
808  Uint8 flags = data[1];
809  SDL_bool on_usb = (((flags & 0x0C) >> 2) == 0);
810 
811  if (on_usb) {
812  /* Does this ever happen? */
814  } else {
815  switch ((flags & 0x03)) {
816  case 0:
818  break;
819  case 1:
821  break;
822  default: /* 2, 3 */
824  break;
825  }
826  }
827 }
828 
829 #ifdef SET_SERIAL_AFTER_OPEN
830 static void
831 HIDAPI_DriverXboxOne_HandleSerialIDPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
832 {
833  char serial[ 29 ];
834  int i;
835 
836  for (i = 0; i < 14; ++i) {
837  SDL_uitoa( data[6 + i], &serial[i * 2], 16 );
838  }
839  serial[i * 2] = '\0';
840 
841  if (!joystick->serial || SDL_strcmp(joystick->serial, serial) != 0) {
842 #ifdef DEBUG_JOYSTICK
843  SDL_Log("Setting serial number to %s\n", serial);
844 #endif
845  joystick->serial = SDL_strdup(serial);
846  }
847 }
848 #endif /* SET_SERIAL_AFTER_OPEN */
849 
850 static SDL_bool
851 HIDAPI_DriverXboxOne_UpdateInitState(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
852 {
853  SDL_XboxOneInitState prev_state;
854  do
855  {
856  prev_state = ctx->init_state;
857 
858  switch (ctx->init_state) {
859  case XBOX_ONE_INIT_STATE_START_NEGOTIATING:
860 #ifdef __WIN32__
861  /* The Windows driver is taking care of negotiation */
862  SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
863 #else
864  SetInitState(ctx, XBOX_ONE_INIT_STATE_NEGOTIATING);
865  ctx->init_packet = 0;
866  if (!SendControllerInit(device, ctx)) {
867  return SDL_FALSE;
868  }
869 #endif
870  break;
871  case XBOX_ONE_INIT_STATE_NEGOTIATING:
872  if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_NEGOTIATION_TIMEOUT_MS)) {
873  /* We haven't heard anything, let's move on */
874 #ifdef DEBUG_JOYSTICK
875  SDL_Log("Init sequence %d timed out after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time));
876 #endif
877  ++ctx->init_packet;
878  if (!SendControllerInit(device, ctx)) {
879  return SDL_FALSE;
880  }
881  }
882  break;
883  case XBOX_ONE_INIT_STATE_PREPARE_INPUT:
884  if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->send_time + CONTROLLER_PREPARE_INPUT_TIMEOUT_MS)) {
885 #ifdef DEBUG_JOYSTICK
886  SDL_Log("Prepare input complete after %u ms\n", (SDL_GetTicks() - ctx->send_time));
887 #endif
888  SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
889  }
890  break;
891  case XBOX_ONE_INIT_STATE_COMPLETE:
892  break;
893  }
894 
895  } while (ctx->init_state != prev_state);
896 
897  return SDL_TRUE;
898 }
899 
900 static SDL_bool
901 HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
902 {
903  SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
905  int size;
906 
907  while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
908 #ifdef DEBUG_XBOX_PROTOCOL
909  HIDAPI_DumpPacket("Xbox One packet: size = %d", data, size);
910 #endif
911  if (ctx->bluetooth) {
912  switch (data[0]) {
913  case 0x01:
914  if (size >= 16) {
915  HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick, ctx, data, size);
916  } else {
917 #ifdef DEBUG_JOYSTICK
918  SDL_Log("Unknown Xbox One Bluetooth packet size: %d\n", size);
919 #endif
920  }
921  break;
922  case 0x02:
923  HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, ctx, data, size);
924  break;
925  case 0x04:
926  HIDAPI_DriverXboxOneBluetooth_HandleBatteryPacket(joystick, ctx, data, size);
927  break;
928  default:
929 #ifdef DEBUG_JOYSTICK
930  SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
931 #endif
932  break;
933  }
934  } else {
935  switch (data[0]) {
936  case 0x01:
937  /* ACK packet */
938  /* The data bytes are:
939  0x01 0x20 NN 0x09, where NN is the packet sequence
940  then 0x00
941  then a byte of the sequence being acked
942  then 0x20
943  then 16-bit LE value, the size of the previous packet payload when it's a single packet
944  then 4 bytes of unknown data, often all zero
945  */
946  break;
947  case 0x02:
948  /* Controller is connected and waiting for initialization */
949  /* The data bytes are:
950  0x02 0x20 NN 0x1c, where NN is the packet sequence
951  then 6 bytes of wireless MAC address
952  then 2 bytes padding
953  then 16-bit VID
954  then 16-bit PID
955  then 16-bit firmware version quartet AA.BB.CC.DD
956  e.g. 0x05 0x00 0x05 0x00 0x51 0x0a 0x00 0x00
957  is firmware version 5.5.2641.0, and product version 0x0505 = 1285
958  then 8 bytes of unknown data
959  */
960 #ifdef DEBUG_JOYSTICK
961  SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
962 #endif
963  SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
964  break;
965  case 0x03:
966  /* Controller heartbeat */
967  if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
968  SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
969  }
970  break;
971  case 0x04:
972  /* Unknown chatty controller information, sent by both sides */
973  break;
974  case 0x06:
975  /* Unknown chatty controller information, sent by both sides */
976  break;
977  case 0x07:
978  HIDAPI_DriverXboxOne_HandleModePacket(joystick, ctx, data, size);
979  break;
980  case 0x1E:
981  /* If the packet starts with this:
982  0x1E 0x30 0x07 0x10 0x04 0x00
983  then the next 14 bytes are the controller serial number
984  e.g. 0x30 0x39 0x37 0x31 0x32 0x33 0x33 0x32 0x33 0x35 0x34 0x30 0x33 0x36
985  is serial number "3039373132333332333534303336"
986 
987  The controller sends that in response to this request:
988  0x1E 0x30 0x07 0x01 0x04
989  */
990 #ifdef SET_SERIAL_AFTER_OPEN
991  if (size == 20 && data[3] == 0x10) {
992  HIDAPI_DriverXboxOne_HandleSerialIDPacket(joystick, ctx, data, size);
993  }
994 #endif
995  break;
996  case 0x20:
997  if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
998  SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
999 
1000  /* Ignore the first input, it may be spurious */
1001 #ifdef DEBUG_JOYSTICK
1002  SDL_Log("Controller ignoring spurious input\n");
1003 #endif
1004  break;
1005  }
1006  HIDAPI_DriverXboxOne_HandleStatePacket(joystick, ctx, data, size);
1007  break;
1008  default:
1009 #ifdef DEBUG_JOYSTICK
1010  SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
1011 #endif
1012  break;
1013  }
1014 
1015  SendAckIfNeeded(device, data, size);
1016 
1017  if (ctx->init_state == XBOX_ONE_INIT_STATE_NEGOTIATING) {
1018  const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[ctx->init_packet];
1019 
1020  if (size >= 4 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
1021 #ifdef DEBUG_JOYSTICK
1022  SDL_Log("Init sequence %d got response after %u ms\n", ctx->init_packet, (SDL_GetTicks() - ctx->send_time));
1023 #endif
1024  ++ctx->init_packet;
1025  SendControllerInit(device, ctx);
1026  }
1027  }
1028  }
1029  }
1030 
1031  HIDAPI_DriverXboxOne_UpdateInitState(device, ctx);
1032 
1033  if (size < 0) {
1034  /* Read error, device is disconnected */
1036  }
1037  return (size >= 0);
1038 }
1039 
1040 static SDL_bool
1041 HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
1042 {
1043  SDL_Joystick *joystick = NULL;
1044 
1045  if (device->num_joysticks > 0) {
1046  joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
1047  }
1048  if (!joystick) {
1049  return SDL_FALSE;
1050  }
1051  return HIDAPI_DriverXboxOne_UpdateJoystick(device, joystick);
1052 }
1053 
1054 static void
1055 HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
1056 {
1057  hid_close(device->dev);
1058  device->dev = NULL;
1059 
1060  SDL_free(device->context);
1061  device->context = NULL;
1062 }
1063 
1064 static void
1065 HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device *device)
1066 {
1067 }
1068 
1070 {
1072  SDL_TRUE,
1073  HIDAPI_DriverXboxOne_IsSupportedDevice,
1074  HIDAPI_DriverXboxOne_GetDeviceName,
1075  HIDAPI_DriverXboxOne_InitDevice,
1076  HIDAPI_DriverXboxOne_GetDevicePlayerIndex,
1077  HIDAPI_DriverXboxOne_SetDevicePlayerIndex,
1078  HIDAPI_DriverXboxOne_UpdateDevice,
1079  HIDAPI_DriverXboxOne_OpenJoystick,
1080  HIDAPI_DriverXboxOne_RumbleJoystick,
1081  HIDAPI_DriverXboxOne_RumbleJoystickTriggers,
1082  HIDAPI_DriverXboxOne_HasJoystickLED,
1083  HIDAPI_DriverXboxOne_SetJoystickLED,
1084  HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled,
1085  HIDAPI_DriverXboxOne_CloseJoystick,
1086  HIDAPI_DriverXboxOne_FreeDevice,
1087 };
1088 
1089 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
1090 
1091 #endif /* SDL_JOYSTICK_HIDAPI */
1092 
1093 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_SetError
#define SDL_JoystickFromInstanceID
#define SDL_free
#define SDL_strdup
#define SDL_strcmp
#define SDL_memcmp
#define SDL_memcpy
#define SDL_Log
#define SDL_calloc
#define SDL_uitoa
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_PRESSED
Definition: SDL_events.h:50
@ SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_BACK
@ SDL_CONTROLLER_BUTTON_LEFTSTICK
@ SDL_CONTROLLER_BUTTON_START
@ SDL_CONTROLLER_BUTTON_DPAD_LEFT
@ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
@ SDL_CONTROLLER_BUTTON_DPAD_DOWN
@ SDL_CONTROLLER_BUTTON_DPAD_UP
@ SDL_CONTROLLER_BUTTON_LEFTSHOULDER
@ SDL_CONTROLLER_BUTTON_GUIDE
@ SDL_CONTROLLER_BUTTON_DPAD_RIGHT
@ SDL_CONTROLLER_BUTTON_MISC1
@ SDL_CONTROLLER_BUTTON_X
@ SDL_CONTROLLER_BUTTON_RIGHTSTICK
@ SDL_CONTROLLER_BUTTON_Y
@ SDL_CONTROLLER_BUTTON_A
SDL_GameControllerType
@ SDL_CONTROLLER_TYPE_XBOXONE
const GLubyte GLuint red
Definition: SDL_glfuncs.h:80
#define USB_PACKET_LENGTH
void HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne
#define SDL_HINT_JOYSTICK_HIDAPI_XBOX
A variable controlling whether the HIDAPI driver for XBox controllers should be used.
Definition: SDL_hints.h:664
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
SDL_bool SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
@ SDL_JOYSTICK_POWER_FULL
Definition: SDL_joystick.h:103
@ SDL_JOYSTICK_POWER_MEDIUM
Definition: SDL_joystick.h:102
@ SDL_JOYSTICK_POWER_WIRED
Definition: SDL_joystick.h:104
@ SDL_JOYSTICK_POWER_LOW
Definition: SDL_joystick.h:101
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLbyte GLbyte blue
GLuint const GLchar * name
GLsizeiptr size
GLbitfield flags
GLbyte green
uint16_t Uint16
Definition: SDL_stdinc.h:197
int16_t Sint16
Definition: SDL_stdinc.h:191
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:121
uint8_t Uint8
Definition: SDL_stdinc.h:185
#define SDL_min(x, y)
Definition: SDL_stdinc.h:412
uint32_t Uint32
Definition: SDL_stdinc.h:209
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
struct xkb_state * state
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
#define NULL
Definition: begin_code.h:163
EGLContext ctx
Definition: eglext.h:208
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.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
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.
static SDL_AudioDeviceID device
Definition: loopwave.c:37
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
SDL_Texture * axis
static SDL_Joystick * joystick
Definition: testjoystick.c:37
#define USB_VENDOR_PDP
Definition: usb_ids.h:32
#define USB_VENDOR_POWERA
Definition: usb_ids.h:33
#define USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH
Definition: usb_ids.h:54
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH
Definition: usb_ids.h:51
#define USB_VENDOR_MICROSOFT
Definition: usb_ids.h:29
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH
Definition: usb_ids.h:49
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH
Definition: usb_ids.h:52
#define USB_PRODUCT_RAZER_ATROX
Definition: usb_ids.h:42
#define USB_VENDOR_RAZER
Definition: usb_ids.h:35
typedef int(__stdcall *FARPROC)()