New Wiimote Plugin: Moved Linux cursor position code into ControllerInterface/Xlib...
[dolphin.git] / Source / Core / InputCommon / Src / ControllerInterface / XInput / XInput.cpp
blob526c6ffd9aa85000f29e3ea6986c5fe21b0beeb4
1 #include "../ControllerInterface.h"
3 #ifdef CIFACE_USE_XINPUT
5 #include "XInput.h"
7 namespace ciface
9 namespace XInput
12 static struct
14 const char* const name;
15 const WORD bitmask;
16 } named_buttons[] =
18 { "Button A", XINPUT_GAMEPAD_A },
19 { "Button B", XINPUT_GAMEPAD_B },
20 { "Button X", XINPUT_GAMEPAD_X },
21 { "Button Y", XINPUT_GAMEPAD_Y },
22 { "Pad N", XINPUT_GAMEPAD_DPAD_UP },
23 { "Pad S", XINPUT_GAMEPAD_DPAD_DOWN },
24 { "Pad W", XINPUT_GAMEPAD_DPAD_LEFT },
25 { "Pad E", XINPUT_GAMEPAD_DPAD_RIGHT },
26 { "Start", XINPUT_GAMEPAD_START },
27 { "Back", XINPUT_GAMEPAD_BACK },
28 { "Shoulder L", XINPUT_GAMEPAD_LEFT_SHOULDER },
29 { "Shoulder R", XINPUT_GAMEPAD_RIGHT_SHOULDER },
30 { "Thumb L", XINPUT_GAMEPAD_LEFT_THUMB },
31 { "Thumb R", XINPUT_GAMEPAD_RIGHT_THUMB }
34 static const char* const named_triggers[] =
36 "Trigger L",
37 "Trigger R"
40 static const char* const named_axes[] =
42 "Left X",
43 "Left Y",
44 "Right X",
45 "Right Y"
48 static const char* const named_motors[] =
50 "Motor L",
51 "Motor R"
54 void Init( std::vector<ControllerInterface::Device*>& devices )
56 XINPUT_CAPABILITIES caps;
57 for ( int i = 0; i < 4; ++i )
58 if ( ERROR_SUCCESS == XInputGetCapabilities( i, 0, &caps ) )
59 devices.push_back( new Device( &caps, i ) );
63 Device::Device( const XINPUT_CAPABILITIES* const caps, const unsigned int index )
64 : m_index(index), m_subtype(caps->SubType)
66 ZeroMemory( &m_state_out, sizeof(m_state_out) );
67 ZeroMemory( &m_current_state_out, sizeof(m_current_state_out) );
69 // XInputGetCaps seems to always claim all capabilities are supported
70 // but i will leave all this stuff in, incase m$ fixes xinput up a bit
72 // get supported buttons
73 for ( int i = 0; i < sizeof(named_buttons)/sizeof(*named_buttons); ++i )
74 if ( named_buttons[i].bitmask & caps->Gamepad.wButtons )
75 AddInput( new Button( /*xinput_named_buttons[i].bitmask, */i ) );
77 // get supported triggers
78 for ( int i = 0; i < sizeof(named_triggers)/sizeof(*named_triggers); ++i )
80 //BYTE val = (&caps->Gamepad.bLeftTrigger)[i]; // should be max value / msdn lies
81 if ( (&caps->Gamepad.bLeftTrigger)[i] )
82 AddInput( new Trigger( i, 255 ) );
85 // get supported axes
86 for ( int i = 0; i < sizeof(named_axes)/sizeof(*named_axes); ++i )
88 //SHORT val = (&caps->Gamepad.sThumbLX)[i]; // xinput doesnt give the range / msdn is lier
89 if ( (&caps->Gamepad.sThumbLX)[i] )
91 // each axis gets a negative and a positive input instance associated with it
92 AddInput( new Axis( i, -32768 ) );
93 AddInput( new Axis( i, 32767 ) );
97 // get supported motors
98 for ( int i = 0; i < sizeof(named_motors)/sizeof(*named_motors); ++i )
100 //WORD val = (&caps->Vibration.wLeftMotorSpeed)[i]; // should be max value / nope, more lies
101 if ( (&caps->Vibration.wLeftMotorSpeed)[i] )
102 AddOutput( new Motor(i, 65535 ) );
105 ClearInputState();
109 void Device::ClearInputState()
111 ZeroMemory( &m_state_in, sizeof(m_state_in) );
114 std::string Device::GetName() const
116 // why aren't these defined
117 // subtype doesn't seem to work, i tested with 2 diff arcade sticks, both were shown as gamepad
118 // ill leave it in anyway, maybe m$ will fix it
120 switch ( m_subtype )
122 case XINPUT_DEVSUBTYPE_GAMEPAD : return "Gamepad"; break;
123 case 0x02 /*XINPUT_DEVSUBTYPE_WHEEL*/ : return "Wheel"; break;
124 case 0x03 /*XINPUT_DEVSUBTYPE_ARCADE_STICK*/ : return "Arcade Stick"; break;
125 case 0x04 /*XINPUT_DEVSUBTYPE_FLIGHT_STICK*/ : return "Flight Stick"; break;
126 case 0x05 /*XINPUT_DEVSUBTYPE_DANCE_PAD*/ : return "Dance Pad"; break;
127 case 0x06 /*XINPUT_DEVSUBTYPE_GUITAR*/ : return "Guitar"; break;
128 case 0x08 /*XINPUT_DEVSUBTYPE_DRUM_KIT*/ : return "Drum Kit"; break;
129 default : return "Device"; break;
133 int Device::GetId() const
135 return m_index;
138 std::string Device::GetSource() const
140 return "XInput";
143 // update i/o
145 bool Device::UpdateInput()
147 return ( ERROR_SUCCESS == XInputGetState( m_index, &m_state_in ) );
150 bool Device::UpdateOutput()
152 // this if statement is to make rumble work better when multiple ControllerInterfaces are using the device
153 // only calls XInputSetState if the state changed
154 if ( memcmp( &m_state_out, &m_current_state_out, sizeof(m_state_out) ) )
156 m_current_state_out = m_state_out;
157 return ( ERROR_SUCCESS == XInputSetState( m_index, &m_state_out ) );
159 else
160 return true;
163 // GET name/source/id
166 std::string Device::Button::GetName() const
168 return named_buttons[m_index].name;
171 std::string Device::Axis::GetName() const
173 return std::string(named_axes[m_index]) + (m_range<0 ? '-' : '+');
176 std::string Device::Trigger::GetName() const
178 return named_triggers[m_index];
181 std::string Device::Motor::GetName() const
183 return named_motors[m_index];
186 // get/set control state
188 ControlState Device::GetInputState( const ControllerInterface::Device::Input* const input ) const
190 return ((Input*)input)->GetState( &m_state_in.Gamepad );
193 void Device::SetOutputState( const ControllerInterface::Device::Output* const output, const ControlState state )
195 return ((Output*)output)->SetState( state, &m_state_out );
198 // GET / SET STATES
200 ControlState Device::Button::GetState( const XINPUT_GAMEPAD* const gamepad ) const
202 return (gamepad->wButtons & named_buttons[m_index].bitmask) > 0;
205 ControlState Device::Trigger::GetState( const XINPUT_GAMEPAD* const gamepad ) const
207 return ControlState((&gamepad->bLeftTrigger)[m_index]) / m_range;
210 ControlState Device::Axis::GetState( const XINPUT_GAMEPAD* const gamepad ) const
212 return std::max( 0.0f, ControlState((&gamepad->sThumbLX)[m_index]) / m_range );
215 void Device::Motor::SetState( const ControlState state, XINPUT_VIBRATION* const vibration )
217 (&vibration->wLeftMotorSpeed)[m_index] = (WORD)(state * m_range);
223 #endif