src/joystick/hidapi/SDL_hidapi_xboxone.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 09 Dec 2019 16:52:11 -0800
changeset 13324 b46a94bb2ab0
parent 13323 a8804daa1c3d
child 13330 c88765bcf1da
permissions -rw-r--r--
Fixed rumble after Xbox controller initialization
When we initialize the controller it has an internal rumble sequence number, and if our rumble sequence number doesn't match that, rumble won't happen. To fix that we cycle through the range of sequence numbers, and at some point we'll match up with the controller's sequence number and it'll roll forward until it matches our next rumble sequence number.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 
    34 
    35 #ifdef SDL_JOYSTICK_HIDAPI_XBOXONE
    36 
    37 #define USB_PACKET_LENGTH   64
    38 
    39 /* The amount of time to wait after hotplug to send controller init sequence */
    40 #define CONTROLLER_INIT_DELAY_MS    100
    41 
    42 /* This is the full init sequence for the Xbox One Elite Series 2 controller.
    43    Normally it isn't needed, but this switches the controller back to wired report mode after being in Bluetooth mode.
    44 */
    45 static const Uint8 xboxone_elite_init0[] = {
    46     0x04, 0x20, 0x01, 0x00
    47 };
    48 static const Uint8 xboxone_elite_init1[] = {
    49     0x01, 0x20, 0x28, 0x09, 0x00, 0x04, 0x20, 0x3A,
    50     0x00, 0x00, 0x00, 0x31, 0x01
    51 };
    52 static const Uint8 xboxone_elite_init2[] = {
    53     0x01, 0x20, 0x28, 0x09, 0x00, 0x04, 0x20, 0x6B,
    54     0x01, 0x00, 0x00, 0x00, 0x00
    55 };
    56 static const Uint8 xboxone_elite_init3[] = {
    57     0x05, 0x20, 0x02, 0x0F, 0x06, 0x00, 0x00, 0x00,
    58     0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
    59     0x00, 0x00, 0x00
    60 };
    61 static const Uint8 xboxone_elite_init4[] = {
    62     0x05, 0x20, 0x03, 0x01, 0x00
    63 };
    64 static const Uint8 xboxone_elite_init5[] = {
    65     0x0A, 0x20, 0x04, 0x03, 0x00, 0x01, 0x14
    66 };
    67 
    68 /*
    69  * This packet is required for all Xbox One pads with 2015
    70  * or later firmware installed (or present from the factory).
    71  */
    72 static const Uint8 xboxone_fw2015_init[] = {
    73     0x05, 0x20, 0x00, 0x01, 0x00
    74 };
    75 
    76 /*
    77  * This packet is required for the Titanfall 2 Xbox One pads
    78  * (0x0e6f:0x0165) to finish initialization and for Hori pads
    79  * (0x0f0d:0x0067) to make the analog sticks work.
    80  */
    81 static const Uint8 xboxone_hori_init[] = {
    82     0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
    83     0x00, 0x00, 0x00, 0x80, 0x00
    84 };
    85 
    86 /*
    87  * This packet is required for some of the PDP pads to start
    88  * sending input reports. These pads include: (0x0e6f:0x02ab),
    89  * (0x0e6f:0x02a4).
    90  */
    91 static const Uint8 xboxone_pdp_init1[] = {
    92     0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
    93 };
    94 
    95 /*
    96  * This packet is required for some of the PDP pads to start
    97  * sending input reports. These pads include: (0x0e6f:0x02ab),
    98  * (0x0e6f:0x02a4).
    99  */
   100 static const Uint8 xboxone_pdp_init2[] = {
   101     0x06, 0x20, 0x00, 0x02, 0x01, 0x00
   102 };
   103 
   104 /*
   105  * A specific rumble packet is required for some PowerA pads to start
   106  * sending input reports. One of those pads is (0x24c6:0x543a).
   107  */
   108 static const Uint8 xboxone_rumblebegin_init[] = {
   109     0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
   110     0x1D, 0x1D, 0xFF, 0x00, 0x00
   111 };
   112 
   113 /*
   114  * A rumble packet with zero FF intensity will immediately
   115  * terminate the rumbling required to init PowerA pads.
   116  * This should happen fast enough that the motors don't
   117  * spin up to enough speed to actually vibrate the gamepad.
   118  */
   119 static const Uint8 xboxone_rumbleend_init[] = {
   120     0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
   121     0x00, 0x00, 0x00, 0x00, 0x00
   122 };
   123 
   124 /*
   125  * This specifies the selection of init packets that a gamepad
   126  * will be sent on init *and* the order in which they will be
   127  * sent. The correct sequence number will be added when the
   128  * packet is going to be sent.
   129  */
   130 typedef struct {
   131     Uint16 vendor_id;
   132     Uint16 product_id;
   133     const Uint8 *data;
   134     int size;
   135 } SDL_DriverXboxOne_InitPacket;
   136 
   137 
   138 static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
   139     { 0x0e6f, 0x0165, xboxone_hori_init, sizeof(xboxone_hori_init) },
   140     { 0x0f0d, 0x0067, xboxone_hori_init, sizeof(xboxone_hori_init) },
   141     { 0x045e, 0x0b00, xboxone_elite_init0, sizeof(xboxone_elite_init0) },
   142     { 0x045e, 0x0b00, xboxone_elite_init1, sizeof(xboxone_elite_init1) },
   143     { 0x045e, 0x0b00, xboxone_elite_init2, sizeof(xboxone_elite_init2) },
   144     { 0x045e, 0x0b00, xboxone_elite_init3, sizeof(xboxone_elite_init3) },
   145     { 0x045e, 0x0b00, xboxone_elite_init4, sizeof(xboxone_elite_init4) },
   146     { 0x045e, 0x0b00, xboxone_elite_init5, sizeof(xboxone_elite_init5) },
   147     { 0x0000, 0x0000, xboxone_fw2015_init, sizeof(xboxone_fw2015_init) },
   148     { 0x0e6f, 0x0000, xboxone_pdp_init1, sizeof(xboxone_pdp_init1) },
   149     { 0x0e6f, 0x0000, xboxone_pdp_init2, sizeof(xboxone_pdp_init2) },
   150     { 0x24c6, 0x541a, xboxone_rumblebegin_init, sizeof(xboxone_rumblebegin_init) },
   151     { 0x24c6, 0x542a, xboxone_rumblebegin_init, sizeof(xboxone_rumblebegin_init) },
   152     { 0x24c6, 0x543a, xboxone_rumblebegin_init, sizeof(xboxone_rumblebegin_init) },
   153     { 0x24c6, 0x541a, xboxone_rumbleend_init, sizeof(xboxone_rumbleend_init) },
   154     { 0x24c6, 0x542a, xboxone_rumbleend_init, sizeof(xboxone_rumbleend_init) },
   155     { 0x24c6, 0x543a, xboxone_rumbleend_init, sizeof(xboxone_rumbleend_init) },
   156 };
   157 
   158 typedef struct {
   159     Uint16 vendor_id;
   160     Uint16 product_id;
   161     Uint32 start_time;
   162     SDL_bool initialized;
   163     Uint8 sequence;
   164     Uint8 last_state[USB_PACKET_LENGTH];
   165     Uint32 rumble_expiration;
   166 } SDL_DriverXboxOne_Context;
   167 
   168 
   169 static SDL_bool
   170 IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
   171 {
   172     /* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
   173     const Uint16 USB_VENDOR_MICROSOFT = 0x045e;
   174     const Uint16 USB_PRODUCT_XBOX_ONE_S_REV1 = 0x02e0;
   175     const Uint16 USB_PRODUCT_XBOX_ONE_S_REV2 = 0x02fd;
   176     const Uint16 USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 = 0x0b05;
   177 
   178     if (vendor_id == USB_VENDOR_MICROSOFT) {
   179         if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1 ||
   180             product_id == USB_PRODUCT_XBOX_ONE_S_REV2 ||
   181             product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) {
   182             return SDL_TRUE;
   183         }
   184     }
   185     return SDL_FALSE;
   186 }
   187 
   188 static SDL_bool
   189 SendControllerInit(hid_device *dev, SDL_DriverXboxOne_Context *ctx)
   190 {
   191     Uint16 vendor_id = ctx->vendor_id;
   192     Uint16 product_id = ctx->product_id;
   193 
   194     if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
   195         int i, j;
   196         Uint8 init_packet[USB_PACKET_LENGTH];
   197 
   198         for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
   199             const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
   200 
   201             if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
   202                 continue;
   203             }
   204 
   205             if (packet->product_id && (product_id != packet->product_id)) {
   206                 continue;
   207             }
   208 
   209             SDL_memcpy(init_packet, packet->data, packet->size);
   210             init_packet[2] = ctx->sequence++;
   211             if (hid_write(dev, init_packet, packet->size) != packet->size) {
   212                 SDL_SetError("Couldn't write Xbox One initialization packet");
   213                 return SDL_FALSE;
   214             }
   215 
   216             /* After the init we need to sync up the rumble sequence */
   217             if (packet->data == xboxone_fw2015_init) {
   218                 for (j = 0; j < 255; ++j) {
   219                     if (hid_write(dev, xboxone_rumbleend_init, sizeof(xboxone_rumbleend_init)) != sizeof(xboxone_rumbleend_init)) {
   220                         SDL_SetError("Couldn't write Xbox One initialization packet");
   221                         return SDL_FALSE;
   222                     }
   223                 }
   224             }
   225         }
   226     }
   227     return SDL_TRUE;
   228 }
   229 
   230 
   231 static SDL_bool
   232 HIDAPI_DriverXboxOne_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name)
   233 {
   234 #ifdef __LINUX__
   235     if (IsBluetoothXboxOneController(vendor_id, product_id)) {
   236         /* We can't do rumble on this device, hid_write() fails, so don't try to open it here */
   237         return SDL_FALSE;
   238     }
   239     if (vendor_id == 0x24c6 && product_id == 0x541a) {
   240         /* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
   241         return SDL_FALSE;
   242     }
   243 #endif
   244     return (SDL_GetJoystickGameControllerType(vendor_id, product_id, name) == SDL_CONTROLLER_TYPE_XBOXONE);
   245 }
   246 
   247 static const char *
   248 HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
   249 {
   250     return HIDAPI_XboxControllerName(vendor_id, product_id);
   251 }
   252 
   253 static SDL_bool
   254 HIDAPI_DriverXboxOne_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
   255 {
   256     SDL_DriverXboxOne_Context *ctx;
   257 
   258     ctx = (SDL_DriverXboxOne_Context *)SDL_calloc(1, sizeof(*ctx));
   259     if (!ctx) {
   260         SDL_OutOfMemory();
   261         return SDL_FALSE;
   262     }
   263     *context = ctx;
   264 
   265     ctx->vendor_id = vendor_id;
   266     ctx->product_id = product_id;
   267     ctx->start_time = SDL_GetTicks();
   268 
   269     /* Initialize the joystick capabilities */
   270     joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   271     joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
   272     joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
   273 
   274     return SDL_TRUE;
   275 }
   276 
   277 static int
   278 HIDAPI_DriverXboxOne_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   279 {
   280     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
   281     Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
   282 
   283     if (!ctx->initialized) {
   284         return 0;
   285     }
   286 
   287     /* Magnitude is 1..100 so scale the 16-bit input here */
   288     rumble_packet[2] = ctx->sequence++;
   289     rumble_packet[8] = low_frequency_rumble / 655;
   290     rumble_packet[9] = high_frequency_rumble / 655;
   291 
   292     if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
   293         return SDL_SetError("Couldn't send rumble packet");
   294     }
   295 
   296     if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
   297         ctx->rumble_expiration = SDL_GetTicks() + duration_ms;
   298     } else {
   299         ctx->rumble_expiration = 0;
   300     }
   301     return 0;
   302 }
   303 
   304 static void
   305 HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
   306 {
   307     Sint16 axis;
   308 
   309     if (ctx->last_state[4] != data[4]) {
   310         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[4] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   311         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[4] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   312         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   313         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   314         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   315         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   316     }
   317 
   318     if (ctx->last_state[5] != data[5]) {
   319         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data[5] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   320         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data[5] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
   321         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data[5] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
   322         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data[5] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
   323         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
   324         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
   325         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[5] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
   326         SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[5] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
   327     }
   328 
   329     axis = ((int)*(Sint16*)(&data[6]) * 64) - 32768;
   330     if (axis == 32704) {
   331         axis = 32767;
   332     }
   333     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
   334     axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
   335     if (axis == 32704) {
   336         axis = 32767;
   337     }
   338     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
   339     axis = *(Sint16*)(&data[10]);
   340     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
   341     axis = *(Sint16*)(&data[12]);
   342     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~axis);
   343     axis = *(Sint16*)(&data[14]);
   344     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
   345     axis = *(Sint16*)(&data[16]);
   346     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~axis);
   347 
   348     SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
   349 }
   350 
   351 static void
   352 HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
   353 {
   354     if (data[1] == 0x30) {
   355         /* The Xbox One S controller needs acks for mode reports */
   356         const Uint8 seqnum = data[2];
   357         const Uint8 ack[] = { 0x01, 0x20, seqnum, 0x09, 0x00, 0x07, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
   358         hid_write(dev, ack, sizeof(ack));
   359     }
   360 
   361     SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
   362 }
   363 
   364 static SDL_bool
   365 HIDAPI_DriverXboxOne_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
   366 {
   367     SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)context;
   368     Uint8 data[USB_PACKET_LENGTH];
   369     int size;
   370 
   371     if (!ctx->initialized) {
   372         if (SDL_TICKS_PASSED(SDL_GetTicks(), ctx->start_time + CONTROLLER_INIT_DELAY_MS)) {
   373             if (!SendControllerInit(dev, ctx)) {
   374                 return SDL_FALSE;
   375             }
   376             ctx->initialized = SDL_TRUE;
   377         }
   378     }
   379 
   380     while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
   381 #ifdef DEBUG_XBOX_PROTOCOL
   382         SDL_Log("Xbox One packet: size = %d\n"
   383                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   384                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n"
   385                 "                 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
   386                     size,
   387                     data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
   388                     data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
   389                     data[16], data[17], data[18], data[19]);
   390 #endif
   391         switch (data[0]) {
   392         case 0x20:
   393             HIDAPI_DriverXboxOne_HandleStatePacket(joystick, dev, ctx, data, size);
   394             break;
   395         case 0x07:
   396             HIDAPI_DriverXboxOne_HandleModePacket(joystick, dev, ctx, data, size);
   397             break;
   398         default:
   399 #ifdef DEBUG_JOYSTICK
   400             SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
   401 #endif
   402             break;
   403         }
   404     }
   405 
   406     if (ctx->rumble_expiration) {
   407         Uint32 now = SDL_GetTicks();
   408         if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
   409             HIDAPI_DriverXboxOne_Rumble(joystick, dev, context, 0, 0, 0);
   410         }
   411     }
   412 
   413     return (size >= 0);
   414 }
   415 
   416 static void
   417 HIDAPI_DriverXboxOne_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
   418 {
   419     SDL_free(context);
   420 }
   421 
   422 SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
   423 {
   424     SDL_HINT_JOYSTICK_HIDAPI_XBOX,
   425     SDL_TRUE,
   426     HIDAPI_DriverXboxOne_IsSupportedDevice,
   427     HIDAPI_DriverXboxOne_GetDeviceName,
   428     HIDAPI_DriverXboxOne_Init,
   429     HIDAPI_DriverXboxOne_Rumble,
   430     HIDAPI_DriverXboxOne_Update,
   431     HIDAPI_DriverXboxOne_Quit
   432 };
   433 
   434 #endif /* SDL_JOYSTICK_HIDAPI_XBOXONE */
   435 
   436 #endif /* SDL_JOYSTICK_HIDAPI */
   437 
   438 /* vi: set ts=4 sw=4 expandtab: */