From faeac6e86c207de9d2340e93e08503cf672c8541 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 6 Nov 2020 16:42:46 -0800 Subject: [PATCH] Added additional game controller button support on iOS/tvOS --- src/joystick/SDL_gamecontrollerdb.h | 6 +- src/joystick/iphoneos/SDL_sysjoystick.m | 94 ++++++++++++++++++++--- src/joystick/iphoneos/SDL_sysjoystick_c.h | 4 +- src/joystick/usb_ids.h | 1 + 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index 359d4cad2..204c2bd55 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -827,11 +827,13 @@ static const char *s_ControllerMappings [] = "05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,", - "050000004c050000cc090000df070000,DUALSHOCK 4 Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", - "050000004c050000cc090000ff070000,DUALSHOCK 4 Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", + "050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", + "050000004c050000cc090000ff876d01,PS4 Controller,a:b0,aux1:b11,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,", "05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", "05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,", + "050000005e040000050b0000ff876d01,Xbox Elite Wireless Controller,a:b0,aux1:b11,aux2:b12,aux3:b13,aux4:b13,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", "050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", #endif diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index 915016308..794d31fc0 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -33,6 +33,7 @@ #include "SDL_stdinc.h" #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" +#include "../usb_ids.h" #if !SDL_EVENTS_DISABLED @@ -77,6 +78,7 @@ static id disconnectObserver = nil; #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 140000) || (__MAC_OS_VERSION_MAX_ALLOWED > 1500000) #define ENABLE_MFI_BATTERY #define ENABLE_MFI_RUMBLE +#define ENABLE_PHYSICAL_INPUT_PROFILE #endif #ifdef ENABLE_MFI_RUMBLE @@ -116,9 +118,6 @@ static void IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller) { #ifdef SDL_JOYSTICK_MFI - const Uint16 VENDOR_APPLE = 0x05AC; - const Uint16 VENDOR_MICROSOFT = 0x045e; - const Uint16 VENDOR_SONY = 0x054C; Uint16 *guid16 = (Uint16 *)device->guid.data; Uint16 vendor = 0; Uint16 product = 0; @@ -188,16 +187,60 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle if (!has_direct_menu) { device->uses_pause_handler = SDL_TRUE; } + +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + if ([controller respondsToSelector:@selector(physicalInputProfile)]) { + if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) { + device->has_dualshock_touchpad = SDL_TRUE; + device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_AUX1); + ++nbuttons; + } + if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) { + device->has_xbox_paddles = SDL_TRUE; + device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_AUX1); + ++nbuttons; + } + if (controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo] != nil) { + device->has_xbox_paddles = SDL_TRUE; + device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_AUX2); + ++nbuttons; + } + if (controller.physicalInputProfile.buttons[GCInputXboxPaddleThree] != nil) { + device->has_xbox_paddles = SDL_TRUE; + device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_AUX3); + ++nbuttons; + } + if (controller.physicalInputProfile.buttons[GCInputXboxPaddleFour] != nil) { + device->has_xbox_paddles = SDL_TRUE; + device->button_mask |= (1 << SDL_CONTROLLER_BUTTON_AUX4); + ++nbuttons; + } + } +#endif #pragma clang diagnostic pop if (is_xbox) { - vendor = VENDOR_MICROSOFT; - product = 0x02E0; /* Assume Xbox One S BLE Controller unless/until GCController flows VID/PID */ + vendor = USB_VENDOR_MICROSOFT; + if (device->has_xbox_paddles) { + /* Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID */ + product = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH; + subtype = 1; + } else { + /* Assume Xbox One S BLE Controller unless/until GCController flows VID/PID */ + product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; + subtype = 0; + } } else if (is_ps4) { - vendor = VENDOR_SONY; - product = 0x09CC; /* Assume DS4 Slim unless/until GCController flows VID/PID */ + /* Assume DS4 Slim unless/until GCController flows VID/PID */ + vendor = USB_VENDOR_SONY; + product = USB_PRODUCT_SONY_DS4_SLIM; + if ( device->has_dualshock_touchpad ) { + subtype = 1; + } else { + subtype = 0; + } } else { - vendor = VENDOR_APPLE; + vendor = USB_VENDOR_APPLE; product = 1; subtype = 1; } @@ -220,7 +263,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle nbuttons += 7; device->uses_pause_handler = SDL_TRUE; - vendor = VENDOR_APPLE; + vendor = USB_VENDOR_APPLE; product = 2; subtype = 2; device->naxes = 0; /* no traditional analog inputs */ @@ -239,7 +282,7 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle ++nbuttons; device->uses_pause_handler = SDL_TRUE; - vendor = VENDOR_APPLE; + vendor = USB_VENDOR_APPLE; product = 3; subtype = 3; device->naxes = 2; /* treat the touch surface as two axes */ @@ -700,6 +743,37 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) buttons[button_count++] = gamepad.buttonMenu.isPressed; } } + +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE + if (joystick->hwdata->has_dualshock_touchpad) { + if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_AUX1)) { + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed; + } + } + + if (joystick->hwdata->has_xbox_paddles) { + if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_AUX1)) { + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed; + } + if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_AUX2)) { + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed; + } + if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_AUX3)) { + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed; + } + if (joystick->hwdata->button_mask & (1 << SDL_CONTROLLER_BUTTON_AUX4)) { + buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed; + } + + /* + SDL_Log("Paddles: [%d,%d,%d,%d]", + controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed, + controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed, + controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed, + controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed); + */ + } +#endif #pragma clang diagnostic pop hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad); diff --git a/src/joystick/iphoneos/SDL_sysjoystick_c.h b/src/joystick/iphoneos/SDL_sysjoystick_c.h index 8dcdeccec..c004fda1b 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick_c.h +++ b/src/joystick/iphoneos/SDL_sysjoystick_c.h @@ -47,7 +47,9 @@ typedef struct joystick_hwdata int naxes; int nbuttons; int nhats; - Uint16 button_mask; + Uint32 button_mask; + SDL_bool has_dualshock_touchpad; + SDL_bool has_xbox_paddles; struct joystick_hwdata *next; } joystick_hwdata; diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 976273078..d1981b407 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -24,6 +24,7 @@ /* Definitions of useful USB VID/PID values */ +#define USB_VENDOR_APPLE 0x05ac #define USB_VENDOR_HYPERKIN 0x2e24 #define USB_VENDOR_MICROSOFT 0x045e #define USB_VENDOR_NINTENDO 0x057e