From ca22980dc0427401b645efc3fc156d7f52cc11e8 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 23 Oct 2013 22:42:48 -0700 Subject: [PATCH] XInput polling. --- src/xenia/hid/input_driver.h | 7 +++ src/xenia/hid/input_system.cc | 22 +++++++- src/xenia/hid/nop/nop_input_driver.cc | 18 +++++++ src/xenia/hid/nop/nop_input_driver.h | 7 +++ src/xenia/hid/xinput/xinput_input_driver.cc | 59 +++++++++++++++++++++ src/xenia/hid/xinput/xinput_input_driver.h | 7 +++ src/xenia/xbox.h | 17 ++++++ xenia.gyp | 1 + 8 files changed, 137 insertions(+), 1 deletion(-) diff --git a/src/xenia/hid/input_driver.h b/src/xenia/hid/input_driver.h index 15c0f24a1..03e036da3 100644 --- a/src/xenia/hid/input_driver.h +++ b/src/xenia/hid/input_driver.h @@ -26,6 +26,13 @@ public: virtual X_STATUS Setup() = 0; + virtual XRESULT GetCapabilities( + uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) = 0; + virtual XRESULT GetState( + uint32_t user_index, X_INPUT_STATE& out_state) = 0; + virtual XRESULT SetState( + uint32_t user_index, X_INPUT_VIBRATION& vibration) = 0; + protected: InputDriver(InputSystem* input_system); diff --git a/src/xenia/hid/input_system.cc b/src/xenia/hid/input_system.cc index 72de3454f..aeb4e8a90 100644 --- a/src/xenia/hid/input_system.cc +++ b/src/xenia/hid/input_system.cc @@ -44,15 +44,35 @@ void InputSystem::AddDriver(InputDriver* driver) { XRESULT InputSystem::GetCapabilities( uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) { + for (std::vector::iterator it = drivers_.begin(); + it != drivers_.end(); ++it) { + InputDriver* driver = *it; + if (XSUCCEEDED(driver->GetCapabilities(user_index, flags, out_caps))) { + return X_ERROR_SUCCESS; + } + } return X_ERROR_DEVICE_NOT_CONNECTED; } XRESULT InputSystem::GetState(uint32_t user_index, X_INPUT_STATE& out_state) { + for (std::vector::iterator it = drivers_.begin(); + it != drivers_.end(); ++it) { + InputDriver* driver = *it; + if (XSUCCEEDED(driver->GetState(user_index, out_state))) { + return X_ERROR_SUCCESS; + } + } return X_ERROR_DEVICE_NOT_CONNECTED; } XRESULT InputSystem::SetState( uint32_t user_index, X_INPUT_VIBRATION& vibration) { - // or X_ERROR_BUSY + for (std::vector::iterator it = drivers_.begin(); + it != drivers_.end(); ++it) { + InputDriver* driver = *it; + if (XSUCCEEDED(driver->SetState(user_index, vibration))) { + return X_ERROR_SUCCESS; + } + } return X_ERROR_DEVICE_NOT_CONNECTED; } diff --git a/src/xenia/hid/nop/nop_input_driver.cc b/src/xenia/hid/nop/nop_input_driver.cc index 1fde3ad7e..4dce8c37e 100644 --- a/src/xenia/hid/nop/nop_input_driver.cc +++ b/src/xenia/hid/nop/nop_input_driver.cc @@ -27,3 +27,21 @@ NopInputDriver::~NopInputDriver() { X_STATUS NopInputDriver::Setup() { return X_STATUS_SUCCESS; } + +// TODO(benvanik): spoof a device so that games don't stop waiting for +// a controller to be plugged in. + +XRESULT NopInputDriver::GetCapabilities( + uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) { + return X_ERROR_DEVICE_NOT_CONNECTED; +} + +XRESULT NopInputDriver::GetState( + uint32_t user_index, X_INPUT_STATE& out_state) { + return X_ERROR_DEVICE_NOT_CONNECTED; +} + +XRESULT NopInputDriver::SetState( + uint32_t user_index, X_INPUT_VIBRATION& vibration) { + return X_ERROR_DEVICE_NOT_CONNECTED; +} diff --git a/src/xenia/hid/nop/nop_input_driver.h b/src/xenia/hid/nop/nop_input_driver.h index 2dd78e312..dad3aa3bb 100644 --- a/src/xenia/hid/nop/nop_input_driver.h +++ b/src/xenia/hid/nop/nop_input_driver.h @@ -28,6 +28,13 @@ public: virtual X_STATUS Setup(); + virtual XRESULT GetCapabilities( + uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps); + virtual XRESULT GetState( + uint32_t user_index, X_INPUT_STATE& out_state); + virtual XRESULT SetState( + uint32_t user_index, X_INPUT_VIBRATION& vibration); + protected: }; diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc index bb7625c67..08c887385 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.cc +++ b/src/xenia/hid/xinput/xinput_input_driver.cc @@ -11,6 +11,8 @@ #include +#include + using namespace xe; using namespace xe::hid; @@ -19,11 +21,68 @@ using namespace xe::hid::xinput; XInputInputDriver::XInputInputDriver(InputSystem* input_system) : InputDriver(input_system) { + XInputEnable(TRUE); } XInputInputDriver::~XInputInputDriver() { + XInputEnable(FALSE); } X_STATUS XInputInputDriver::Setup() { return X_STATUS_SUCCESS; } + +XRESULT XInputInputDriver::GetCapabilities( + uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) { + XINPUT_CAPABILITIES native_caps; + DWORD result = XInputGetCapabilities(user_index, flags, &native_caps); + if (result) { + return result; + } + + out_caps.type = native_caps.Type; + out_caps.sub_type = native_caps.SubType; + out_caps.flags = native_caps.Flags; + out_caps.gamepad.buttons = native_caps.Gamepad.wButtons; + out_caps.gamepad.left_trigger = native_caps.Gamepad.bLeftTrigger; + out_caps.gamepad.right_trigger = native_caps.Gamepad.bRightTrigger; + out_caps.gamepad.thumb_lx = native_caps.Gamepad.sThumbLX; + out_caps.gamepad.thumb_ly = native_caps.Gamepad.sThumbLY; + out_caps.gamepad.thumb_rx = native_caps.Gamepad.sThumbRX; + out_caps.gamepad.thumb_ry = native_caps.Gamepad.sThumbRY; + out_caps.vibration.left_motor_speed = + native_caps.Vibration.wLeftMotorSpeed; + out_caps.vibration.right_motor_speed = + native_caps.Vibration.wRightMotorSpeed; + + return result; +} + +XRESULT XInputInputDriver::GetState( + uint32_t user_index, X_INPUT_STATE& out_state) { + XINPUT_STATE native_state; + DWORD result = XInputGetState(user_index, &native_state); + if (result) { + return result; + } + + out_state.packet_number = native_state.dwPacketNumber; + out_state.gamepad.buttons = native_state.Gamepad.wButtons; + out_state.gamepad.left_trigger = native_state.Gamepad.bLeftTrigger; + out_state.gamepad.right_trigger = native_state.Gamepad.bRightTrigger; + out_state.gamepad.thumb_lx = native_state.Gamepad.sThumbLX; + out_state.gamepad.thumb_ly = native_state.Gamepad.sThumbLY; + out_state.gamepad.thumb_rx = native_state.Gamepad.sThumbRX; + out_state.gamepad.thumb_ry = native_state.Gamepad.sThumbRY; + + return result; +} + +XRESULT XInputInputDriver::SetState( + uint32_t user_index, X_INPUT_VIBRATION& vibration) { + XINPUT_VIBRATION native_vibration; + native_vibration.wLeftMotorSpeed = vibration.left_motor_speed; + native_vibration.wRightMotorSpeed= vibration.right_motor_speed; + DWORD result = XInputSetState(user_index, &native_vibration); + return result; +} diff --git a/src/xenia/hid/xinput/xinput_input_driver.h b/src/xenia/hid/xinput/xinput_input_driver.h index 5c2fb4056..581b791c7 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.h +++ b/src/xenia/hid/xinput/xinput_input_driver.h @@ -28,6 +28,13 @@ public: virtual X_STATUS Setup(); + virtual XRESULT GetCapabilities( + uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps); + virtual XRESULT GetState( + uint32_t user_index, X_INPUT_STATE& out_state); + virtual XRESULT SetState( + uint32_t user_index, X_INPUT_VIBRATION& vibration); + protected: }; diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 9b9916214..bcc7c4e7a 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -256,6 +256,23 @@ typedef enum _X_INPUT_FLAG { X_INPUT_FLAG_GAMEPAD = 0x00000001, } X_INPUT_FLAG; +typedef enum _X_INPUT_GAMEPAD_BUTTON { + X_INPUT_GAMEPAD_DPAD_UP = 0x0001, + X_INPUT_GAMEPAD_DPAD_DOWN = 0x0002, + X_INPUT_GAMEPAD_DPAD_LEFT = 0x0004, + X_INPUT_GAMEPAD_DPAD_RIGHT = 0x0008, + X_INPUT_GAMEPAD_START = 0x0010, + X_INPUT_GAMEPAD_BACK = 0x0020, + X_INPUT_GAMEPAD_LEFT_THUMB = 0x0040, + X_INPUT_GAMEPAD_RIGHT_THUMB = 0x0080, + X_INPUT_GAMEPAD_LEFT_SHOULDER = 0x0100, + X_INPUT_GAMEPAD_RIGHT_SHOULDER = 0x0200, + X_INPUT_GAMEPAD_A = 0x1000, + X_INPUT_GAMEPAD_B = 0x2000, + X_INPUT_GAMEPAD_X = 0x4000, + X_INPUT_GAMEPAD_Y = 0x8000, +} X_INPUT_GAMEPAD_BUTTON; + class X_INPUT_GAMEPAD { public: uint16_t buttons; diff --git a/xenia.gyp b/xenia.gyp index 0c344ce56..b42265e92 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -46,6 +46,7 @@ 'dxgi', 'd3d11', 'd3dcompiler', + 'xinput', ], }], ['OS == "mac"', {