diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 15ceb96fa1..be21cbbc97 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -18,9 +18,6 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -/* This driver supports both simplified reports and the extended input reports enabled by Steam. - Code and logic contributed by Valve Corporation under the SDL zlib license. -*/ #include "../../SDL_internal.h" #ifdef SDL_JOYSTICK_HIDAPI @@ -109,6 +106,9 @@ HIDAPI_DriverPS3_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) { return SDL_TRUE; } + if (vendor_id == USB_VENDOR_SHANWAN && product_id == USB_PRODUCT_SHANWAN_DS3) { + return SDL_TRUE; + } return SDL_FALSE; } @@ -323,6 +323,83 @@ HIDAPI_DriverPS3_ScaleAccel(Sint16 value) return (float)(value - 511) / 113.0f; } +static void +HIDAPI_DriverPS3_HandleMiniStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) +{ + Sint16 axis; + + if (ctx->last_state[4] != data[4]) { + 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[4] & 0x0f) { + case 0: + dpad_up = SDL_TRUE; + break; + case 1: + dpad_up = SDL_TRUE; + dpad_right = SDL_TRUE; + break; + case 2: + dpad_right = SDL_TRUE; + break; + case 3: + dpad_right = SDL_TRUE; + dpad_down = SDL_TRUE; + break; + case 4: + dpad_down = SDL_TRUE; + break; + case 5: + dpad_left = SDL_TRUE; + dpad_down = SDL_TRUE; + break; + case 6: + dpad_left = SDL_TRUE; + break; + case 7: + 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); + + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[4] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[4] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[4] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[4] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + } + + if (ctx->last_state[5] != data[5]) { + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[5] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[5] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, (data[5] & 0x04) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN); + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, (data[5] & 0x08) ? SDL_JOYSTICK_AXIS_MAX : SDL_JOYSTICK_AXIS_MIN); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[5] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (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); + } + + axis = ((int)data[2] * 257) - 32768; + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis); + axis = ((int)data[3] * 257) - 32768; + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis); + axis = ((int)data[0] * 257) - 32768; + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis); + axis = ((int)data[1] * 257) - 32768; + SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis); + + SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); +} + static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) { @@ -431,6 +508,12 @@ HIDAPI_DriverPS3_UpdateDevice(SDL_HIDAPI_Device *device) HIDAPI_DumpPacket("PS3 packet: size = %d", data, size); #endif + if (size == 7) { + /* Seen on a ShanWan PS2 -> PS3 USB converter */ + HIDAPI_DriverPS3_HandleMiniStatePacket(joystick, ctx, data, size); + continue; + } + switch (data[0]) { case k_EPS3ReportIdState: if (data[1] == 0xFF) { diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 94fe777cd4..b650c2e1f5 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -37,6 +37,7 @@ #define USB_VENDOR_POWERA 0x24c6 #define USB_VENDOR_POWERA_ALT 0x20d6 #define USB_VENDOR_RAZER 0x1532 +#define USB_VENDOR_SHANWAN 0x2563 #define USB_VENDOR_SHENZHEN 0x0079 #define USB_VENDOR_SONY 0x054c #define USB_VENDOR_VALVE 0x28de @@ -62,6 +63,7 @@ #define USB_PRODUCT_RAZER_PANTHERA 0x0401 #define USB_PRODUCT_RAZER_PANTHERA_EVO 0x1008 #define USB_PRODUCT_RAZER_ATROX 0x0a00 +#define USB_PRODUCT_SHANWAN_DS3 0x0523 #define USB_PRODUCT_SONY_DS3 0x0268 #define USB_PRODUCT_SONY_DS4 0x05c4 #define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0