Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/ois/win32/Win32JoyStick.cpp @ 8351

Last change on this file since 8351 was 8351, checked in by rgrieder, 13 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
  • Property svn:eol-style set to native
File size: 21.4 KB
Line 
1/*
2The zlib/libpng License
3
4Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6This software is provided 'as-is', without any express or implied warranty. In no event will
7the authors be held liable for any damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose, including commercial
10applications, and to alter it and redistribute it freely, subject to the following
11restrictions:
12
13    1. The origin of this software must not be misrepresented; you must not claim that
14                you wrote the original software. If you use this software in a product,
15                an acknowledgment in the product documentation would be appreciated but is
16                not required.
17
18    2. Altered source versions must be plainly marked as such, and must not be
19                misrepresented as being the original software.
20
21    3. This notice may not be removed or altered from any source distribution.
22*/
23#include "win32/Win32JoyStick.h"
24#include "win32/Win32InputManager.h"
25#include "win32/Win32ForceFeedback.h"
26#include "OISEvents.h"
27#include "OISException.h"
28
29// (Orxonox): Required for MinGW to compile properly
30#ifdef __MINGW32__
31#  include <oaidl.h>
32#  ifndef __MINGW_EXTENSION
33#    define __MINGW_EXTENSION __extension__
34#  endif
35#endif
36
37#include <cassert>
38#include <wbemidl.h>
39#include <oleauto.h>
40//#include <wmsstd.h>
41#ifndef SAFE_RELEASE
42#define SAFE_RELEASE(x) \
43   if(x != NULL)        \
44   {                    \
45      x->Release();     \
46      x = NULL;         \
47   }
48#endif
49
50// (Orxonox): MinGW doesn't have swscanf_s
51#ifdef __MINGW32__
52#       define swscanf_s swscanf
53#endif
54
55#ifdef OIS_WIN32_XINPUT_SUPPORT
56#       pragma comment(lib, "xinput.lib")
57#endif
58
59//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
60#undef DIJOFS_BUTTON
61#undef DIJOFS_POV
62
63#define DIJOFS_BUTTON(n)  (FIELD_OFFSET(DIJOYSTATE2, rgbButtons) + (n))
64#define DIJOFS_POV(n)     (FIELD_OFFSET(DIJOYSTATE2, rgdwPOV)+(n)*sizeof(DWORD))
65#define DIJOFS_SLIDER0(n) (FIELD_OFFSET(DIJOYSTATE2, rglSlider)+(n) * sizeof(LONG))
66#define DIJOFS_SLIDER1(n) (FIELD_OFFSET(DIJOYSTATE2, rglVSlider)+(n) * sizeof(LONG))
67#define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG))
68#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
69
70#define XINPUT_TRANSLATED_BUTTON_COUNT 12
71#define XINPUT_TRANSLATED_AXIS_COUNT 6
72
73using namespace OIS;
74
75//--------------------------------------------------------------------------------------------------//
76Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) :
77        JoyStick(info.vendor, buffered, info.devId, creator),
78        mDirectInput(pDI),
79        coopSetting(coopSettings),
80        mJoyStick(0),
81        mJoyInfo(info),
82        mFfDevice(0)
83{
84}
85
86//--------------------------------------------------------------------------------------------------//
87Win32JoyStick::~Win32JoyStick()
88{
89        delete mFfDevice;
90
91        if(mJoyStick)
92        {
93                mJoyStick->Unacquire();
94                mJoyStick->Release();
95                mJoyStick = 0;
96        }
97
98        //Return joystick to pool
99        static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo);
100}
101
102//--------------------------------------------------------------------------------------------------//
103void Win32JoyStick::_initialize()
104{
105    if (mJoyInfo.isXInput)
106    {
107        _enumerate();
108    }
109    else
110    {
111            //Clear old state
112            mState.mAxes.clear();
113
114            delete mFfDevice;
115            mFfDevice = 0;
116
117            DIPROPDWORD dipdw;
118
119            dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
120            dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
121            dipdw.diph.dwObj        = 0;
122            dipdw.diph.dwHow        = DIPH_DEVICE;
123            dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
124
125            if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL)))
126                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
127
128            if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
129                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
130
131            HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
132
133            if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
134                    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
135
136            if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
137                    OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
138
139            //Enumerate all axes/buttons/sliders/etc before aquiring
140            _enumerate();
141
142            mState.clear();
143
144            capture();
145    }
146}
147
148//--------------------------------------------------------------------------------------------------//
149void Win32JoyStick::_enumerate()
150{
151    if (mJoyInfo.isXInput)
152    {
153        mPOVs = 1;
154
155        mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT);
156            mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT);
157    }
158    else
159    {
160                // Get joystick capabilities.
161                mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
162                if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
163                        OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
164
165            mPOVs = (short)mDIJoyCaps.dwPOVs;
166
167            mState.mButtons.resize(mDIJoyCaps.dwButtons);
168            mState.mAxes.resize(mDIJoyCaps.dwAxes);
169
170            //Reset the axis mapping enumeration value
171            _AxisNumber = 0;
172
173            //Enumerate Force Feedback (if any)
174            mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
175
176            //Enumerate and set axis constraints (and check FF Axes)
177            mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
178    }
179}
180
181//--------------------------------------------------------------------------------------------------//
182BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
183{
184        Win32JoyStick* _this = (Win32JoyStick*)pvRef;
185
186        //Setup mappings
187        DIPROPPOINTER diptr;
188        diptr.diph.dwSize       = sizeof(DIPROPPOINTER);
189        diptr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
190        diptr.diph.dwHow        = DIPH_BYID;
191        diptr.diph.dwObj        = lpddoi->dwType;
192        //Add a magic number to recognise we set seomthing
193        diptr.uData             = 0x13130000 | _this->_AxisNumber;
194
195        //Check if axis is slider, if so, do not treat as regular axis
196        if(GUID_Slider == lpddoi->guidType)
197        {
198                ++_this->mSliders;
199
200                //Decrease Axes, since this slider shows up in a different place
201                _this->mState.mAxes.pop_back();
202        }
203        else if (FAILED(_this->mJoyStick->SetProperty(DIPROP_APPDATA, &diptr.diph)))
204        {       //If for some reason we could not set needed user data, just ignore this axis
205                return DIENUM_CONTINUE;
206        }
207
208        //Increase for next time through
209        if(GUID_Slider != lpddoi->guidType)
210                _this->_AxisNumber += 1;
211
212        //Set range
213        DIPROPRANGE diprg;
214        diprg.diph.dwSize       = sizeof(DIPROPRANGE);
215        diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
216        diprg.diph.dwHow        = DIPH_BYID;
217        diprg.diph.dwObj        = lpddoi->dwType;
218        diprg.lMin              = MIN_AXIS;
219        diprg.lMax              = MAX_AXIS;
220
221        if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph)))
222                OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
223
224        //Check if FF Axes, and if so, increment counter
225        if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
226        {
227                if( _this->mFfDevice )
228                {
229                        _this->mFfDevice->_addFFAxis();
230                }
231        }
232
233        //Force the flags for gain and auto-center support to true,
234        //as DInput has no API to query the device for these capabilities
235        //(the only way to know is to try them ...)
236        if( _this->mFfDevice )
237        {
238            _this->mFfDevice->_setGainSupport(true);
239            _this->mFfDevice->_setAutoCenterSupport(true);
240        }
241
242        return DIENUM_CONTINUE;
243}
244
245//--------------------------------------------------------------------------------------------------//
246BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef)
247{
248        Win32JoyStick* _this = (Win32JoyStick*)pvRef;
249
250        //Create the FF instance only after we know there is at least one effect type
251        if( _this->mFfDevice == 0 )
252                _this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
253
254        _this->mFfDevice->_addEffectSupport(pdei);
255
256        return DIENUM_CONTINUE;
257}
258
259//--------------------------------------------------------------------------------------------------//
260void Win32JoyStick::capture()
261{
262#ifdef OIS_WIN32_XINPUT_SUPPORT
263        //handle xbox controller differently
264    if (mJoyInfo.isXInput)
265        {
266                captureXInput();
267                return;
268        }
269#endif
270
271        //handle directinput based devices
272        DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
273        DWORD entries = JOYSTICK_DX_BUFFERSIZE;
274
275        // Poll the device to read the current state
276        HRESULT hr = mJoyStick->Poll();
277        if( hr == DI_OK )
278                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
279
280        if( hr != DI_OK )
281        {
282                hr = mJoyStick->Acquire();
283                while( hr == DIERR_INPUTLOST )
284                        hr = mJoyStick->Acquire();
285
286                // Poll the device to read the current state
287                mJoyStick->Poll();
288                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
289                //Perhaps the user just tabbed away
290                if( FAILED(hr) )
291                        return;
292        }
293
294        bool axisMoved[24] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,
295                                                  false,false,false,false,false,false,false,false};
296        bool sliderMoved[4] = {false,false,false,false};
297
298        //Loop through all the events
299        for(unsigned int i = 0; i < entries; ++i)
300        {
301                //This may seem outof order, but is in order of the way these variables
302                //are declared in the JoyStick State 2 structure.
303                switch(diBuff[i].dwOfs)
304                {
305                //------ slider -//
306                case DIJOFS_SLIDER0(0):
307                        sliderMoved[0] = true;
308                        mState.mSliders[0].abX = diBuff[i].dwData;
309                        break;
310                case DIJOFS_SLIDER0(1):
311                        sliderMoved[0] = true;
312                        mState.mSliders[0].abY = diBuff[i].dwData;
313                        break;
314                //----- Max 4 POVs Next ---------------//
315                case DIJOFS_POV(0):
316                        if(!_changePOV(0,diBuff[i]))
317                                return;
318                        break;
319                case DIJOFS_POV(1):
320                        if(!_changePOV(1,diBuff[i]))
321                                return;
322                        break;
323                case DIJOFS_POV(2):
324                        if(!_changePOV(2,diBuff[i]))
325                                return;
326                        break;
327                case DIJOFS_POV(3):
328                        if(!_changePOV(3,diBuff[i]))
329                                return;
330                        break;
331                case DIJOFS_SLIDER1(0):
332                        sliderMoved[1] = true;
333                        mState.mSliders[1].abX = diBuff[i].dwData;
334                        break;
335                case DIJOFS_SLIDER1(1):
336                        sliderMoved[1] = true;
337                        mState.mSliders[1].abY = diBuff[i].dwData;
338                        break;
339                case DIJOFS_SLIDER2(0):
340                        sliderMoved[2] = true;
341                        mState.mSliders[2].abX = diBuff[i].dwData;
342                        break;
343                case DIJOFS_SLIDER2(1):
344                        sliderMoved[2] = true;
345                        mState.mSliders[2].abY = diBuff[i].dwData;
346                        break;
347                case DIJOFS_SLIDER3(0):
348                        sliderMoved[3] = true;
349                        mState.mSliders[3].abX = diBuff[i].dwData;
350                        break;
351                case DIJOFS_SLIDER3(1):
352                        sliderMoved[3] = true;
353                        mState.mSliders[3].abY = diBuff[i].dwData;
354                        break;
355                //-----------------------------------------//
356                default:
357                        //Handle Button Events Easily using the DX Offset Macros
358                        if( diBuff[i].dwOfs >= DIJOFS_BUTTON(0) && diBuff[i].dwOfs < DIJOFS_BUTTON(128) )
359                        {
360                                if(!_doButtonClick((diBuff[i].dwOfs - DIJOFS_BUTTON(0)), diBuff[i]))
361                                        return;
362                        }
363                        else if((short)(diBuff[i].uAppData >> 16) == 0x1313)
364                        {       //If it was nothing else, might be axis enumerated earlier (determined by magic number)
365                                int axis = (int)(0x0000FFFF & diBuff[i].uAppData); //Mask out the high bit
366                                assert( axis >= 0 && axis < (int)mState.mAxes.size() && "Axis out of range!");
367
368                                if(axis >= 0 && axis < (int)mState.mAxes.size())
369                                {
370                                        mState.mAxes[axis].abs = diBuff[i].dwData;
371                                        axisMoved[axis] = true;
372                                }
373                        }
374
375                        break;
376                } //end case
377        } //end for
378
379        //Check to see if any of the axes values have changed.. if so send events
380        if( mBuffered && mListener && entries > 0 )
381        {
382                JoyStickEvent temp(this, mState);
383
384                //Update axes
385                for( int i = 0; i < 24; ++i )
386                        if( axisMoved[i] )
387                                if( mListener->axisMoved( temp, i ) == false )
388                                        return;
389
390                //Now update sliders
391                for( int i = 0; i < 4; ++i )
392                        if( sliderMoved[i] )
393                                if( mListener->sliderMoved( temp, i ) == false )
394                                        return;
395        }
396}
397
398//--------------------------------------------------------------------------------------------------//
399void Win32JoyStick::captureXInput()
400{
401#ifdef OIS_WIN32_XINPUT_SUPPORT
402    XINPUT_STATE inputState;
403        if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS)
404        memset(&inputState, 0, sizeof(inputState));
405
406    //Sticks and triggers
407        int value;
408    bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false};
409
410        //LeftY
411        value = -(int)inputState.Gamepad.sThumbLY;
412        mState.mAxes[0].rel = value - mState.mAxes[0].abs;
413        mState.mAxes[0].abs = value;
414        if(mState.mAxes[0].rel != 0)
415        axisMoved[0] = true;
416
417        //LeftX
418    mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs;
419    mState.mAxes[1].abs = inputState.Gamepad.sThumbLX;
420
421        if(mState.mAxes[1].rel != 0)
422        axisMoved[1] = true;
423
424        //RightY
425        value = -(int)inputState.Gamepad.sThumbRY;           
426    mState.mAxes[2].rel = value - mState.mAxes[2].abs;
427    mState.mAxes[2].abs = value;
428        if(mState.mAxes[2].rel != 0)
429        axisMoved[2] = true;
430
431        //RightX
432    mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs;
433    mState.mAxes[3].abs = inputState.Gamepad.sThumbRX;
434        if(mState.mAxes[3].rel != 0)
435                axisMoved[3] = true;
436
437        //Left trigger
438    value = inputState.Gamepad.bLeftTrigger * 129;
439        if(value > JoyStick::MAX_AXIS)
440                value = JoyStick::MAX_AXIS;
441
442    mState.mAxes[4].rel = value - mState.mAxes[4].abs;
443    mState.mAxes[4].abs = value;
444        if(mState.mAxes[4].rel != 0)
445                axisMoved[4] = true;
446
447        //Right trigger
448    value = (int)inputState.Gamepad.bRightTrigger * 129;
449        if(value > JoyStick::MAX_AXIS)
450                value = JoyStick::MAX_AXIS;
451
452        mState.mAxes[5].rel = value - mState.mAxes[5].abs;
453    mState.mAxes[5].abs = value;
454        if(mState.mAxes[5].rel != 0)
455                axisMoved[5] = true;
456   
457    //POV
458    int previousPov = mState.mPOV[0].direction;       
459    int& pov = mState.mPOV[0].direction;
460    pov = Pov::Centered;       
461    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
462        pov |= Pov::North;
463    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
464        pov |= Pov::South;
465    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
466        pov |= Pov::West;
467    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
468        pov |= Pov::East;
469   
470    //Buttons - The first 4 buttons don't need to be checked since they represent the dpad
471    bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT];
472    std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons);
473    for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
474        mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0;
475
476    //Send events
477    if (mBuffered && mListener)
478    {
479            JoyStickEvent joystickEvent(this, mState);
480
481            //Axes
482            for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++)
483        {
484                    if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i))
485                            return;
486        }
487
488        //POV
489        if (previousPov != pov && !mListener->povMoved(joystickEvent, 0))
490            return;
491
492        //Buttons
493        for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
494        {
495            if (!previousButtons[i] && mState.mButtons[i])
496            {
497                if (!mListener->buttonPressed(joystickEvent, i))
498                    return;
499            }
500            else if (previousButtons[i] && !mState.mButtons[i])
501            {
502                if (!mListener->buttonReleased(joystickEvent, i))
503                    return;
504            }
505        }
506    }
507#endif
508}
509
510//--------------------------------------------------------------------------------------------------//
511bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
512{
513        if( di.dwData & 0x80 )
514        {
515                mState.mButtons[button] = true;
516                if( mBuffered && mListener )
517                        return mListener->buttonPressed( JoyStickEvent( this, mState ), button );
518        }
519        else
520        {
521                mState.mButtons[button] = false;
522                if( mBuffered && mListener )
523                        return mListener->buttonReleased( JoyStickEvent( this, mState ), button );
524        }
525
526        return true;
527}
528
529//--------------------------------------------------------------------------------------------------//
530bool Win32JoyStick::_changePOV( int pov, DIDEVICEOBJECTDATA& di )
531{
532        //Some drivers report a value of 65,535, instead of —1,
533        //for the center position
534        if(LOWORD(di.dwData) == 0xFFFF)
535        {
536                mState.mPOV[pov].direction = Pov::Centered;
537        }
538        else
539        {
540                switch(di.dwData)
541                {
542                        case 0: mState.mPOV[pov].direction = Pov::North; break;
543                        case 4500: mState.mPOV[pov].direction = Pov::NorthEast; break;
544                        case 9000: mState.mPOV[pov].direction = Pov::East; break;
545                        case 13500: mState.mPOV[pov].direction = Pov::SouthEast; break;
546                        case 18000: mState.mPOV[pov].direction = Pov::South; break;
547                        case 22500: mState.mPOV[pov].direction = Pov::SouthWest; break;
548                        case 27000: mState.mPOV[pov].direction = Pov::West; break;
549                        case 31500: mState.mPOV[pov].direction = Pov::NorthWest; break;
550                }
551        }
552
553        if( mBuffered && mListener )
554                return mListener->povMoved( JoyStickEvent( this, mState ), pov );
555
556        return true;
557}
558
559//--------------------------------------------------------------------------------------------------//
560void Win32JoyStick::setBuffered(bool buffered)
561{
562        mBuffered = buffered;
563}
564
565//--------------------------------------------------------------------------------------------------//
566Interface* Win32JoyStick::queryInterface(Interface::IType type)
567{
568        if( mFfDevice && type == Interface::ForceFeedback )
569                return mFfDevice;
570        else
571                return 0;
572}
573
574//--------------------------------------------------------------------------------------------------//
575void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys)
576{
577    IWbemLocator*           pIWbemLocator  = NULL;
578    IEnumWbemClassObject*   pEnumDevices   = NULL;
579    IWbemClassObject*       pDevices[20]   = {0};
580    IWbemServices*          pIWbemServices = NULL;
581    BSTR                    bstrNamespace  = NULL;
582    BSTR                    bstrDeviceID   = NULL;
583    BSTR                    bstrClassName  = NULL;
584    DWORD                   uReturned      = 0;
585    bool                    bIsXinputDevice= false;
586        DWORD                   iDevice        = 0;
587        int                     xDevice        = 0;
588    VARIANT                 var;
589    HRESULT                 hr;
590
591        if(joys.size() == 0)
592                return;
593
594    // CoInit if needed
595    hr = CoInitialize(NULL);
596    bool bCleanupCOM = SUCCEEDED(hr);
597
598    // Create WMI
599    // (Orxonox): Fix for MinGW
600#ifdef __MINGW32__
601    hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator);
602#else
603    hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
604#endif
605    if( FAILED(hr) || pIWbemLocator == NULL )
606        goto LCleanup;
607
608    bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
609        if( bstrNamespace == NULL )
610                goto LCleanup;
611
612    bstrClassName = SysAllocString( L"Win32_PNPEntity" );
613        if( bstrClassName == NULL )
614                goto LCleanup;
615
616    bstrDeviceID  = SysAllocString( L"DeviceID" );
617        if( bstrDeviceID == NULL )
618                goto LCleanup;
619   
620    // Connect to WMI
621    hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
622    if( FAILED(hr) || pIWbemServices == NULL )
623        goto LCleanup;
624
625    // Switch security level to IMPERSONATE.
626    CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                   
627
628    hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices ); 
629    if( FAILED(hr) || pEnumDevices == NULL )
630        goto LCleanup;
631
632    // Loop over all devices
633    for( ;; )
634    {
635        // Get 20 at a time
636        hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned);
637        if( FAILED(hr) )
638            goto LCleanup;
639
640        if( uReturned == 0 )
641            break;
642
643        for(iDevice = 0; iDevice < uReturned; iDevice++)
644        {
645            // For each device, get its device ID
646            hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
647            if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
648            {
649                // Check if the device ID contains "IG_".  If it does, then it's an XInput device - This information can not be found from DirectInput
650                if(wcsstr(var.bstrVal, L"IG_"))
651                {
652                    // If it does, then get the VID/PID from var.bstrVal
653                    DWORD dwPid = 0, dwVid = 0;
654                    WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
655                    if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1)
656                                                dwVid = 0;
657
658                    WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
659                    if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1)
660                        dwPid = 0;
661
662                    // Compare the VID/PID to the DInput device
663                    DWORD dwVidPid = MAKELONG(dwVid, dwPid);
664                                        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
665                                        {
666                                                if(dwVidPid == i->productGuid.Data1)
667                                                {
668                                                        i->isXInput = true;
669                                                        i->xInputDev = xDevice;
670                                                }
671                                        }
672
673                                        if(joys.size() == 0)
674                                                goto LCleanup;
675                }
676            }
677
678            SAFE_RELEASE(pDevices[iDevice]);
679        }
680    }
681
682LCleanup:
683    if(bstrNamespace)
684        SysFreeString(bstrNamespace);
685
686    if(bstrDeviceID)
687        SysFreeString(bstrDeviceID);
688
689    if(bstrClassName)
690        SysFreeString(bstrClassName);
691
692    for(iDevice=0; iDevice < 20; iDevice++)
693        SAFE_RELEASE(pDevices[iDevice]);
694
695    SAFE_RELEASE(pEnumDevices);
696    SAFE_RELEASE(pIWbemLocator);
697    SAFE_RELEASE(pIWbemServices);
698
699    if(bCleanupCOM)
700        CoUninitialize();
701}
Note: See TracBrowser for help on using the repository browser.