|
@@ -40,6 +40,9 @@
|
|
|
/* The amount of time to wait after hotplug to send controller init sequence */
|
|
|
#define CONTROLLER_INIT_DELAY_MS 1500 /* 475 for Xbox One S, 1275 for the PDP Battlefield 1 */
|
|
|
|
|
|
+/* The amount of time to wait after init for valid input */
|
|
|
+#define CONTROLLER_INPUT_DELAY_MS 50 /* 42 for Razer Wolverine Ultimate */
|
|
|
+
|
|
|
/* Connect controller */
|
|
|
static const Uint8 xboxone_init0[] = {
|
|
|
0x04, 0x20, 0x00, 0x00
|
|
@@ -116,7 +119,9 @@ typedef struct {
|
|
|
SDL_bool bluetooth;
|
|
|
SDL_XboxOneWirelessProtocol wireless_protocol;
|
|
|
SDL_bool initialized;
|
|
|
+ SDL_bool input_ready;
|
|
|
Uint32 start_time;
|
|
|
+ Uint32 initialized_time;
|
|
|
Uint8 sequence;
|
|
|
Uint8 last_state[USB_PACKET_LENGTH];
|
|
|
SDL_bool has_paddles;
|
|
@@ -319,6 +324,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
|
|
|
ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
|
|
|
ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
|
|
|
ctx->start_time = SDL_GetTicks();
|
|
|
+ ctx->input_ready = SDL_TRUE;
|
|
|
ctx->sequence = 1;
|
|
|
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
|
|
|
|
|
@@ -377,8 +383,14 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
|
|
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, (data[5] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, (data[5] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, (data[5] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
- SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
+ if (ctx->vendor_id == USB_VENDOR_RAZER && ctx->product_id == USB_PRODUCT_RAZER_ATROX) {
|
|
|
+ /* The Razer Atrox has the right and left shoulder bits reversed */
|
|
|
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
+ } else {
|
|
|
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
+ SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
+ }
|
|
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[5] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[5] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
|
|
|
}
|
|
@@ -448,12 +460,20 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
|
|
|
if (axis == 32704) {
|
|
|
axis = 32767;
|
|
|
}
|
|
|
+ if (axis == -32768 && size == 30 && (data[22] & 0x80) != 0) {
|
|
|
+ axis = 32767;
|
|
|
+ }
|
|
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
|
|
|
+
|
|
|
axis = ((int)*(Sint16*)(&data[8]) * 64) - 32768;
|
|
|
+ if (axis == -32768 && size == 30 && (data[22] & 0x40) != 0) {
|
|
|
+ axis = 32767;
|
|
|
+ }
|
|
|
if (axis == 32704) {
|
|
|
axis = 32767;
|
|
|
}
|
|
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
|
|
+
|
|
|
axis = *(Sint16*)(&data[10]);
|
|
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
|
|
axis = *(Sint16*)(&data[12]);
|
|
@@ -700,6 +720,8 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|
|
return SDL_FALSE;
|
|
|
}
|
|
|
ctx->initialized = SDL_TRUE;
|
|
|
+ ctx->initialized_time = SDL_GetTicks();
|
|
|
+ ctx->input_ready = SDL_FALSE;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -743,12 +765,23 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
|
|
|
return SDL_FALSE;
|
|
|
}
|
|
|
ctx->initialized = SDL_TRUE;
|
|
|
+ ctx->initialized_time = SDL_GetTicks();
|
|
|
+ ctx->input_ready = SDL_FALSE;
|
|
|
}
|
|
|
break;
|
|
|
case 0x03:
|
|
|
/* Controller heartbeat */
|
|
|
break;
|
|
|
case 0x20:
|
|
|
+ if (!ctx->input_ready) {
|
|
|
+ if (!SDL_TICKS_PASSED(SDL_GetTicks(), ctx->initialized_time + CONTROLLER_INPUT_DELAY_MS)) {
|
|
|
+#ifdef DEBUG_XBOX_PROTOCOL
|
|
|
+ SDL_Log("Spurious input at %ums\n", SDL_GetTicks() - ctx->initialized_time);
|
|
|
+#endif
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ctx->input_ready = SDL_TRUE;
|
|
|
+ }
|
|
|
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
|
|
|
break;
|
|
|
case 0x07:
|