Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10980 was 9674, checked in by landauf, 11 years ago

fixed build for MinGW with GCC 4.6

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