diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c index 5d82f056f50..33a92e1e0f7 100644 --- a/dlls/xinput1_3/hid.c +++ b/dlls/xinput1_3/hid.c @@ -192,6 +192,11 @@ static BOOL VerifyGamepad(PHIDP_PREPARSED_DATA ppd, XINPUT_CAPABILITIES *xinput_ xinput_caps->Type = XINPUT_DEVTYPE_GAMEPAD; xinput_caps->SubType = XINPUT_DEVSUBTYPE_GAMEPAD; + + value_caps_count = caps->NumberOutputValueCaps; + if (value_caps_count > 0) + xinput_caps->Flags |= XINPUT_CAPS_FFB_SUPPORTED; + return TRUE; } @@ -411,3 +416,40 @@ void HID_update_state(xinput_controller* device) device->state.Gamepad.bLeftTrigger = SCALE_BYTE(value, private->LeftTriggerRange); LeaveCriticalSection(&private->crit); } + +DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) +{ + struct hid_platform_private *private = device->platform_private; + + struct { + BYTE report; + BYTE pad1[2]; + BYTE left; + BYTE right; + BYTE pad2[3]; + } report; + + if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED) + { + BOOLEAN rc; + + device->caps.Vibration.wLeftMotorSpeed = state->wLeftMotorSpeed; + device->caps.Vibration.wRightMotorSpeed = state->wRightMotorSpeed; + + report.report = 0; + report.pad1[0] = 0x8; + report.pad1[1] = 0x0; + report.left = (BYTE)(state->wLeftMotorSpeed / 255); + report.right = (BYTE)(state->wRightMotorSpeed / 255); + memset(&report.pad2, 0, sizeof(report.pad2)); + + EnterCriticalSection(&private->crit); + rc = HidD_SetOutputReport(private->device, &report, sizeof(report)); + LeaveCriticalSection(&private->crit); + if (rc) + return ERROR_SUCCESS; + return GetLastError(); + } + + return ERROR_NOT_SUPPORTED; +} diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c index 83ecb712439..680aba33a8c 100644 --- a/dlls/xinput1_3/xinput_main.c +++ b/dlls/xinput1_3/xinput_main.c @@ -63,14 +63,16 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable) DWORD WINAPI XInputSetState(DWORD index, XINPUT_VIBRATION* vibration) { - FIXME("(index %u, vibration %p) Stub!\n", index, vibration); + TRACE("(index %u, vibration %p)\n", index, vibration); + + HID_find_gamepads(controllers); if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS; if (!controllers[index].connected) return ERROR_DEVICE_NOT_CONNECTED; - return ERROR_NOT_SUPPORTED; + return HID_set_state(&controllers[index], vibration); } DWORD WINAPI DECLSPEC_HOTPATCH XInputGetState(DWORD index, XINPUT_STATE* state) diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h index 67ddbe4fffd..c10f869242e 100644 --- a/dlls/xinput1_3/xinput_private.h +++ b/dlls/xinput1_3/xinput_private.h @@ -29,3 +29,4 @@ typedef struct _xinput_controller void HID_find_gamepads(xinput_controller *devices) DECLSPEC_HIDDEN; void HID_destroy_gamepads(xinput_controller *devices) DECLSPEC_HIDDEN; void HID_update_state(xinput_controller* device) DECLSPEC_HIDDEN; +DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) DECLSPEC_HIDDEN; diff --git a/include/xinput.h b/include/xinput.h index 99ff0cc7cf8..dae8cad9748 100644 --- a/include/xinput.h +++ b/include/xinput.h @@ -156,6 +156,8 @@ #define XUSER_MAX_COUNT 4 #define XUSER_INDEX_ANY 0x000000FF +#define XINPUT_CAPS_FFB_SUPPORTED 0x0001 + /* * Defines the structure of an xbox 360 joystick. */