Added support for the Xbox Series X controller to the HIDAPI driver

This commit is contained in:
Sam Lantinga 2020-11-10 12:26:30 -08:00
parent 7b5a0a9f97
commit e12457d8bf
7 changed files with 49 additions and 8 deletions

View File

@ -982,9 +982,9 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
libusb_get_config_descriptor(usb_dev, 0, &conf_desc);
if (!conf_desc)
continue;
for (j = 0; j < conf_desc->bNumInterfaces; j++) {
for (j = 0; j < conf_desc->bNumInterfaces && !good_open; j++) {
const struct libusb_interface *intf = &conf_desc->interface[j];
for (k = 0; k < intf->num_altsetting; k++) {
for (k = 0; k < intf->num_altsetting && !good_open; k++) {
const struct libusb_interface_descriptor *intf_desc;
intf_desc = &intf->altsetting[k];
if (should_enumerate_interface(desc.idVendor, intf_desc)) {

View File

@ -568,7 +568,10 @@ static ControllerMapping_t *SDL_CreateMappingForHIDAPIController(SDL_JoystickGUI
/* All other controllers have the standard set of 19 buttons and 6 axes */
SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", sizeof(mapping_string));
if (SDL_IsJoystickXboxOneElite(vendor, product)) {
if (SDL_IsJoystickXboxOneSeriesX(vendor, product)) {
/* XBox One Series X Controllers have a share button under the guide button */
SDL_strlcat(mapping_string, "misc1:b15,", sizeof(mapping_string));
} else if (SDL_IsJoystickXboxOneElite(vendor, product)) {
/* XBox One Elite Controllers have 4 back paddle buttons */
SDL_strlcat(mapping_string, "paddle1:b15,paddle2:b17,paddle3:b16,paddle4:b18,", sizeof(mapping_string));
} else if (SDL_IsJoystickSteamController(vendor, product)) {

View File

@ -1793,6 +1793,18 @@ SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
return SDL_FALSE;
}
SDL_bool
SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_SERIES_X ||
product_id == USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
SDL_bool
SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id)
{

View File

@ -64,6 +64,9 @@ extern SDL_GameControllerType SDL_GetJoystickGameControllerType(const char *name
/* Function to return whether a joystick is an Xbox One Elite controller */
extern SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is an Xbox One Series X controller */
extern SDL_bool SDL_IsJoystickXboxOneSeriesX(Uint16 vendor_id, Uint16 product_id);
/* Function to return whether a joystick is a PS4 controller */
extern SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id);

View File

@ -323,6 +323,8 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with the RAWINPUT driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One

View File

@ -125,6 +125,7 @@ typedef struct {
Uint8 sequence;
Uint8 last_state[USB_PACKET_LENGTH];
SDL_bool has_paddles;
SDL_bool has_share_button;
} SDL_DriverXboxOne_Context;
@ -148,6 +149,12 @@ ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
return SDL_IsJoystickXboxOneElite(vendor_id, product_id);
}
static SDL_bool
ControllerHasShareButton(Uint16 vendor_id, Uint16 product_id)
{
return SDL_IsJoystickXboxOneSeriesX(vendor_id, product_id);
}
/* Return true if this controller sends the 0x02 "waiting for init" packet */
static SDL_bool
ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
@ -299,9 +306,16 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->input_ready = SDL_TRUE;
ctx->sequence = 1;
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
ctx->has_share_button = ControllerHasShareButton(ctx->vendor_id, ctx->product_id);
/* Initialize the joystick capabilities */
joystick->nbuttons = ctx->has_paddles ? 19 : 15;
joystick->nbuttons = 15;
if (ctx->has_share_button) {
joystick->nbuttons += 1;
}
if (ctx->has_paddles) {
joystick->nbuttons += 4;
}
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
@ -380,6 +394,10 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[5] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->has_share_button && ctx->last_state[18] != data[18]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[18] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
/* Xbox One S report is 18 bytes
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
Paddle bits:
@ -434,10 +452,11 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
}
if (ctx->last_state[paddle_index] != data[paddle_index]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 0, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 1, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 2, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1 + 3, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
int nButton = SDL_CONTROLLER_BUTTON_MISC1 + ctx->has_share_button;
SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button1_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button2_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button3_bit) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, nButton++, (data[paddle_index] & button4_bit) ? SDL_PRESSED : SDL_RELEASED);
}
}

View File

@ -50,6 +50,8 @@
#define USB_PRODUCT_XBOX_ONE_S 0x02ea
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH 0x02e0
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH 0x02fd
#define USB_PRODUCT_XBOX_ONE_SERIES_X 0x0b12
#define USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH 0x0b13
#endif /* usb_ids_h_ */