src/joystick/hidapi/SDL_hidapi_xbox360.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 09 Aug 2018 16:00:17 -0700
changeset 12088 399cc39583cc
child 12111 6c1ae9f1effb
permissions -rw-r--r--
Added HIDAPI joystick drivers for more consistent support for Xbox, PS4 and Nintendo Switch Pro controller support across platforms.
Added SDL_GameControllerRumble() and SDL_JoystickRumble() for simple force feedback outside of the SDL haptics API
slouken@12088
     1
/*
slouken@12088
     2
  Simple DirectMedia Layer
slouken@12088
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
slouken@12088
     4
slouken@12088
     5
  This software is provided 'as-is', without any express or implied
slouken@12088
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@12088
     7
  arising from the use of this software.
slouken@12088
     8
slouken@12088
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@12088
    10
  including commercial applications, and to alter it and redistribute it
slouken@12088
    11
  freely, subject to the following restrictions:
slouken@12088
    12
slouken@12088
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@12088
    14
     claim that you wrote the original software. If you use this software
slouken@12088
    15
     in a product, an acknowledgment in the product documentation would be
slouken@12088
    16
     appreciated but is not required.
slouken@12088
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@12088
    18
     misrepresented as being the original software.
slouken@12088
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@12088
    20
*/
slouken@12088
    21
#include "../../SDL_internal.h"
slouken@12088
    22
slouken@12088
    23
#ifdef SDL_JOYSTICK_HIDAPI
slouken@12088
    24
slouken@12088
    25
#include "SDL_hints.h"
slouken@12088
    26
#include "SDL_log.h"
slouken@12088
    27
#include "SDL_events.h"
slouken@12088
    28
#include "SDL_timer.h"
slouken@12088
    29
#include "SDL_joystick.h"
slouken@12088
    30
#include "SDL_gamecontroller.h"
slouken@12088
    31
#include "../SDL_sysjoystick.h"
slouken@12088
    32
#include "SDL_hidapijoystick_c.h"
slouken@12088
    33
slouken@12088
    34
slouken@12088
    35
#ifdef SDL_JOYSTICK_HIDAPI_XBOX360
slouken@12088
    36
slouken@12088
    37
#define USB_PACKET_LENGTH   64
slouken@12088
    38
slouken@12088
    39
typedef struct
slouken@12088
    40
{
slouken@12088
    41
    Uint16 vendor_id;
slouken@12088
    42
    Uint16 product_id;
slouken@12088
    43
    const char *name;
slouken@12088
    44
} SDL_DriverXbox360_DeviceName;
slouken@12088
    45
slouken@12088
    46
