--- a/src/joystick/SDL_gamecontroller.c Wed Aug 28 16:35:32 2013 -0400
+++ b/src/joystick/SDL_gamecontroller.c Wed Aug 28 16:43:47 2013 -0400
@@ -851,9 +851,6 @@
SDL_GameController *gamecontroller;
SDL_GameController *gamecontrollerlist;
ControllerMapping_t *pSupportedController = NULL;
-#ifdef SDL_JOYSTICK_DINPUT
- SDL_bool bIsXinputDevice;
-#endif
if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
@@ -886,11 +883,6 @@
return NULL;
}
-#ifdef SDL_JOYSTICK_DINPUT
- /* check if we think we should open this device in XInput mode */
- bIsXinputDevice = SDL_SYS_IsXInputDeviceIndex(device_index);
-#endif
-
SDL_memset(gamecontroller, 0, (sizeof *gamecontroller));
gamecontroller->joystick = SDL_JoystickOpen(device_index);
if ( !gamecontroller->joystick ) {
@@ -898,19 +890,6 @@
return NULL;
}
-#ifdef SDL_JOYSTICK_DINPUT
- if ( !SDL_SYS_IsXInputJoystick( gamecontroller->joystick ) && bIsXinputDevice )
- {
- /* we tried to open the controller in XInput mode and failed, so get the mapping again for the direct input variant if possible */
- SDL_JoystickGUID jGUID = SDL_JoystickGetDeviceGUID( device_index );
- pSupportedController = SDL_PrivateGetControllerMappingForGUID(&jGUID);
- if ( !pSupportedController ) {
- SDL_SetError("Failed to open device in XInput mode (%d)", device_index );
- return (NULL);
- }
- }
-#endif
-
SDL_PrivateLoadButtonMapping( &gamecontroller->mapping, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping );
/* Add joystick to list */
--- a/src/joystick/windows/SDL_dxjoystick.c Wed Aug 28 16:35:32 2013 -0400
+++ b/src/joystick/windows/SDL_dxjoystick.c Wed Aug 28 16:43:47 2013 -0400
@@ -55,7 +55,6 @@
#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
-#define MAX_JOYSTICKS 8
#define AXIS_MIN -32768 /* minimum value for axis coordinate */
#define AXIS_MAX 32767 /* maximum value for axis coordinate */
#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
@@ -70,7 +69,6 @@
static SDL_bool s_bDeviceAdded = SDL_FALSE;
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
static SDL_JoystickID s_nInstanceID = -1;
-static GUID *s_pKnownJoystickGUIDs = NULL;
static SDL_cond *s_condJoystickThread = NULL;
static SDL_mutex *s_mutexJoyStickEnum = NULL;
static SDL_Thread *s_threadJoystick = NULL;
@@ -481,10 +479,10 @@
HWND messageWindow = 0;
HDEVNOTIFY hNotify = 0;
DEV_BROADCAST_DEVICEINTERFACE dbh;
- SDL_bool bOpenedXInputDevices[4];
+ SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
WNDCLASSEX wincl;
- SDL_memset( bOpenedXInputDevices, 0x0, sizeof(bOpenedXInputDevices) );
+ SDL_zero(bOpenedXInputDevices);
WIN_CoInitialize();
@@ -505,7 +503,7 @@
return SDL_SetError("Failed to create message window for joystick autodetect.", GetLastError());
}
- SDL_memset(&dbh, 0x0, sizeof(dbh));
+ SDL_zero(dbh);
dbh.dbcc_size = sizeof(dbh);
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
@@ -521,9 +519,8 @@
while ( s_bJoystickThreadQuit == SDL_FALSE )
{
MSG messages;
- Uint8 userId;
- int nCurrentOpenedXInputDevices = 0;
- int nNewOpenedXInputDevices = 0;
+ SDL_bool bXInputChanged = SDL_FALSE;
+
SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
@@ -534,33 +531,24 @@
}
}
- if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
- {
+ if ( s_bXInputEnabled && XINPUTGETCAPABILITIES ) {
/* scan for any change in XInput devices */
- for ( userId = 0; userId < 4; userId++ )
- {
+ Uint8 userId;
+ for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
XINPUT_CAPABILITIES capabilities;
- DWORD result;
-
- if ( bOpenedXInputDevices[userId] == SDL_TRUE )
- nCurrentOpenedXInputDevices++;
-
- result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
- if ( result == ERROR_SUCCESS )
- {
- bOpenedXInputDevices[userId] = SDL_TRUE;
- nNewOpenedXInputDevices++;
- }
- else
- {
- bOpenedXInputDevices[userId] = SDL_FALSE;
+ const DWORD result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
+ const SDL_bool available = (result == ERROR_SUCCESS);
+ if (bOpenedXInputDevices[userId] != available) {
+ bXInputChanged = SDL_TRUE;
+ bOpenedXInputDevices[userId] = available;
}
}
}
- if ( s_pKnownJoystickGUIDs && ( s_bWindowsDeviceChanged || nNewOpenedXInputDevices != nCurrentOpenedXInputDevices ) )
- {
+ if (s_bWindowsDeviceChanged || bXInputChanged) {
+ SDL_UnlockMutex( s_mutexJoyStickEnum ); /* let main thread go while we SDL_Delay(). */
SDL_Delay( 300 ); /* wait for direct input to find out about this device */
+ SDL_LockMutex( s_mutexJoyStickEnum );
s_bDeviceRemoved = SDL_TRUE;
s_bDeviceAdded = SDL_TRUE;
@@ -625,15 +613,16 @@
return SetDIerror("IDirectInput::Initialize", result);
}
+ if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
+ s_bXInputEnabled = SDL_FALSE; /* oh well. */
+ }
+
s_mutexJoyStickEnum = SDL_CreateMutex();
s_condJoystickThread = SDL_CreateCond();
s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
+
SDL_SYS_JoystickDetect();
- if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
- s_bXInputEnabled = SDL_FALSE; /* oh well. */
- }
-
if ( !s_threadJoystick )
{
s_bJoystickThreadQuit = SDL_FALSE;
@@ -662,15 +651,17 @@
return nJoysticks;
}
-static int s_iNewGUID = 0;
-
/* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{
JoyStick_DeviceData *pNewJoystick;
JoyStick_DeviceData *pPrevJoystick = NULL;
- SDL_bool bXInputDevice;
+
+ if (SDL_IsXInputDevice( &pdidInstance->guidProduct )) {
+ return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
+ }
+
pNewJoystick = *(JoyStick_DeviceData **)pContext;
while ( pNewJoystick )
{
@@ -689,58 +680,107 @@
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
- s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
- s_iNewGUID++;
- if ( s_iNewGUID < MAX_JOYSTICKS )
- return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
- else
- return DIENUM_STOP;
+ return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
}
pPrevJoystick = pNewJoystick;
pNewJoystick = pNewJoystick->pNext;
}
- s_bDeviceAdded = SDL_TRUE;
-
- bXInputDevice = SDL_IsXInputDevice( &pdidInstance->guidProduct );
-
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
+ if (!pNewJoystick) {
+ return DIENUM_CONTINUE; /* better luck next time? */
+ }
- if ( bXInputDevice )
- {
- pNewJoystick->bXInputDevice = SDL_TRUE;
- pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
- }
- else
- {
- pNewJoystick->bXInputDevice = SDL_FALSE;
+ SDL_zerop(pNewJoystick);
+ pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
+ if (!pNewJoystick->joystickname) {
+ SDL_free(pNewJoystick);
+ return DIENUM_CONTINUE; /* better luck next time? */
}
SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
sizeof(DIDEVICEINSTANCE));
- pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
+ pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
pNewJoystick->send_add_event = 1;
pNewJoystick->nInstanceID = ++s_nInstanceID;
SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
- pNewJoystick->pNext = NULL;
-
- if ( SYS_Joystick )
- {
- pNewJoystick->pNext = SYS_Joystick;
- }
+ pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
- s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
- s_iNewGUID++;
+ s_bDeviceAdded = SDL_TRUE;
+
+ return DIENUM_CONTINUE; /* get next device, please */
+}
+
+static void
+AddXInputDevice(const Uint8 userid, JoyStick_DeviceData **pContext)
+{
+ char name[32];
+ JoyStick_DeviceData *pPrevJoystick = NULL;
+ JoyStick_DeviceData *pNewJoystick = *pContext;
+
+ while (pNewJoystick) {
+ if ((pNewJoystick->bXInputDevice) && (pNewJoystick->XInputUserId == userid)) {
+ /* if we are replacing the front of the list then update it */
+ if (pNewJoystick == *pContext) {
+ *pContext = pNewJoystick->pNext;
+ } else if (pPrevJoystick) {
+ pPrevJoystick->pNext = pNewJoystick->pNext;
+ }
+
+ pNewJoystick->pNext = SYS_Joystick;
+ SYS_Joystick = pNewJoystick;
+ }
+
+ pPrevJoystick = pNewJoystick;
+ pNewJoystick = pNewJoystick->pNext;
+ return; /* already in the list. */
+ }
+
+ pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
+ if (!pNewJoystick) {
+ return; /* better luck next time? */
+ }
+ SDL_zerop(pNewJoystick);
- if ( s_iNewGUID < MAX_JOYSTICKS )
- return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
- else
- return DIENUM_STOP;
+ SDL_snprintf(name, sizeof (name), "XInput Controller #%d", (int) userid);
+ pNewJoystick->joystickname = SDL_strdup(name);
+ if (!pNewJoystick->joystickname) {
+ SDL_free(pNewJoystick);
+ return; /* better luck next time? */
+ }
+
+ pNewJoystick->bXInputDevice = SDL_TRUE;
+ pNewJoystick->XInputUserId = userid;
+ pNewJoystick->send_add_event = 1;
+ pNewJoystick->nInstanceID = ++s_nInstanceID;
+ pNewJoystick->pNext = SYS_Joystick;
+ SYS_Joystick = pNewJoystick;
+
+ s_bDeviceAdded = SDL_TRUE;
}
+static void
+EnumXInputDevices(JoyStick_DeviceData **pContext)
+{
+ if (s_bXInputEnabled) {
+ Uint8 userid;
+ for (userid = 0; userid < SDL_XINPUT_MAX_DEVICES; userid++) {
+ XINPUT_CAPABILITIES capabilities;
+ if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
+ /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
+ /* !!! FIXME: we might want to support steering wheels or guitars or whatever laster. */
+ if (capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD) {
+ AddXInputDevice(userid, pContext);
+ }
+ }
+ }
+ }
+}
+
+
/* detect any new joysticks being inserted into the system */
void SDL_SYS_JoystickDetect()
{
@@ -748,27 +788,26 @@
/* only enum the devices if the joystick thread told us something changed */
if ( s_bDeviceAdded || s_bDeviceRemoved )
{
+ SDL_LockMutex( s_mutexJoyStickEnum );
+
s_bDeviceAdded = SDL_FALSE;
s_bDeviceRemoved = SDL_FALSE;
pCurList = SYS_Joystick;
SYS_Joystick = NULL;
- s_iNewGUID = 0;
- SDL_LockMutex( s_mutexJoyStickEnum );
- if ( !s_pKnownJoystickGUIDs )
- s_pKnownJoystickGUIDs = SDL_malloc( sizeof(GUID)*MAX_JOYSTICKS );
+ /* Look for XInput devices... */
+ EnumXInputDevices(&pCurList);
- SDL_memset( s_pKnownJoystickGUIDs, 0x0, sizeof(GUID)*MAX_JOYSTICKS );
-
- /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
+ /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
IDirectInput8_EnumDevices(dinput,
DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,
&pCurList, DIEDFL_ATTACHEDONLY);
- SDL_free(SDL_RawDevList); /* in case we used this. */
+ SDL_free(SDL_RawDevList); /* in case we used this in DirectInput enumerator. */
SDL_RawDevList = NULL;
+ SDL_RawDevListCount = 0;
SDL_UnlockMutex( s_mutexJoyStickEnum );
}
@@ -872,17 +911,11 @@
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
{
HRESULT result;
- LPDIRECTINPUTDEVICE8 device;
- DIPROPDWORD dipdw;
JoyStick_DeviceData *joystickdevice = SYS_Joystick;
for (; device_index > 0; device_index--)
joystickdevice = joystickdevice->pNext;
- SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
-
/* allocate memory for system specific hardware data */
joystick->instance_id = joystickdevice->nInstanceID;
joystick->closed = 0;
@@ -891,97 +924,50 @@
if (joystick->hwdata == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
- joystick->hwdata->buffered = 1;
- joystick->hwdata->removed = 0;
- joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
- joystick->hwdata->guid = joystickdevice->guid;
+ SDL_zerop(joystick->hwdata);
- if ( joystickdevice->bXInputDevice )
- {
+ if (joystickdevice->bXInputDevice) {
+ const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
+ const Uint8 userId = joystickdevice->XInputUserId;
XINPUT_CAPABILITIES capabilities;
- Uint8 userId = 0;
- DWORD result;
- JoyStick_DeviceData *joysticklist = SYS_Joystick;
- /* scan the opened joysticks and pick the next free xinput userid for this one */
- for( ; joysticklist; joysticklist = joysticklist->pNext)
- {
- if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
- userId++;
- }
- if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
- {
- while ( 1 )
- {
- result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
- if ( result == ERROR_SUCCESS )
- {
- const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
- SDL_bool bIsSupported = SDL_FALSE;
- /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
- bIsSupported = ( capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD );
+ SDL_assert(s_bXInputEnabled);
+ SDL_assert(XINPUTGETCAPABILITIES);
+ SDL_assert(userId >= 0);
+ SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
+
+ joystick->hwdata->bXInputDevice = SDL_TRUE;
- if ( !bIsSupported )
- {
- joystickdevice->bXInputDevice = SDL_FALSE;
- }
- else
- {
- /* valid */
- joystick->hwdata->bXInputDevice = SDL_TRUE;
- if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
- joystick->hwdata->bXInputHaptic = SDL_TRUE;
- }
- SDL_memset( joystick->hwdata->XInputState, 0x0, sizeof(joystick->hwdata->XInputState) );
- joystickdevice->XInputUserId = userId;
- joystick->hwdata->userid = userId;
- joystick->hwdata->currentXInputSlot = 0;
- /* The XInput API has a hard coded button/axis mapping, so we just match it */
- joystick->naxes = 6;
- joystick->nbuttons = 15;
- joystick->nballs = 0;
- joystick->nhats = 0;
- }
- break;
- }
- else
- {
- if ( userId < XUSER_MAX_COUNT && result == ERROR_DEVICE_NOT_CONNECTED )
- {
- /* scan the opened joysticks and pick the next free xinput userid for this one */
- ++userId;
+ if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
+ SDL_free(joystick->hwdata);
+ joystick->hwdata = NULL;
+ return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
+ } else {
+ /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
+ SDL_assert(capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
+ if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
+ joystick->hwdata->bXInputHaptic = SDL_TRUE;
+ }
+ joystick->hwdata->userid = userId;
- joysticklist = SYS_Joystick;
- for( ; joysticklist; joysticklist = joysticklist->pNext)
- {
- if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
- userId++;
- }
+ /* The XInput API has a hard coded button/axis mapping, so we just match it */
+ joystick->naxes = 6;
+ joystick->nbuttons = 15;
+ joystick->nballs = 0;
+ joystick->nhats = 0;
+ }
+ } else { /* use DirectInput, not XInput. */
+ LPDIRECTINPUTDEVICE8 device;
+ DIPROPDWORD dipdw;
- if ( userId >= XUSER_MAX_COUNT )
- {
- joystickdevice->bXInputDevice = SDL_FALSE;
- break;
- }
- }
- else
- {
- joystickdevice->bXInputDevice = SDL_FALSE;
- break;
- }
- }
- }
- }
- else
- {
- joystickdevice->bXInputDevice = SDL_FALSE;
- }
- }
+ joystick->hwdata->buffered = 1;
+ joystick->hwdata->removed = 0;
+ joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
+ joystick->hwdata->guid = joystickdevice->guid;
- if ( joystickdevice->bXInputDevice == SDL_FALSE )
- {
- joystick->hwdata->bXInputDevice = SDL_FALSE;
+ SDL_zero(dipdw);
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
result =
IDirectInput8_CreateDevice(dinput,
@@ -1633,18 +1619,11 @@
coinitialized = SDL_FALSE;
}
- if ( s_pKnownJoystickGUIDs )
- {
- SDL_free( s_pKnownJoystickGUIDs );
- s_pKnownJoystickGUIDs = NULL;
- }
-
if (s_bXInputEnabled) {
WIN_UnloadXInputDLL();
}
}
-
/* return the stable device guid for this device index */
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
{