src/joystick/windows/SDL_dxjoystick.c
changeset 7707 37e02f8fcfa8
parent 7706 8cc29a668223
child 7709 edd2c14acf66
     1.1 --- a/src/joystick/windows/SDL_dxjoystick.c	Wed Aug 28 16:35:32 2013 -0400
     1.2 +++ b/src/joystick/windows/SDL_dxjoystick.c	Wed Aug 28 16:43:47 2013 -0400
     1.3 @@ -55,7 +55,6 @@
     1.4  
     1.5  
     1.6  #define INPUT_QSIZE 32      /* Buffer up to 32 input messages */
     1.7 -#define MAX_JOYSTICKS 8
     1.8  #define AXIS_MIN    -32768  /* minimum value for axis coordinate */
     1.9  #define AXIS_MAX    32767   /* maximum value for axis coordinate */
    1.10  #define JOY_AXIS_THRESHOLD  (((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
    1.11 @@ -70,7 +69,6 @@
    1.12  static SDL_bool s_bDeviceAdded = SDL_FALSE;
    1.13  static SDL_bool s_bDeviceRemoved = SDL_FALSE;
    1.14  static SDL_JoystickID s_nInstanceID = -1;
    1.15 -static GUID *s_pKnownJoystickGUIDs = NULL;
    1.16  static SDL_cond *s_condJoystickThread = NULL;
    1.17  static SDL_mutex *s_mutexJoyStickEnum = NULL;
    1.18  static SDL_Thread *s_threadJoystick = NULL;
    1.19 @@ -481,10 +479,10 @@
    1.20      HWND messageWindow = 0;
    1.21      HDEVNOTIFY hNotify = 0;
    1.22      DEV_BROADCAST_DEVICEINTERFACE dbh;
    1.23 -    SDL_bool bOpenedXInputDevices[4];
    1.24 +    SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
    1.25      WNDCLASSEX wincl;
    1.26  
    1.27 -    SDL_memset( bOpenedXInputDevices, 0x0, sizeof(bOpenedXInputDevices) );
    1.28 +    SDL_zero(bOpenedXInputDevices);
    1.29  
    1.30      WIN_CoInitialize();
    1.31  
    1.32 @@ -505,7 +503,7 @@
    1.33          return SDL_SetError("Failed to create message window for joystick autodetect.", GetLastError());
    1.34      }
    1.35  
    1.36 -    SDL_memset(&dbh, 0x0, sizeof(dbh));
    1.37 +    SDL_zero(dbh);
    1.38  
    1.39      dbh.dbcc_size = sizeof(dbh);
    1.40      dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    1.41 @@ -521,9 +519,8 @@
    1.42      while ( s_bJoystickThreadQuit == SDL_FALSE )
    1.43      {
    1.44          MSG messages;
    1.45 -        Uint8 userId;
    1.46 -        int nCurrentOpenedXInputDevices = 0;
    1.47 -        int nNewOpenedXInputDevices = 0;
    1.48 +        SDL_bool bXInputChanged = SDL_FALSE;
    1.49 +
    1.50          SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
    1.51  
    1.52          while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
    1.53 @@ -534,33 +531,24 @@
    1.54              }
    1.55          }
    1.56  
    1.57 -        if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
    1.58 -        {
    1.59 +        if ( s_bXInputEnabled && XINPUTGETCAPABILITIES ) {
    1.60              /* scan for any change in XInput devices */
    1.61 -            for ( userId = 0; userId < 4; userId++ )
    1.62 -            {
    1.63 +            Uint8 userId;
    1.64 +            for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
    1.65                  XINPUT_CAPABILITIES capabilities;
    1.66 -                DWORD result;
    1.67 -
    1.68 -                if ( bOpenedXInputDevices[userId] == SDL_TRUE )
    1.69 -                    nCurrentOpenedXInputDevices++;
    1.70 -
    1.71 -                result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
    1.72 -                if ( result == ERROR_SUCCESS )
    1.73 -                {
    1.74 -                    bOpenedXInputDevices[userId] = SDL_TRUE;
    1.75 -                    nNewOpenedXInputDevices++;
    1.76 -                }
    1.77 -                else
    1.78 -                {
    1.79 -                    bOpenedXInputDevices[userId] = SDL_FALSE;
    1.80 +                const DWORD result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
    1.81 +                const SDL_bool available = (result == ERROR_SUCCESS);
    1.82 +                if (bOpenedXInputDevices[userId] != available) {
    1.83 +                    bXInputChanged = SDL_TRUE;
    1.84 +                    bOpenedXInputDevices[userId] = available;
    1.85                  }
    1.86              }
    1.87          }
    1.88  
    1.89 -        if ( s_pKnownJoystickGUIDs && ( s_bWindowsDeviceChanged || nNewOpenedXInputDevices != nCurrentOpenedXInputDevices ) )
    1.90 -        {
    1.91 +        if (s_bWindowsDeviceChanged || bXInputChanged) {
    1.92 +            SDL_UnlockMutex( s_mutexJoyStickEnum );  /* let main thread go while we SDL_Delay(). */
    1.93              SDL_Delay( 300 ); /* wait for direct input to find out about this device */
    1.94 +            SDL_LockMutex( s_mutexJoyStickEnum );
    1.95  
    1.96              s_bDeviceRemoved = SDL_TRUE;
    1.97              s_bDeviceAdded = SDL_TRUE;
    1.98 @@ -625,15 +613,16 @@
    1.99          return SetDIerror("IDirectInput::Initialize", result);
   1.100      }
   1.101  
   1.102 +    if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
   1.103 +        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
   1.104 +    }
   1.105 +
   1.106      s_mutexJoyStickEnum = SDL_CreateMutex();
   1.107      s_condJoystickThread = SDL_CreateCond();
   1.108      s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
   1.109 +
   1.110      SDL_SYS_JoystickDetect();
   1.111  
   1.112 -    if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
   1.113 -        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
   1.114 -    }
   1.115 -
   1.116      if ( !s_threadJoystick )
   1.117      {
   1.118          s_bJoystickThreadQuit = SDL_FALSE;
   1.119 @@ -662,15 +651,17 @@
   1.120      return nJoysticks;
   1.121  }
   1.122  
   1.123 -static int s_iNewGUID = 0;
   1.124 -
   1.125  /* helper function for direct input, gets called for each connected joystick */
   1.126  static BOOL CALLBACK
   1.127      EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
   1.128  {
   1.129      JoyStick_DeviceData *pNewJoystick;
   1.130      JoyStick_DeviceData *pPrevJoystick = NULL;
   1.131 -    SDL_bool bXInputDevice;
   1.132 +
   1.133 +    if (SDL_IsXInputDevice( &pdidInstance->guidProduct )) {
   1.134 +        return DIENUM_CONTINUE;  /* ignore XInput devices here, keep going. */
   1.135 +    }
   1.136 +
   1.137      pNewJoystick = *(JoyStick_DeviceData **)pContext;
   1.138      while ( pNewJoystick )
   1.139      {
   1.140 @@ -689,58 +680,107 @@
   1.141              pNewJoystick->pNext = SYS_Joystick;
   1.142              SYS_Joystick = pNewJoystick;
   1.143  
   1.144 -            s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
   1.145 -            s_iNewGUID++;
   1.146 -            if ( s_iNewGUID < MAX_JOYSTICKS )
   1.147 -                return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
   1.148 -            else
   1.149 -                return DIENUM_STOP;
   1.150 +            return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
   1.151          }
   1.152  
   1.153          pPrevJoystick = pNewJoystick;
   1.154          pNewJoystick = pNewJoystick->pNext;
   1.155      }
   1.156  
   1.157 -    s_bDeviceAdded = SDL_TRUE;
   1.158 +    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
   1.159 +    if (!pNewJoystick) {
   1.160 +        return DIENUM_CONTINUE; /* better luck next time? */
   1.161 +    }
   1.162  
   1.163 -    bXInputDevice = SDL_IsXInputDevice( &pdidInstance->guidProduct );
   1.164 -
   1.165 -    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
   1.166 -
   1.167 -    if ( bXInputDevice )
   1.168 -    {
   1.169 -        pNewJoystick->bXInputDevice = SDL_TRUE;
   1.170 -        pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
   1.171 -    }
   1.172 -    else
   1.173 -    {
   1.174 -        pNewJoystick->bXInputDevice = SDL_FALSE;
   1.175 +    SDL_zerop(pNewJoystick);
   1.176 +    pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
   1.177 +    if (!pNewJoystick->joystickname) {
   1.178 +        SDL_free(pNewJoystick);
   1.179 +        return DIENUM_CONTINUE; /* better luck next time? */
   1.180      }
   1.181  
   1.182      SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
   1.183          sizeof(DIDEVICEINSTANCE));
   1.184  
   1.185 -    pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
   1.186 +    pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
   1.187      pNewJoystick->send_add_event = 1;
   1.188      pNewJoystick->nInstanceID = ++s_nInstanceID;
   1.189      SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
   1.190 -    pNewJoystick->pNext = NULL;
   1.191 -
   1.192 -    if ( SYS_Joystick )
   1.193 -    {
   1.194 -        pNewJoystick->pNext = SYS_Joystick;
   1.195 -    }
   1.196 +    pNewJoystick->pNext = SYS_Joystick;
   1.197      SYS_Joystick = pNewJoystick;
   1.198  
   1.199 -    s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
   1.200 -    s_iNewGUID++;
   1.201 +    s_bDeviceAdded = SDL_TRUE;
   1.202  
   1.203 -    if ( s_iNewGUID < MAX_JOYSTICKS )
   1.204 -        return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
   1.205 -    else
   1.206 -        return DIENUM_STOP;
   1.207 +    return DIENUM_CONTINUE; /* get next device, please */
   1.208  }
   1.209  
   1.210 +static void
   1.211 +AddXInputDevice(const Uint8 userid, JoyStick_DeviceData **pContext)
   1.212 +{
   1.213 +    char name[32];
   1.214 +    JoyStick_DeviceData *pPrevJoystick = NULL;
   1.215 +    JoyStick_DeviceData *pNewJoystick = *pContext;
   1.216 +
   1.217 +    while (pNewJoystick) {
   1.218 +        if ((pNewJoystick->bXInputDevice) && (pNewJoystick->XInputUserId == userid)) {
   1.219 +            /* if we are replacing the front of the list then update it */
   1.220 +            if (pNewJoystick == *pContext) {
   1.221 +                *pContext = pNewJoystick->pNext;
   1.222 +            } else if (pPrevJoystick) {
   1.223 +                pPrevJoystick->pNext = pNewJoystick->pNext;
   1.224 +            }
   1.225 +
   1.226 +            pNewJoystick->pNext = SYS_Joystick;
   1.227 +            SYS_Joystick = pNewJoystick;
   1.228 +        }
   1.229 +
   1.230 +        pPrevJoystick = pNewJoystick;
   1.231 +        pNewJoystick = pNewJoystick->pNext;
   1.232 +        return;   /* already in the list. */
   1.233 +    }
   1.234 +
   1.235 +    pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
   1.236 +    if (!pNewJoystick) {
   1.237 +        return; /* better luck next time? */
   1.238 +    }
   1.239 +    SDL_zerop(pNewJoystick);
   1.240 +
   1.241 +    SDL_snprintf(name, sizeof (name), "XInput Controller #%d", (int) userid);
   1.242 +    pNewJoystick->joystickname = SDL_strdup(name);
   1.243 +    if (!pNewJoystick->joystickname) {
   1.244 +        SDL_free(pNewJoystick);
   1.245 +        return; /* better luck next time? */
   1.246 +    }
   1.247 +
   1.248 +    pNewJoystick->bXInputDevice = SDL_TRUE;
   1.249 +    pNewJoystick->XInputUserId = userid;
   1.250 +    pNewJoystick->send_add_event = 1;
   1.251 +    pNewJoystick->nInstanceID = ++s_nInstanceID;
   1.252 +    pNewJoystick->pNext = SYS_Joystick;
   1.253 +    SYS_Joystick = pNewJoystick;
   1.254 +
   1.255 +    s_bDeviceAdded = SDL_TRUE;
   1.256 +}
   1.257 +
   1.258 +static void
   1.259 +EnumXInputDevices(JoyStick_DeviceData **pContext)
   1.260 +{
   1.261 +    if (s_bXInputEnabled) {
   1.262 +        Uint8 userid;
   1.263 +        for (userid = 0; userid < SDL_XINPUT_MAX_DEVICES; userid++) {
   1.264 +            XINPUT_CAPABILITIES capabilities;
   1.265 +            if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
   1.266 +                /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
   1.267 +                /* !!! FIXME: we might want to support steering wheels or guitars or whatever laster. */
   1.268 +                if (capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD) {
   1.269 +                    AddXInputDevice(userid, pContext);
   1.270 +                }
   1.271 +            }
   1.272 +        }
   1.273 +    }
   1.274 +}
   1.275 +
   1.276 +
   1.277  /* detect any new joysticks being inserted into the system */
   1.278  void SDL_SYS_JoystickDetect()
   1.279  {
   1.280 @@ -748,27 +788,26 @@
   1.281      /* only enum the devices if the joystick thread told us something changed */
   1.282      if ( s_bDeviceAdded || s_bDeviceRemoved )
   1.283      {
   1.284 +        SDL_LockMutex( s_mutexJoyStickEnum );
   1.285 +
   1.286          s_bDeviceAdded = SDL_FALSE;
   1.287          s_bDeviceRemoved = SDL_FALSE;
   1.288  
   1.289          pCurList = SYS_Joystick;
   1.290          SYS_Joystick = NULL;
   1.291 -        s_iNewGUID = 0;
   1.292 -        SDL_LockMutex( s_mutexJoyStickEnum );
   1.293  
   1.294 -        if ( !s_pKnownJoystickGUIDs )
   1.295 -            s_pKnownJoystickGUIDs = SDL_malloc( sizeof(GUID)*MAX_JOYSTICKS );
   1.296 +        /* Look for XInput devices... */
   1.297 +        EnumXInputDevices(&pCurList);
   1.298  
   1.299 -        SDL_memset( s_pKnownJoystickGUIDs, 0x0, sizeof(GUID)*MAX_JOYSTICKS );
   1.300 -
   1.301 -        /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
   1.302 +        /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
   1.303          IDirectInput8_EnumDevices(dinput,
   1.304              DI8DEVCLASS_GAMECTRL,
   1.305              EnumJoysticksCallback,
   1.306              &pCurList, DIEDFL_ATTACHEDONLY);
   1.307  
   1.308 -        SDL_free(SDL_RawDevList);  /* in case we used this. */
   1.309 +        SDL_free(SDL_RawDevList);  /* in case we used this in DirectInput enumerator. */
   1.310          SDL_RawDevList = NULL;
   1.311 +        SDL_RawDevListCount = 0;
   1.312  
   1.313          SDL_UnlockMutex( s_mutexJoyStickEnum );
   1.314      }
   1.315 @@ -872,17 +911,11 @@
   1.316  SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   1.317  {
   1.318      HRESULT result;
   1.319 -    LPDIRECTINPUTDEVICE8 device;
   1.320 -    DIPROPDWORD dipdw;
   1.321      JoyStick_DeviceData *joystickdevice = SYS_Joystick;
   1.322  
   1.323      for (; device_index > 0; device_index--)
   1.324          joystickdevice = joystickdevice->pNext;
   1.325  
   1.326 -    SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
   1.327 -    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
   1.328 -    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
   1.329 -
   1.330      /* allocate memory for system specific hardware data */
   1.331      joystick->instance_id = joystickdevice->nInstanceID;
   1.332      joystick->closed = 0;
   1.333 @@ -891,97 +924,50 @@
   1.334      if (joystick->hwdata == NULL) {
   1.335          return SDL_OutOfMemory();
   1.336      }
   1.337 -    SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
   1.338 -    joystick->hwdata->buffered = 1;
   1.339 -    joystick->hwdata->removed = 0;
   1.340 -    joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
   1.341 -    joystick->hwdata->guid = joystickdevice->guid;
   1.342 +    SDL_zerop(joystick->hwdata);
   1.343  
   1.344 -    if ( joystickdevice->bXInputDevice )
   1.345 -    {
   1.346 +    if (joystickdevice->bXInputDevice) {
   1.347 +        const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
   1.348 +        const Uint8 userId = joystickdevice->XInputUserId;
   1.349          XINPUT_CAPABILITIES capabilities;
   1.350 -        Uint8 userId = 0;
   1.351 -        DWORD result;
   1.352 -        JoyStick_DeviceData *joysticklist = SYS_Joystick;
   1.353 -        /* scan the opened joysticks and pick the next free xinput userid for this one */
   1.354 -        for( ; joysticklist; joysticklist = joysticklist->pNext)
   1.355 -        {
   1.356 -            if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
   1.357 -                userId++;
   1.358 -        }
   1.359  
   1.360 -        if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
   1.361 -        {
   1.362 -			while ( 1 )
   1.363 -			{
   1.364 -				result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
   1.365 -				if ( result == ERROR_SUCCESS )
   1.366 -				{
   1.367 -					const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
   1.368 -					SDL_bool bIsSupported = SDL_FALSE;
   1.369 -					/* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
   1.370 -					bIsSupported = ( capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD );
   1.371 +        SDL_assert(s_bXInputEnabled);
   1.372 +        SDL_assert(XINPUTGETCAPABILITIES);
   1.373 +        SDL_assert(userId >= 0);
   1.374 +        SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
   1.375  
   1.376 -					if ( !bIsSupported )
   1.377 -					{
   1.378 -						joystickdevice->bXInputDevice = SDL_FALSE;
   1.379 -					}
   1.380 -					else
   1.381 -					{
   1.382 -						/* valid */
   1.383 -						joystick->hwdata->bXInputDevice = SDL_TRUE;
   1.384 -						if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
   1.385 -							joystick->hwdata->bXInputHaptic = SDL_TRUE;
   1.386 -						}
   1.387 -						SDL_memset( joystick->hwdata->XInputState, 0x0, sizeof(joystick->hwdata->XInputState) );
   1.388 -						joystickdevice->XInputUserId = userId;
   1.389 -						joystick->hwdata->userid = userId;
   1.390 -						joystick->hwdata->currentXInputSlot = 0;
   1.391 -						/* The XInput API has a hard coded button/axis mapping, so we just match it */
   1.392 -						joystick->naxes = 6;
   1.393 -						joystick->nbuttons = 15;
   1.394 -						joystick->nballs = 0;
   1.395 -						joystick->nhats = 0;
   1.396 -					}
   1.397 -					break;
   1.398 -				}
   1.399 -				else
   1.400 -				{
   1.401 -					if ( userId < XUSER_MAX_COUNT && result == ERROR_DEVICE_NOT_CONNECTED )
   1.402 -					{
   1.403 -						/* scan the opened joysticks and pick the next free xinput userid for this one */
   1.404 -						++userId;
   1.405 +        joystick->hwdata->bXInputDevice = SDL_TRUE;
   1.406  
   1.407 -						joysticklist = SYS_Joystick;
   1.408 -						for( ; joysticklist; joysticklist = joysticklist->pNext)
   1.409 -						{
   1.410 -							if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
   1.411 -								userId++;
   1.412 -						}
   1.413 +        if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
   1.414 +            SDL_free(joystick->hwdata);
   1.415 +            joystick->hwdata = NULL;
   1.416 +            return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
   1.417 +        } else {
   1.418 +            /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
   1.419 +            SDL_assert(capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
   1.420 +            if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
   1.421 +                joystick->hwdata->bXInputHaptic = SDL_TRUE;
   1.422 +            }
   1.423 +            joystick->hwdata->userid = userId;
   1.424  
   1.425 -						if ( userId >= XUSER_MAX_COUNT )
   1.426 -						{
   1.427 -							joystickdevice->bXInputDevice = SDL_FALSE;
   1.428 -							break;
   1.429 -						}
   1.430 -					}
   1.431 -					else
   1.432 -					{
   1.433 -						joystickdevice->bXInputDevice = SDL_FALSE;
   1.434 -						break;
   1.435 -					}
   1.436 -				}
   1.437 -			}
   1.438 -        }
   1.439 -        else
   1.440 -        {
   1.441 -            joystickdevice->bXInputDevice = SDL_FALSE;
   1.442 -        }
   1.443 -    }
   1.444 +            /* The XInput API has a hard coded button/axis mapping, so we just match it */
   1.445 +            joystick->naxes = 6;
   1.446 +            joystick->nbuttons = 15;
   1.447 +            joystick->nballs = 0;
   1.448 +            joystick->nhats = 0;
   1.449 +		}
   1.450 +    } else {  /* use DirectInput, not XInput. */
   1.451 +        LPDIRECTINPUTDEVICE8 device;
   1.452 +        DIPROPDWORD dipdw;
   1.453  
   1.454 -    if ( joystickdevice->bXInputDevice == SDL_FALSE )
   1.455 -    {
   1.456 -        joystick->hwdata->bXInputDevice = SDL_FALSE;
   1.457 +        joystick->hwdata->buffered = 1;
   1.458 +        joystick->hwdata->removed = 0;
   1.459 +        joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
   1.460 +        joystick->hwdata->guid = joystickdevice->guid;
   1.461 +
   1.462 +        SDL_zero(dipdw);
   1.463 +        dipdw.diph.dwSize = sizeof(DIPROPDWORD);
   1.464 +        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
   1.465  
   1.466          result =
   1.467              IDirectInput8_CreateDevice(dinput,
   1.468 @@ -1633,18 +1619,11 @@
   1.469          coinitialized = SDL_FALSE;
   1.470      }
   1.471  
   1.472 -    if ( s_pKnownJoystickGUIDs )
   1.473 -    {
   1.474 -        SDL_free( s_pKnownJoystickGUIDs );
   1.475 -        s_pKnownJoystickGUIDs = NULL;
   1.476 -    }
   1.477 -
   1.478      if (s_bXInputEnabled) {
   1.479          WIN_UnloadXInputDLL();
   1.480      }
   1.481  }
   1.482  
   1.483 -
   1.484  /* return the stable device guid for this device index */
   1.485  SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
   1.486  {