21 #include "../../SDL_internal.h"
23 #ifdef SDL_JOYSTICK_HIDAPI
31 #include "../SDL_sysjoystick.h"
36 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
42 #define CONTROLLER_INIT_DELAY_MS 1500
45 static const Uint8 xboxone_init0[] = {
46 0x04, 0x20, 0x00, 0x00
49 static const Uint8 xboxone_init1[] = {
50 0x01, 0x20, 0x01, 0x09, 0x00, 0x04, 0x20, 0x3a,
51 0x00, 0x00, 0x00, 0x80, 0x00
54 static const Uint8 xboxone_init2[] = {
55 0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
60 static const Uint8 xboxone_init3[] = {
61 0x05, 0x20, 0x03, 0x01, 0x00
64 static const Uint8 xboxone_init4[] = {
65 0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
68 static const Uint8 xboxone_init5[] = {
69 0x06, 0x20, 0x00, 0x02, 0x01, 0x00
72 static const Uint8 xboxone_init6[] = {
73 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
74 0x00, 0x00, 0xFF, 0x00, 0xEB
90 const Uint8 response[2];
91 } SDL_DriverXboxOne_InitPacket;
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 } },
104 { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5,
sizeof(xboxone_init5), { 0x00, 0x00 } },
105 { 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init6,
sizeof(xboxone_init6), { 0x00, 0x00 } },
109 XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN,
110 XBOX_ONE_WIRELESS_PROTOCOL_V1,
111 XBOX_ONE_WIRELESS_PROTOCOL_V2,
112 } SDL_XboxOneWirelessProtocol;
118 SDL_XboxOneWirelessProtocol wireless_protocol;
124 } SDL_DriverXboxOne_Context;
127 #ifdef DEBUG_XBOX_PROTOCOL
147 IsBluetoothXboxOneController(
Uint16 vendor_id,
Uint16 product_id)
161 ControllerHasPaddles(
Uint16 vendor_id,
Uint16 product_id)
174 ControllerSendsWaitingForInit(
Uint16 vendor_id,
Uint16 product_id)
202 const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[
i];
204 if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
208 if (packet->product_id && (product_id != packet->product_id)) {
212 if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
216 if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
220 SDL_memcpy(init_packet, packet->data, packet->size);
221 if (init_packet[0] != 0x01) {
222 init_packet[2] =
ctx->sequence++;
224 if (
hid_write(
device->dev, init_packet, packet->size) != packet->size) {
225 SDL_SetError(
"Couldn't write Xbox One initialization packet");
229 if (packet->response[0]) {
230 const Uint32 RESPONSE_TIMEOUT_MS = 50;
239 #ifdef DEBUG_XBOX_PROTOCOL
240 DumpPacket(
"Xbox One INIT packet: size = %d",
data,
size);
242 if (
size >= 2 &&
data[0] == packet->response[0] &&
data[1] == packet->response[1]) {
247 #ifdef DEBUG_XBOX_PROTOCOL
248 SDL_Log(
"Init sequence %d got response: %s\n",
i, got_response ?
"TRUE" :
"FALSE");
266 if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
274 HIDAPI_DriverXboxOne_GetDeviceName(
Uint16 vendor_id,
Uint16 product_id)
299 SDL_DriverXboxOne_Context *
ctx;
317 ctx->bluetooth = IsBluetoothXboxOneController(
device->vendor_id,
device->product_id);
321 ctx->has_paddles = ControllerHasPaddles(
ctx->vendor_id,
ctx->product_id);
334 SDL_DriverXboxOne_Context *
ctx = (SDL_DriverXboxOne_Context *)
device->context;
336 if (
ctx->bluetooth) {
337 Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
339 rumble_packet[4] = (low_frequency_rumble >> 8);
340 rumble_packet[5] = (high_frequency_rumble >> 8);
342 if (SDL_HIDAPI_SendRumble(
device, rumble_packet,
sizeof(rumble_packet)) !=
sizeof(rumble_packet)) {
346 Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
349 rumble_packet[8] = low_frequency_rumble / 655;
350 rumble_packet[9] = high_frequency_rumble / 655;
352 if (SDL_HIDAPI_SendRumble(
device, rumble_packet,
sizeof(rumble_packet)) !=
sizeof(rumble_packet)) {
360 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick,
hid_device *dev, SDL_DriverXboxOne_Context *
ctx,
Uint8 *
data,
int size)
364 if (
ctx->last_state[4] !=
data[4]) {
373 if (
ctx->last_state[5] !=
data[5]) {
394 if (
ctx->has_paddles && (
size == 33 ||
size == 38)) {
420 paddles_mapped = (
data[19] != 0);
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"
432 if (paddles_mapped) {
434 data[paddle_index] = 0;
437 if (
ctx->last_state[paddle_index] !=
data[paddle_index]) {
468 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick,
hid_device *dev, SDL_DriverXboxOne_Context *
ctx,
Uint8 *
data,
int size)
470 if (
data[1] == 0x30) {
473 const Uint8 ack[] = { 0x01, 0x20, seqnum, 0x09, 0x00, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
481 HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick,
hid_device *dev, SDL_DriverXboxOne_Context *
ctx,
Uint8 *
data,
int size)
485 if (
ctx->last_state[14] !=
data[14]) {
494 if (
ctx->last_state[15] !=
data[15]) {
498 if (
ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN)
500 if (
data[15] & 0x10) {
501 ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V2;
504 if (
ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_V2)
510 if (
ctx->last_state[16] !=
data[16]) {
514 if (
ctx->last_state[13] !=
data[13]) {
583 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick,
hid_device *dev, SDL_DriverXboxOne_Context *
ctx,
Uint8 *
data,
int size)
585 ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V1;
592 SDL_DriverXboxOne_Context *
ctx = (SDL_DriverXboxOne_Context *)
device->context;
593 SDL_Joystick *joystick =
NULL;
604 if (!
ctx->initialized &&
605 !ControllerSendsWaitingForInit(
device->vendor_id,
device->product_id)) {
616 #ifdef DEBUG_XBOX_PROTOCOL
617 DumpPacket(
"Xbox One packet: size = %d",
data,
size);
619 if (
ctx->bluetooth) {
622 HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick,
device->dev,
ctx,
data,
size);
625 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick,
device->dev,
ctx,
data,
size);
628 #ifdef DEBUG_JOYSTICK
629 SDL_Log(
"Unknown Xbox One packet: 0x%.2x\n",
data[0]);
637 if (!
ctx->initialized) {
638 #ifdef DEBUG_XBOX_PROTOCOL
658 #ifdef DEBUG_JOYSTICK
659 SDL_Log(
"Unknown Xbox One packet: 0x%.2x\n",
data[0]);
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