mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-25 09:17:12 +01:00
Updated the HIDAPI Xbox One driver with support for Bluetooth Xbox One controllers
This commit is contained in:
parent
997f3e9e82
commit
756d2073fe
@ -285,6 +285,17 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
|
|||||||
/* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */
|
/* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
#if defined(__MACOSX__)
|
||||||
|
/* Wired Xbox One controllers are handled by this driver, interfacing with
|
||||||
|
the 360Controller driver available from:
|
||||||
|
https://github.com/360Controller/360Controller/releases
|
||||||
|
|
||||||
|
Bluetooth Xbox One controllers are handled by the SDL Xbox One driver
|
||||||
|
*/
|
||||||
|
if (IsBluetoothXboxOneController(vendor_id, product_id)) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE);
|
return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE);
|
||||||
#else
|
#else
|
||||||
return (type == SDL_CONTROLLER_TYPE_XBOX360);
|
return (type == SDL_CONTROLLER_TYPE_XBOX360);
|
||||||
@ -680,106 +691,6 @@ HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
|
|||||||
}
|
}
|
||||||
#endif /* __WIN32__ */
|
#endif /* __WIN32__ */
|
||||||
|
|
||||||
#ifdef __MACOSX__
|
|
||||||
static void
|
|
||||||
HIDAPI_DriverXboxOneS_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size)
|
|
||||||
{
|
|
||||||
Sint16 axis;
|
|
||||||
|
|
||||||
if (ctx->last_state[14] != data[14]) {
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->last_state[15] != data[15]) {
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->last_state[16] != data[16]) {
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->last_state[13] != data[13]) {
|
|
||||||
SDL_bool dpad_up = SDL_FALSE;
|
|
||||||
SDL_bool dpad_down = SDL_FALSE;
|
|
||||||
SDL_bool dpad_left = SDL_FALSE;
|
|
||||||
SDL_bool dpad_right = SDL_FALSE;
|
|
||||||
|
|
||||||
switch (data[13]) {
|
|
||||||
case 1:
|
|
||||||
dpad_up = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dpad_up = SDL_TRUE;
|
|
||||||
dpad_right = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
dpad_right = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dpad_right = SDL_TRUE;
|
|
||||||
dpad_down = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
dpad_down = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
dpad_left = SDL_TRUE;
|
|
||||||
dpad_down = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
dpad_left = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
dpad_up = SDL_TRUE;
|
|
||||||
dpad_left = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
|
|
||||||
}
|
|
||||||
|
|
||||||
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
|
||||||
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
|
|
||||||
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
|
|
||||||
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
|
||||||
|
|
||||||
axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
|
|
||||||
if (axis == 32704) {
|
|
||||||
axis = 32767;
|
|
||||||
}
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
|
||||||
|
|
||||||
axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
|
|
||||||
if (axis == 32704) {
|
|
||||||
axis = 32767;
|
|
||||||
}
|
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
|
||||||
|
|
||||||
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
HIDAPI_DriverXboxOneS_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size)
|
|
||||||
{
|
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
|
||||||
}
|
|
||||||
#endif /* __MACOSX__ */
|
|
||||||
|
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
|
HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||||
{
|
{
|
||||||
@ -796,31 +707,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||||
#ifdef __WIN32__
|
|
||||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
HIDAPI_DriverXbox360_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
||||||
#else
|
|
||||||
switch (data[0]) {
|
|
||||||
case 0x00:
|
|
||||||
HIDAPI_DriverXbox360_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
|
||||||
break;
|
|
||||||
#ifdef __MACOSX__
|
|
||||||
case 0x01:
|
|
||||||
HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, device->dev, ctx, data, size);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
#ifdef DEBUG_JOYSTICK
|
|
||||||
SDL_Log("Unknown Xbox 360 packet, size = %d\n", size);
|
|
||||||
SDL_Log("%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
|
|
||||||
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
|
|
||||||
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16]);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* __WIN32__ */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
|
@ -108,14 +108,16 @@ static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Uint16 vendor_id;
|
Uint16 vendor_id;
|
||||||
Uint16 product_id;
|
Uint16 product_id;
|
||||||
Uint32 start_time;
|
SDL_bool bluetooth;
|
||||||
SDL_bool initialized;
|
SDL_bool initialized;
|
||||||
|
Uint32 start_time;
|
||||||
Uint8 sequence;
|
Uint8 sequence;
|
||||||
Uint8 last_state[USB_PACKET_LENGTH];
|
Uint8 last_state[USB_PACKET_LENGTH];
|
||||||
SDL_bool has_paddles;
|
SDL_bool has_paddles;
|
||||||
} SDL_DriverXboxOne_Context;
|
} SDL_DriverXboxOne_Context;
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUG_XBOX_PROTOCOL
|
||||||
#ifdef DEBUG_XBOX_PROTOCOL
|
#ifdef DEBUG_XBOX_PROTOCOL
|
||||||
static void
|
static void
|
||||||
DumpPacket(const char *prefix, Uint8 *data, int size)
|
DumpPacket(const char *prefix, Uint8 *data, int size)
|
||||||
@ -187,64 +189,60 @@ SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
|
|||||||
{
|
{
|
||||||
Uint16 vendor_id = ctx->vendor_id;
|
Uint16 vendor_id = ctx->vendor_id;
|
||||||
Uint16 product_id = ctx->product_id;
|
Uint16 product_id = ctx->product_id;
|
||||||
|
int i;
|
||||||
|
Uint8 init_packet[USB_PACKET_LENGTH];
|
||||||
|
|
||||||
if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
|
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
|
||||||
int i;
|
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
|
||||||
Uint8 init_packet[USB_PACKET_LENGTH];
|
|
||||||
|
|
||||||
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
|
if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
|
||||||
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
|
if (packet->product_id && (product_id != packet->product_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->product_id && (product_id != packet->product_id)) {
|
if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
|
if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
|
SDL_memcpy(init_packet, packet->data, packet->size);
|
||||||
continue;
|
if (init_packet[0] != 0x01) {
|
||||||
}
|
init_packet[2] = ctx->sequence++;
|
||||||
|
}
|
||||||
|
if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
|
||||||
|
SDL_SetError("Couldn't write Xbox One initialization packet");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_memcpy(init_packet, packet->data, packet->size);
|
if (packet->response[0]) {
|
||||||
if (init_packet[0] != 0x01) {
|
const Uint32 RESPONSE_TIMEOUT_MS = 50;
|
||||||
init_packet[2] = ctx->sequence++;
|
Uint32 start = SDL_GetTicks();
|
||||||
}
|
SDL_bool got_response = SDL_FALSE;
|
||||||
if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
|
|
||||||
SDL_SetError("Couldn't write Xbox One initialization packet");
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet->response[0]) {
|
while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
|
||||||
const Uint32 RESPONSE_TIMEOUT_MS = 50;
|
Uint8 data[USB_PACKET_LENGTH];
|
||||||
Uint32 start = SDL_GetTicks();
|
int size;
|
||||||
SDL_bool got_response = SDL_FALSE;
|
|
||||||
|
|
||||||
while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
|
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
||||||
Uint8 data[USB_PACKET_LENGTH];
|
|
||||||
int size;
|
|
||||||
|
|
||||||
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
|
|
||||||
#ifdef DEBUG_XBOX_PROTOCOL
|
#ifdef DEBUG_XBOX_PROTOCOL
|
||||||
DumpPacket("Xbox One INIT packet: size = %d", data, size);
|
DumpPacket("Xbox One INIT packet: size = %d", data, size);
|
||||||
#endif
|
#endif
|
||||||
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
|
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
|
||||||
got_response = SDL_TRUE;
|
got_response = SDL_TRUE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_XBOX_PROTOCOL
|
|
||||||
SDL_Log("Init sequence %d got response: %s\n", i, got_response ? "TRUE" : "FALSE");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_XBOX_PROTOCOL
|
||||||
|
SDL_Log("Init sequence %d got response: %s\n", i, got_response ? "TRUE" : "FALSE");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,14 +250,16 @@ static SDL_bool
|
|||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
#ifdef __LINUX__
|
#ifdef __LINUX__
|
||||||
if (IsBluetoothXboxOneController(vendor_id, product_id)) {
|
|
||||||
/* We can't do rumble on this device, hid_write() fails, so don't try to open it here */
|
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
|
if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
|
||||||
/* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
|
/* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __MACOSX__
|
||||||
|
/* Wired Xbox One controllers are handled by the 360Controller driver */
|
||||||
|
if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return (type == SDL_CONTROLLER_TYPE_XBOXONE);
|
return (type == SDL_CONTROLLER_TYPE_XBOXONE);
|
||||||
}
|
}
|
||||||
@ -308,6 +308,8 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
|
|||||||
|
|
||||||
ctx->vendor_id = device->vendor_id;
|
ctx->vendor_id = device->vendor_id;
|
||||||
ctx->product_id = device->product_id;
|
ctx->product_id = device->product_id;
|
||||||
|
ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
|
||||||
|
ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
|
||||||
ctx->start_time = SDL_GetTicks();
|
ctx->start_time = SDL_GetTicks();
|
||||||
ctx->sequence = 1;
|
ctx->sequence = 1;
|
||||||
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
|
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
|
||||||
@ -323,14 +325,27 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
|
|||||||
static int
|
static int
|
||||||
HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||||
{
|
{
|
||||||
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
|
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
|
||||||
|
|
||||||
/* Magnitude is 1..100 so scale the 16-bit input here */
|
if (ctx->bluetooth) {
|
||||||
rumble_packet[8] = low_frequency_rumble / 655;
|
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
|
||||||
rumble_packet[9] = high_frequency_rumble / 655;
|
|
||||||
|
|
||||||
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
rumble_packet[4] = (low_frequency_rumble >> 8);
|
||||||
return SDL_SetError("Couldn't send rumble packet");
|
rumble_packet[5] = (high_frequency_rumble >> 8);
|
||||||
|
|
||||||
|
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||||
|
return SDL_SetError("Couldn't send rumble packet");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
|
||||||
|
|
||||||
|
/* Magnitude is 1..100 so scale the 16-bit input here */
|
||||||
|
rumble_packet[8] = low_frequency_rumble / 655;
|
||||||
|
rumble_packet[9] = high_frequency_rumble / 655;
|
||||||
|
|
||||||
|
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||||
|
return SDL_SetError("Couldn't send rumble packet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -456,6 +471,104 @@ HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, S
|
|||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
|
||||||
|
{
|
||||||
|
Sint16 axis;
|
||||||
|
|
||||||
|
if (ctx->last_state[14] != data[14]) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->last_state[15] != data[15]) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->last_state[16] != data[16]) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->last_state[13] != data[13]) {
|
||||||
|
SDL_bool dpad_up = SDL_FALSE;
|
||||||
|
SDL_bool dpad_down = SDL_FALSE;
|
||||||
|
SDL_bool dpad_left = SDL_FALSE;
|
||||||
|
SDL_bool dpad_right = SDL_FALSE;
|
||||||
|
|
||||||
|
switch (data[13]) {
|
||||||
|
case 1:
|
||||||
|
dpad_up = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dpad_up = SDL_TRUE;
|
||||||
|
dpad_right = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
dpad_right = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
dpad_right = SDL_TRUE;
|
||||||
|
dpad_down = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
dpad_down = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
dpad_left = SDL_TRUE;
|
||||||
|
dpad_down = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
dpad_left = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
dpad_up = SDL_TRUE;
|
||||||
|
dpad_left = SDL_TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||||
|
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
|
||||||
|
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
|
||||||
|
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
||||||
|
|
||||||
|
axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
|
||||||
|
if (axis == 32704) {
|
||||||
|
axis = 32767;
|
||||||
|
}
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
||||||
|
|
||||||
|
axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
|
||||||
|
if (axis == 32704) {
|
||||||
|
axis = 32767;
|
||||||
|
}
|
||||||
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
||||||
|
|
||||||
|
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
|
||||||
|
{
|
||||||
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||||
{
|
{
|
||||||
@ -486,34 +599,50 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||||||
#ifdef DEBUG_XBOX_PROTOCOL
|
#ifdef DEBUG_XBOX_PROTOCOL
|
||||||
DumpPacket("Xbox One packet: size = %d", data, size);
|
DumpPacket("Xbox One packet: size = %d", data, size);
|
||||||
#endif
|
#endif
|
||||||
switch (data[0]) {
|
if (ctx->bluetooth) {
|
||||||
case 0x02:
|
switch (data[0]) {
|
||||||
/* Controller is connected and waiting for initialization */
|
case 0x01:
|
||||||
if (!ctx->initialized) {
|
HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
||||||
#ifdef DEBUG_XBOX_PROTOCOL
|
break;
|
||||||
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
|
case 0x02:
|
||||||
#endif
|
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
|
||||||
if (!SendControllerInit(device, ctx)) {
|
break;
|
||||||
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
default:
|
||||||
return SDL_FALSE;
|
|
||||||
}
|
|
||||||
ctx->initialized = SDL_TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
/* Controller heartbeat */
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
|
||||||
break;
|
|
||||||
case 0x07:
|
|
||||||
HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#ifdef DEBUG_JOYSTICK
|
#ifdef DEBUG_JOYSTICK
|
||||||
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
|
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (data[0]) {
|
||||||
|
case 0x02:
|
||||||
|
/* Controller is connected and waiting for initialization */
|
||||||
|
if (!ctx->initialized) {
|
||||||
|
#ifdef DEBUG_XBOX_PROTOCOL
|
||||||
|
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
|
||||||
|
#endif
|
||||||
|
if (!SendControllerInit(device, ctx)) {
|
||||||
|
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
ctx->initialized = SDL_TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
/* Controller heartbeat */
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
#ifdef DEBUG_JOYSTICK
|
||||||
|
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user