src/joystick/hidapi/SDL_hidapi_xboxone.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 13 Mar 2020 19:00:24 -0700
changeset 13620 317366b2c172
parent 13606 6b0a65d1e16f
child 13633 340324c76848
permissions -rw-r--r--
Added support for the older Xbox One S Bluetooth controller report format
     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 ||
   152             product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
   153             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_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;
   231             Uint32 start = SDL_GetTicks();
   232             SDL_bool got_response = SDL_FALSE;
   233 
   234             while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
   235                 Uint8 data[USB_PACKET_LENGTH];
   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 {
   282     return HIDAPI_JoystickConnected(device, NULL);
   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]) {
   365         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[4] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   366         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[4] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   367         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   368         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   369         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   370         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   371     }
   372 
   373     if (ctx->last_state[5] != data[5]) {
   374         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data[5] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   375         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data[5] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   376         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data[5] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   377         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data[5] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   378         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   379         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   380         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[5] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   381         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[5] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   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     }
   449     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
   450     axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
   451     if (axis == 32704) {
   452         axis = 32767;
   453     }
   454     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
   455     axis = *(Sint16*)(&data[10]);
   456     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
   457     axis = *(Sint16*)(&data[12]);
   458     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
   459     axis = *(Sint16*)(&data[14]);
   460     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
   461     axis = *(Sint16*)(&data[16]);
   462     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
   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 
   477     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   478 }
   479 
   480 static void
   481 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV1(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]) {
   486         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   487         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   488         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   489         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   490         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   491         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   492         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   493         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   494     }
   495 
   496     if (ctx->last_state[15] != data[15]) {
   497         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   498         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   499     }
   500 
   501     if (ctx->last_state[13] != data[13]) {
   502         SDL_bool dpad_up = SDL_FALSE;
   503         SDL_bool dpad_down = SDL_FALSE;
   504         SDL_bool dpad_left = SDL_FALSE;
   505         SDL_bool dpad_right = SDL_FALSE;
   506 
   507         switch (data[13]) {
   508         case 1:
   509             dpad_up = SDL_TRUE;
   510             break;
   511         case 2:
   512             dpad_up = SDL_TRUE;
   513             dpad_right = SDL_TRUE;
   514             break;
   515         case 3:
   516             dpad_right = SDL_TRUE;
   517             break;
   518         case 4:
   519             dpad_right = SDL_TRUE;
   520             dpad_down = SDL_TRUE;
   521             break;
   522         case 5:
   523             dpad_down = SDL_TRUE;
   524             break;
   525         case 6:
   526             dpad_left = SDL_TRUE;
   527             dpad_down = SDL_TRUE;
   528             break;
   529         case 7:
   530             dpad_left = SDL_TRUE;
   531             break;
   532         case 8:
   533             dpad_up = SDL_TRUE;
   534             dpad_left = SDL_TRUE;
   535             break;
   536         default:
   537             break;
   538         }
   539         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
   540         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
   541         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
   542         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
   543     }
   544 
   545     axis = (int)*(Uint16*)(&data[1]) - 0x8000;
   546     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
   547     axis = (int)*(Uint16*)(&data[3]) - 0x8000;
   548     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
   549     axis = (int)*(Uint16*)(&data[5]) - 0x8000;
   550     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
   551     axis = (int)*(Uint16*)(&data[7]) - 0x8000;
   552     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
   553 
   554     axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
   555     if (axis == 32704) {
   556         axis = 32767;
   557     }
   558     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
   559 
   560     axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
   561     if (axis == 32704) {
   562         axis = 32767;
   563     }
   564     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
   565 
   566     SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
   567 }
   568 
   569 static void
   570 HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV2(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
   571 {
   572     Sint16 axis;
   573 
   574     if (ctx->last_state[14] != data[14]) {
   575         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   576         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   577         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   578         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   579         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   580         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   581     }
   582 
   583     if (ctx->last_state[15] != data[15]) {
   584         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   585         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   586         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   587         if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN)
   588         {
   589             if (data[15] & 0x10) {
   590                 ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V2;
   591             }
   592         }
   593         if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_V2)
   594         {
   595             SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   596         }
   597     }
   598 
   599     if (ctx->last_state[16] != data[16]) {
   600         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   601     }
   602 
   603     if (ctx->last_state[13] != data[13]) {
   604         SDL_bool dpad_up = SDL_FALSE;
   605         SDL_bool dpad_down = SDL_FALSE;
   606         SDL_bool dpad_left = SDL_FALSE;
   607         SDL_bool dpad_right = SDL_FALSE;
   608 
   609         switch (data[13]) {
   610         case 1:
   611             dpad_up = SDL_TRUE;
   612             break;
   613         case 2:
   614             dpad_up = SDL_TRUE;
   615             dpad_right = SDL_TRUE;
   616             break;
   617         case 3:
   618             dpad_right = SDL_TRUE;
   619             break;
   620         case 4:
   621             dpad_right = SDL_TRUE;
   622             dpad_down = SDL_TRUE;
   623             break;
   624         case 5:
   625             dpad_down = SDL_TRUE;
   626             break;
   627         case 6:
   628             dpad_left = SDL_TRUE;
   629             dpad_down = SDL_TRUE;
   630             break;
   631         case 7:
   632             dpad_left = SDL_TRUE;
   633             break;
   634         case 8:
   635             dpad_up = SDL_TRUE;
   636             dpad_left = SDL_TRUE;
   637             break;
   638         default:
   639             break;
   640         }
   641         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
   642         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
   643         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
   644         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
   645     }
   646 
   647     axis = (int)*(Uint16*)(&data[1]) - 0x8000;
   648     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
   649     axis = (int)*(Uint16*)(&data[3]) - 0x8000;
   650     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
   651     axis = (int)*(Uint16*)(&data[5]) - 0x8000;
   652     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
   653     axis = (int)*(Uint16*)(&data[7]) - 0x8000;
   654     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
   655 
   656     axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
   657     if (axis == 32704) {
   658         axis = 32767;
   659     }
   660     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
   661 
   662     axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
   663     if (axis == 32704) {
   664         axis = 32767;
   665     }
   666     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
   667 
   668     SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
   669 }
   670 
   671 static void
   672 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
   673 {
   674     ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V1;
   675     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   676 }
   677 
   678 static SDL_bool
   679 HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
   680 {
   681     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
   682     SDL_Joystick *joystick = NULL;
   683     Uint8 data[USB_PACKET_LENGTH];
   684     int size;
   685 
   686     if (device->num_joysticks > 0) {
   687         joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
   688     }
   689     if (!joystick) {
   690         return SDL_FALSE;
   691     }
   692 
   693     if (!ctx->initialized &&
   694         !ControllerSendsWaitingForInit(device->vendor_id, device->product_id)) {
   695         if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
   696             if (!SendControllerInit(device, ctx)) {
   697                 HIDAPI_JoystickDisconnected(device, joystick->instance_id);
   698                 return SDL_FALSE;
   699             }
   700             ctx->initialized = SDL_TRUE;
   701         }
   702     }
   703 
   704     while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
   705 #ifdef DEBUG_XBOX_PROTOCOL
   706         DumpPacket("Xbox One packet: size = %d", data, size);
   707 #endif
   708         if (ctx->bluetooth) {
   709             switch (data[0]) {
   710             case 0x01:
   711                 switch (size) {
   712                 case 16:
   713                     HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV1(joystick, device->dev, ctx, data, size);
   714                     break;
   715                 case 17:
   716                     HIDAPI_DriverXboxOneBluetooth_HandleStatePacketV2(joystick, device->dev, ctx, data, size);
   717                     break;
   718                 default:
   719                     break;
   720                 }
   721                 break;
   722             case 0x02:
   723                 HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
   724                 break;
   725             default:
   726 #ifdef DEBUG_JOYSTICK
   727                 SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
   728 #endif
   729                 break;
   730             }
   731         } else {
   732             switch (data[0]) {
   733             case 0x02:
   734                 /* Controller is connected and waiting for initialization */
   735                 if (!ctx->initialized) {
   736 #ifdef DEBUG_XBOX_PROTOCOL
   737                     SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
   738 #endif
   739                     if (!SendControllerInit(device, ctx)) {
   740                         HIDAPI_JoystickDisconnected(device, joystick->instance_id);
   741                         return SDL_FALSE;
   742                     }
   743                     ctx->initialized = SDL_TRUE;
   744                 }
   745                 break;
   746             case 0x03:
   747                 /* Controller heartbeat */
   748                 break;
   749             case 0x20:
   750                 HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
   751                 break;
   752             case 0x07:
   753                 HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
   754                 break;
   755             default:
   756 #ifdef DEBUG_JOYSTICK
   757                 SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
   758 #endif
   759                 break;
   760             }
   761         }
   762     }
   763 
   764     if (size < 0) {
   765         /* Read error, device is disconnected */
   766         HIDAPI_JoystickDisconnected(device, joystick->instance_id);
   767     }
   768     return (size >= 0);
   769 }
   770 
   771 static void
   772 HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   773 {
   774     hid_close(device->dev);
   775     device->dev = NULL;
   776 
   777     SDL_free(device->context);
   778     device->context = NULL;
   779 }
   780 
   781 static void
   782 HIDAPI_DriverXboxOne_FreeDevice(SDL_HIDAPI_Device *device)
   783 {
   784 }
   785 
   786 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
   787 {
   788     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   789     SDL_TRUE,
   790     HIDAPI_DriverXboxOne_IsSupportedDevice,
   791     HIDAPI_DriverXboxOne_GetDeviceName,
   792     HIDAPI_DriverXboxOne_InitDevice,
   793     HIDAPI_DriverXboxOne_GetDevicePlayerIndex,
   794     HIDAPI_DriverXboxOne_SetDevicePlayerIndex,
   795     HIDAPI_DriverXboxOne_UpdateDevice,
   796     HIDAPI_DriverXboxOne_OpenJoystick,
   797     HIDAPI_DriverXboxOne_RumbleJoystick,
   798     HIDAPI_DriverXboxOne_CloseJoystick,
   799     HIDAPI_DriverXboxOne_FreeDevice
   800 };
   801 
   802 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
   803 
   804 #endif /* SDL_JOYSTICK_HIDAPI */
   805 
   806 /* vi: set ts=4 sw=4 expandtab: */