Getting Started With XInput

XInput is an API that allows applications to receive input from the Xbox 360 Controller for Windows. Controller rumble effects and voice input and output are supported.

This topic provides a brief overview of the capabilities of XInput and how to set it up in an application. It includes the following:

Introduction to XInput

The Xbox 360 console uses a gaming controller that is compatible with Windows. Applications can use the XInput API to communicate with these controllers when they are plugged into a Windows PC (up to four unique controllers can be plugged in at a time).

Using this API, any connected Xbox 360 Controller can be queried for its state, and vibration effects can be set. Controllers that have the headset attached can also be queried for sound input and output devices that can be used with the headset for voice processing.

Operating System Requirements

XInput is supported on Windows XP (Service Pack 1) and above.

The Xbox 360 Controller

The Xbox 360 Controller has two analog directional sticks, each with a digital button, two analog triggers, a digital directional pad with four directions, and eight digital buttons. The states of each of these inputs are returned in the XINPUT_GAMEPAD structure when the XInputGetState function is called.

The controller also has two vibration motors to supply force feedback effects to the user. The speeds of these motors are specified in the XINPUT_VIBRATION structure that is passed to the XInputSetState function to set vibration effects.

Optionally, a headset can be connected to the controller. The headset has a microphone for voice input, and a headphone for sound output. Using the XInputGetDSoundAudioDeviceGuids function, you can retrieve the GUIDs that correspond to the DirectSound devices for the microphone and headphone, and receive voice input and send sound output using DirectSound APIs.

Note    Drivers for the Xbox 360 Controller are not included in the SDK or the DirectX redistributable. The drivers are available via Windows Update, or at windowsgaming.com.

Using XInput

Using XInput is as simple as calling the XInput functions as required. Using the XInput functions, you can retrieve controller state, get headset DirectSound GUIDs, and set controller rumble effects.

Multiple Controllers

The XInput API supports up to four controllers connected at any time. The XInput functions all require a dwUserIndex parameter that is passed in to identify the controller being set or queried. This ID will be in the range of 0-3 and is set automatically by XInput. The number corresponds to the port that the controller is plugged into, and is not modifiable.

Each controller displays which ID it is using by lighting up a quadrant on the "ring of light" in the center of the controller. A dwUserIndex value of 0 corresponds to the top-left quadrant; the numbering proceeds around the ring in clockwise order.

Applications should support multiple controllers. For examples on how to support multiple controllers, see the Samples.

Getting Controller State

Throughout the duration of an application, getting state from a controller will probably be done most often. From frame to frame in a game application, state should be retrieved and game information updated to reflect the controller changes.

To retrieve state, use the XInputGetState function:

DWORD dwResult;    
for (DWORD i=0; i< MAX_CONTROLLERS; i++ )
{
	XINPUT_STATE state;
	ZeroMemory( &state, sizeof(XINPUT_STATE) );

        // Simply get the state of the controller from XInput.
        dwResult = XInputGetState( i, &state );

        if( dwResult == ERROR_SUCCESS )
	{ 
	    // Controller is connected 
	}
        else
	{
            // Controller is not connected 
	}
}

Note that the return value of XInputGetState can be used to determine if the controller is connected. Applications should define a structure to hold internal controller information; this information should be compared against the results of XInputGetState to determine what changes, such as button presses or analog controller deltas, were made that frame. In the above example, g_Controllers represents such a structure.

Once the state has been retrieved in a XINPUT_STATE structure, you can check it for changes and get specific information about controller state.

The dwPacketNumber member of the XINPUT_STATE structure can be used to check if the state of the controller has changed since the last call to XInputGetState. If dwPacketNumber does not change between two sequential calls to XInputGetState, then there has been no change in state. If it differs, then the application should check the Gamepad member of the XINPUT_STATE structure to get more detailed state information.

Dead Zone

In order for users to have a consistent gameplay experience, your game must implement dead zone correctly. The dead zone is "movement" values reported by the controller even when the analog thumbsticks are untouched and centered. There is also a dead zone for the 2 analog triggers.

Note    Games that use XInput that do not filter dead zone at all will experience poor gameplay. Please note that some controllers are more sensitive than others, thus the dead zone may vary from unit to unit. It is recommended that you test your games with several Xbox 360 controllers on different systems.

Applications should use "dead zones" on analog inputs (triggers, sticks) to indicate when a movement has been made sufficiently on the stick or trigger to be considered valid.

Your application should check for dead zones and respond appopriately, as in this example:

// Zero value if thumbsticks are within the dead zone 
if( (state.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && 
     state.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) && 
    (state.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE && 
     state.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) )
{	
   state.Gamepad.sThumbLX = 0;
   state.Gamepad.sThumbLY = 0;
}

if( (state.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && 
     state.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) && 
    (state.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE && 
state.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) ) 
{
   state.Gamepad.sThumbRX = 0;
   state.Gamepad.sThumbRY = 0;
}

Note that you may define your own dead zones for the sticks and triggers (anywhere from 0-65534), or you may use the provided deadzones defined as XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE, and XINPUT_GAMEPAD_TRIGGER_THRESHOLD in XInput.h:

#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE  7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD    30

Once the deadzone is enforced, you may find it useful to scale the resulting range [0.0..1.0] floating point, and optionally apply a non-linear transform.

For example, with driving games, it may be helpful to cube the result to provide a better feel to driving the cars using a gamepad, as cubing the result gives you more precision in the lower ranges, which is desirable, since gamers typically either apply soft force to get subtle movement or apply hard force all the way in one direction to get rapid response.

Setting Vibration Effects

In addition to getting the state of the controller, you may also send vibration data to the controller to alter the feedback provided to the user of the controller. The controller contains two rumble motors that can be independently controlled by passing values to the XInputSetState function.

The speed of each motor can be specified using a WORD value in the XINPUT_VIBRATION structure that is passed to the XInputSetState function as follows:

XINPUT_VIBRATION vibration;
ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );
vibration.wLeftMotorSpeed = 32000; // use any value between 0-65535 here
vibration.wRightMotorSpeed = 16000; // use any value between 0-65535 here
XInputSetState( i, &vibration );

Note that the right motor is the high-frequency motor, the left motor is the low-frequency motor. They do not always need to be set to the same amount, as they provide different effects.

Getting DirectSound GUIDs

The headset that can be connected to an Xbox 360 Controller has two functions: it can record sound using a microphone, and it can play back sound using a headphone. In the XInput API, these functions are accomplished through DirectSound, using the IDirectSound8 and IDirectSoundCapture8 interfaces.

To associate the headset microphone and headphone with their appropriate DirectSound interfaces, you must get the DirectSound GUIDs for the capture and render devices by calling XInputGetDSoundAudioDeviceGuids.

XInputGetDSoundAudioDeviceGuids( i, &dsRenderGuid, &dsCaptureGuid );

Once you have retrieved the GUIDs you can create the appropriate interfaces by calling DirectSoundCreate8 and DirectSoundCaptureCreate8 like this:

// Create IDirectSound8 using the controller's render device
if( FAILED( hr = DirectSoundCreate8( &dsRenderGuid, &pDS, NULL ) ) )
   return hr;

// Set coop level to DSSCL_PRIORITY
if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
   return hr;

// Create IDirectSoundCapture using the controller's capture device
if( FAILED( hr = DirectSoundCaptureCreate8( &dsCaptureGuid, &pDSCapture, NULL ) ) )
   return hr;

See Also

XInput Reference | XInput Samples | DirectSound Reference