static const SDL_DriverXbox360_DeviceName xbox360_devicenames[] = {
slouken@12088
    47
    { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller" },
slouken@12088
    48
    { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID" },
slouken@12088
    49
    { 0x045e, 0x028e, "Microsoft X-Box 360 pad" },
slouken@12088
    50
    { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2" },
slouken@12088
    51
    { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)" },
slouken@12088
    52
    { 0x045e, 0x0719, "Xbox 360 Wireless Receiver" },
slouken@12088
    53
    { 0x046d, 0xc21d, "Logitech Gamepad F310" },
slouken@12088
    54
    { 0x046d, 0xc21e, "Logitech Gamepad F510" },
slouken@12088
    55
    { 0x046d, 0xc21f, "Logitech Gamepad F710" },
slouken@12088
    56
    { 0x046d, 0xc242, "Logitech Chillstream Controller" },
slouken@12088
    57
    { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel" },
slouken@12088
    58
    { 0x056e, 0x2004, "Elecom JC-U3613M" },
slouken@12088
    59
    { 0x06a3, 0xf51a, "Saitek P3600" },
slouken@12088
    60
    { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller" },
slouken@12088
    61
    { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE" },
slouken@12088
    62
    { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller" },
slouken@12088
    63
    { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad" },
slouken@12088
    64
    { 0x0738, 0x4736, "Mad Catz MicroCon Gamepad" },
slouken@12088
    65
    { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)" },
slouken@12088
    66
    { 0x0738, 0x4740, "Mad Catz Beat Pad" },
slouken@12088
    67
    { 0x0738, 0x4758, "Mad Catz Arcade Game Stick" },
slouken@12088
    68
    { 0x0738, 0x9871, "Mad Catz Portable Drum" },
slouken@12088
    69
    { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2" },
slouken@12088
    70
    { 0x0738, 0xb738, "Mad Catz MVC2TE Stick 2" },
slouken@12088
    71
    { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad" },
slouken@12088
    72
    { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360" },
slouken@12088
    73
    { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360" },
slouken@12088
    74
    { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02" },
slouken@12088
    75
    { 0x0738, 0xf738, "Super SFIV FightStick TE S" },
slouken@12088
    76
    { 0x07ff, 0xffff, "Mad Catz GamePad" },
slouken@12088
    77
    { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad" },
slouken@12088
    78
    { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360" },
slouken@12088
    79
    { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller" },
slouken@12088
    80
    { 0x0e6f, 0x0131, "PDP EA Sports Controller" },
slouken@12088
    81
    { 0x0e6f, 0x0133, "Xbox 360 Wired Controller" },
slouken@12088
    82
    { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller" },
slouken@12088
    83
    { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360" },
slouken@12088
    84
    { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360" },
slouken@12088
    85
    { 0x0e6f, 0x0301, "Logic3 Controller" },
slouken@12088
    86
    { 0x0e6f, 0x0401, "Logic3 Controller" },
slouken@12088
    87
    { 0x0e6f, 0x0413, "Afterglow AX.1 Gamepad for Xbox 360" },
slouken@12088
    88
    { 0x0e6f, 0x0501, "PDP Xbox 360 Controller" },
slouken@12088
    89
    { 0x0e6f, 0xf900, "PDP Afterglow AX.1" },
slouken@12088
    90
    { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick" },
slouken@12088
    91
    { 0x0f0d, 0x000c, "Hori PadEX Turbo" },
slouken@12088
    92
    { 0x0f0d, 0x000d, "Hori Fighting Stick EX2" },
slouken@12088
    93
    { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX" },
slouken@12088
    94
    { 0x0f0d, 0x001b, "Hori Real Arcade Pro VX" },
slouken@12088
    95
    { 0x11c9, 0x55f0, "Nacon GC-100XF" },
slouken@12088
    96
    { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad" },
slouken@12088
    97
    { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1" },
slouken@12088
    98
    { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick" },
slouken@12088
    99
    { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer" },
slouken@12088
   100
    { 0x1430, 0xf801, "RedOctane Controller" },
slouken@12088
   101
    { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller" },
slouken@12088
   102
    { 0x1532, 0x0037, "Razer Sabertooth" },
slouken@12088
   103
    { 0x15e4, 0x3f00, "Power A Mini Pro Elite" },
slouken@12088
   104
    { 0x15e4, 0x3f0a, "Xbox Airflo wired controller" },
slouken@12088
   105
    { 0x15e4, 0x3f10, "Batarang Xbox 360 controller" },
slouken@12088
   106
    { 0x162e, 0xbeef, "Joytech Neo-Se Take2" },
slouken@12088
   107
    { 0x1689, 0xfd00, "Razer Onza Tournament Edition" },
slouken@12088
   108
    { 0x1689, 0xfd01, "Razer Onza Classic Edition" },
slouken@12088
   109
    { 0x1689, 0xfe00, "Razer Sabertooth" },
slouken@12088
   110
    { 0x1bad, 0x0002, "Harmonix Rock Band Guitar" },
slouken@12088
   111
    { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit" },
slouken@12088
   112
    { 0x1bad, 0x0130, "Ion Drum Rocker" },
slouken@12088
   113
    { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller" },
slouken@12088
   114
    { 0x1bad, 0xf018, "Mad Catz Street Fighter IV SE Fighting Stick" },
slouken@12088
   115
    { 0x1bad, 0xf019, "Mad Catz Brawlstick for Xbox 360" },
slouken@12088
   116
    { 0x1bad, 0xf021, "Mad Cats Ghost Recon FS GamePad" },
slouken@12088
   117
    { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)" },
slouken@12088
   118
    { 0x1bad, 0xf025, "Mad Catz Call Of Duty" },
slouken@12088
   119
    { 0x1bad, 0xf027, "Mad Catz FPS Pro" },
slouken@12088
   120
    { 0x1bad, 0xf028, "Street Fighter IV FightPad" },
slouken@12088
   121
    { 0x1bad, 0xf02e, "Mad Catz Fightpad" },
slouken@12088
   122
    { 0x1bad, 0xf030, "Mad Catz Xbox 360 MC2 MicroCon Racing Wheel" },
slouken@12088
   123
    { 0x1bad, 0xf036, "Mad Catz MicroCon GamePad Pro" },
slouken@12088
   124
    { 0x1bad, 0xf038, "Street Fighter IV FightStick TE" },
slouken@12088
   125
    { 0x1bad, 0xf039, "Mad Catz MvC2 TE" },
slouken@12088
   126
    { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro" },
slouken@12088
   127
    { 0x1bad, 0xf03d, "Street Fighter IV Arcade Stick TE - Chun Li" },
slouken@12088
   128
    { 0x1bad, 0xf03e, "Mad Catz MLG FightStick TE" },
slouken@12088
   129
    { 0x1bad, 0xf03f, "Mad Catz FightStick SoulCaliber" },
slouken@12088
   130
    { 0x1bad, 0xf042, "Mad Catz FightStick TES+" },
slouken@12088
   131
    { 0x1bad, 0xf080, "Mad Catz FightStick TE2" },
slouken@12088
   132
    { 0x1bad, 0xf501, "HoriPad EX2 Turbo" },
slouken@12088
   133
    { 0x1bad, 0xf502, "Hori Real Arcade Pro.VX SA" },
slouken@12088
   134
    { 0x1bad, 0xf503, "Hori Fighting Stick VX" },
slouken@12088
   135
    { 0x1bad, 0xf504, "Hori Real Arcade Pro. EX" },
slouken@12088
   136
    { 0x1bad, 0xf505, "Hori Fighting Stick EX2B" },
slouken@12088
   137
    { 0x1bad, 0xf506, "Hori Real Arcade Pro.EX Premium VLX" },
slouken@12088
   138
    { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller" },
slouken@12088
   139
    { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller" },
slouken@12088
   140
    { 0x1bad, 0xf903, "Tron Xbox 360 controller" },
slouken@12088
   141
    { 0x1bad, 0xf904, "PDP Versus Fighting Pad" },
slouken@12088
   142
    { 0x1bad, 0xf906, "MortalKombat FightStick" },
slouken@12088
   143
    { 0x1bad, 0xfa01, "MadCatz GamePad" },
slouken@12088
   144
    { 0x1bad, 0xfd00, "Razer Onza TE" },
slouken@12088
   145
    { 0x1bad, 0xfd01, "Razer Onza" },
slouken@12088
   146
    { 0x24c6, 0x5000, "Razer Atrox Arcade Stick" },
slouken@12088
   147
    { 0x24c6, 0x5300, "PowerA MINI PROEX Controller" },
slouken@12088
   148
    { 0x24c6, 0x5303, "Xbox Airflo wired controller" },
slouken@12088
   149
    { 0x24c6, 0x530a, "Xbox 360 Pro EX Controller" },
slouken@12088
   150
    { 0x24c6, 0x531a, "PowerA Pro Ex" },
slouken@12088
   151
    { 0x24c6, 0x5397, "FUS1ON Tournament Controller" },
slouken@12088
   152
    { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo" },
slouken@12088
   153
    { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA" },
slouken@12088
   154
    { 0x24c6, 0x5502, "Hori Fighting Stick VX Alt" },
slouken@12088
   155
    { 0x24c6, 0x5503, "Hori Fighting Edge" },
slouken@12088
   156
    { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick" },
slouken@12088
   157
    { 0x24c6, 0x550d, "Hori GEM Xbox controller" },
slouken@12088
   158
    { 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360" },
slouken@12088
   159
    { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel" },
slouken@12088
   160
    { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller" },
slouken@12088
   161
    { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel" },
slouken@12088
   162
    { 0x24c6, 0x5d04, "Razer Sabertooth" },
slouken@12088
   163
    { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360" },
slouken@12088
   164
};
slouken@12088
   165
slouken@12088
   166
typedef struct {
slouken@12088
   167
    Uint8 last_state[USB_PACKET_LENGTH];
slouken@12088
   168
    Uint32 rumble_expiration;
slouken@12088
   169
} SDL_DriverXbox360_Context;
slouken@12088
   170
slouken@12088
   171
slouken@12088
   172
static SDL_bool
slouken@12088
   173
HIDAPI_DriverXbox360_IsSupportedDevice(Uint16 vendor_id, Uint16 product_id, int interface_number, Uint16 usage_page, Uint16 usage)
slouken@12088
   174
{
slouken@12088
   175
#ifdef __MACOSX__
slouken@12088
   176
    return SDL_IsJoystickXbox360(vendor_id, product_id) || SDL_IsJoystickXboxOne(vendor_id, product_id);
slouken@12088
   177
#else
slouken@12088
   178
    return SDL_IsJoystickXbox360(vendor_id, product_id);
slouken@12088
   179
#endif
slouken@12088
   180
}
slouken@12088
   181
slouken@12088
   182
static const char *
slouken@12088
   183
HIDAPI_DriverXbox360_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
slouken@12088
   184
{
slouken@12088
   185
    int i;
slouken@12088
   186
slouken@12088
   187
    for (i = 0; i < SDL_arraysize(xbox360_devicenames); ++i) {
slouken@12088
   188
        const SDL_DriverXbox360_DeviceName *entry = &xbox360_devicenames[i];
slouken@12088
   189
        if (vendor_id == entry->vendor_id && product_id == entry->product_id) {
slouken@12088
   190
            return entry->name;
slouken@12088
   191
        }
slouken@12088
   192
    }
slouken@12088
   193
    return NULL;
slouken@12088
   194
}
slouken@12088
   195
slouken@12088
   196
static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
slouken@12088
   197
{
slouken@12088
   198
    const Uint8 led_packet[] = { 0x01, 0x03, (2 + slot) };
slouken@12088
   199
slouken@12088
   200
    if (hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
slouken@12088
   201
		return SDL_FALSE;
slouken@12088
   202
	}
slouken@12088
   203
	return SDL_TRUE;
slouken@12088
   204
}
slouken@12088
   205
slouken@12088
   206
static SDL_bool
slouken@12088
   207
HIDAPI_DriverXbox360_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
slouken@12088
   208
{
slouken@12088
   209
    SDL_DriverXbox360_Context *ctx;
slouken@12088
   210
slouken@12088
   211
    ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
slouken@12088
   212
    if (!ctx) {
slouken@12088
   213
        SDL_OutOfMemory();
slouken@12088
   214
        return SDL_FALSE;
slouken@12088
   215
    }
slouken@12088
   216
    *context = ctx;
slouken@12088
   217
slouken@12088
   218
    /* Set the controller LED */
slouken@12088
   219
	SetSlotLED(dev, (joystick->instance_id % 4));
slouken@12088
   220
slouken@12088
   221
    /* Initialize the joystick capabilities */
slouken@12088
   222
    joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
slouken@12088
   223
    joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
slouken@12088
   224
    joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
slouken@12088
   225
slouken@12088
   226
    return SDL_TRUE;
slouken@12088
   227
}
slouken@12088
   228
slouken@12088
   229
static int
slouken@12088
   230
HIDAPI_DriverXbox360_Rumble(SDL_Joystick *joystick, hid_device *dev, void *context, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
slouken@12088
   231
{
slouken@12088
   232
    SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
slouken@12088
   233
#ifdef __MACOSX__
slouken@12088
   234
    /* On Mac OS X the 360Controller driver uses this short report,
slouken@12088
   235
       and we need to prefix it with a magic token so hidapi passes it through untouched
slouken@12088
   236
     */
slouken@12088
   237
    Uint8 rumble_packet[] = { 'M', 'A', 'G', 'I', 'C', '0', 0x00, 0x04, 0x00, 0x00 };
slouken@12088
   238
slouken@12088
   239
    rumble_packet[6+2] = (low_frequency_rumble >> 8);
slouken@12088
   240
    rumble_packet[6+3] = (high_frequency_rumble >> 8);
slouken@12088
   241
#else
slouken@12088
   242
    Uint8 rumble_packet[] = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
slouken@12088
   243
slouken@12088
   244
    rumble_packet[3] = (low_frequency_rumble >> 8);
slouken@12088
   245
    rumble_packet[4] = (high_frequency_rumble >> 8);
slouken@12088
   246
#endif
slouken@12088
   247
slouken@12088
   248
    if (hid_write(dev, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
slouken@12088
   249
        return SDL_SetError("Couldn't send rumble packet");
slouken@12088
   250
    }
slouken@12088
   251
slouken@12088
   252
    if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
slouken@12088
   253
        ctx->rumble_expiration = SDL_GetTicks() + duration_ms;
slouken@12088
   254
    } else {
slouken@12088
   255
        ctx->rumble_expiration = 0;
slouken@12088
   256
    }
slouken@12088
   257
    return 0;
slouken@12088
   258
}
slouken@12088
   259
slouken@12088
   260
static void
slouken@12088
   261
HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size)
slouken@12088
   262
{
slouken@12088
   263
    Sint16 axis;
slouken@12088
   264
#ifdef __MACOSX__
slouken@12088
   265
	const SDL_bool invert_y_axes = SDL_FALSE;
slouken@12088
   266
#else
slouken@12088
   267
	const SDL_bool invert_y_axes = SDL_TRUE;
slouken@12088
   268
#endif
slouken@12088
   269
slouken@12088
   270
    if (ctx->last_state[2] != data[2]) {
slouken@12088
   271
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   272
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   273
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   274
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   275
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   276
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   277
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[2] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   278
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   279
    }
slouken@12088
   280
slouken@12088
   281
    if (ctx->last_state[3] != data[3]) {
slouken@12088
   282
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[3] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   283
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[3] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   284
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   285
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   286
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   287
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   288
        SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
slouken@12088
   289
    }
slouken@12088
   290
slouken@12088
   291
    axis = ((int)data[4] * 257) - 32768;
slouken@12088
   292
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
slouken@12088
   293
    axis = ((int)data[5] * 257) - 32768;
slouken@12088
   294
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
slouken@12088
   295
    axis = *(Sint16*)(&data[6]);
slouken@12088
   296
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
slouken@12088
   297
    axis = *(Sint16*)(&data[8]);
slouken@12088
   298
	if (invert_y_axes) {
slouken@12088
   299
		axis = ~axis;
slouken@12088
   300
	}
slouken@12088
   301
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
slouken@12088
   302
    axis = *(Sint16*)(&data[10]);
slouken@12088
   303
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
slouken@12088
   304
    axis = *(Sint16*)(&data[12]);
slouken@12088
   305
	if (invert_y_axes) {
slouken@12088
   306
		axis = ~axis;
slouken@12088
   307
	}
slouken@12088
   308
    SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
slouken@12088
   309
slouken@12088
   310
    SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
slouken@12088
   311
}
slouken@12088
   312
slouken@12088
   313
static void
slouken@12088
   314
HIDAPI_DriverXbox360_Update(SDL_Joystick *joystick, hid_device *dev, void *context)
slouken@12088
   315
{
slouken@12088
   316
    SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)context;
slouken@12088
   317
    Uint8 data[USB_PACKET_LENGTH];
slouken@12088
   318
    int size;
slouken@12088
   319
slouken@12088
   320
    while ((size = hid_read_timeout(dev, data, sizeof(data), 0)) > 0) {
slouken@12088
   321
        switch (data[0]) {
slouken@12088
   322
        case 0x00:
slouken@12088
   323
            HIDAPI_DriverXbox360_HandleStatePacket(joystick, dev, ctx, data, size);
slouken@12088
   324
            break;
slouken@12088
   325
        default:
slouken@12088
   326
#ifdef DEBUG_JOYSTICK
slouken@12088
   327
            SDL_Log("Unknown Xbox 360 packet: 0x%.2x\n", data[0]);
slouken@12088
   328
#endif
slouken@12088
   329
            break;
slouken@12088
   330
        }
slouken@12088
   331
    }
slouken@12088
   332
slouken@12088
   333
    if (ctx->rumble_expiration) {
slouken@12088
   334
        Uint32 now = SDL_GetTicks();
slouken@12088
   335
        if (SDL_TICKS_PASSED(now, ctx->rumble_expiration)) {
slouken@12088
   336
            HIDAPI_DriverXbox360_Rumble(joystick, dev, context, 0, 0, 0);
slouken@12088
   337
        }
slouken@12088
   338
    }
slouken@12088
   339
}
slouken@12088
   340
slouken@12088
   341
static void
slouken@12088
   342
HIDAPI_DriverXbox360_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
slouken@12088
   343
{
slouken@12088
   344
    SDL_free(context);
slouken@12088
   345
}
slouken@12088
   346
slouken@12088
   347
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
slouken@12088
   348
{
slouken@12088
   349
    SDL_HINT_JOYSTICK_HIDAPI_XBOX360,
slouken@12088
   350
    SDL_TRUE,
slouken@12088
   351
    HIDAPI_DriverXbox360_IsSupportedDevice,
slouken@12088
   352
    HIDAPI_DriverXbox360_GetDeviceName,
slouken@12088
   353
    HIDAPI_DriverXbox360_Init,
slouken@12088
   354
    HIDAPI_DriverXbox360_Rumble,
slouken@12088
   355
    HIDAPI_DriverXbox360_Update,
slouken@12088
   356
    HIDAPI_DriverXbox360_Quit
slouken@12088
   357
};
slouken@12088
   358
slouken@12088
   359
#endif /* SDL_JOYSTICK_HIDAPI_XBOX360 */
slouken@12088
   360
slouken@12088
   361
#endif /* SDL_JOYSTICK_HIDAPI */
slouken@12088
   362
slouken@12088
   363
/* vi: set ts=4 sw=4 expandtab: */