Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/ois/linux/LinuxJoyStickEvents.cpp @ 12064

Last change on this file since 12064 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 8.5 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 "OISConfig.h"
24
25#include "linux/LinuxJoyStickEvents.h"
26#include "linux/LinuxInputManager.h"
27#include "linux/LinuxForceFeedback.h"
28#include "linux/EventHelpers.h"
29
30#include "OISEvents.h"
31#include "OISException.h"
32
33#include <fcntl.h>        //Needed to Open a file descriptor
34#include <cassert>      
35#include <linux/input.h>
36#include <unistd.h>
37
38#include <sstream>
39# include <iostream>
40using namespace std;
41
42using namespace OIS;
43
44//#define OIS_LINUX_JOY_DEBUG
45
46//-------------------------------------------------------------------//
47LinuxJoyStick::LinuxJoyStick(InputManager* creator, bool buffered, const JoyStickInfo& js)
48        : JoyStick(js.vendor, buffered, js.devId, creator)
49{
50        mJoyStick = js.joyFileD;
51
52        mState.mAxes.clear();
53        mState.mAxes.resize(js.axes);
54        mState.mButtons.clear();
55        mState.mButtons.resize(js.buttons);
56
57        mPOVs = js.hats;
58
59        mButtonMap = js.button_map;
60        mAxisMap = js.axis_map;
61        mRanges = js.axis_range;
62
63        ff_effect = 0;
64}
65
66//-------------------------------------------------------------------//
67LinuxJoyStick::~LinuxJoyStick()
68{
69        EventUtils::removeForceFeedback( &ff_effect );
70}
71
72//-------------------------------------------------------------------//
73void LinuxJoyStick::_initialize()
74{
75        //Clear old joy state
76        mState.mAxes.resize(mAxisMap.size());
77        mState.clear();
78
79        //This will create and new us a force feedback structure if it exists
80        EventUtils::enumerateForceFeedback( mJoyStick, &ff_effect );
81
82        if( mJoyStick == -1 )
83                OIS_EXCEPT(E_InputDeviceNonExistant, "LinuxJoyStick::_initialize() >> JoyStick Not Found!");
84}
85
86//-------------------------------------------------------------------//
87void LinuxJoyStick::capture()
88{
89        static const short POV_MASK[8] = {0,0,1,1,2,2,3,3};
90
91        //Used to determine if an axis has been changed and needs an event
92        bool axisMoved[32] = {false, false, false, false, false, false, false, false, false, false, false, false, false,
93                                                  false, false, false, false, false, false, false, false, false, false, false, false, false,
94                                                  false, false, false, false, false, false};
95
96        //We are in non blocking mode - we just read once, and try to fill up buffer
97        input_event js[JOY_BUFFERSIZE];
98        while(true)
99        {
100                int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
101        if( ret < 0 )
102                        break;
103
104                //Determine how many whole events re read up
105                ret /= sizeof(struct input_event);
106                for(int i = 0; i < ret; ++i)
107                {
108                        switch(js[i].type)
109                        {
110                        case EV_KEY:  //Button
111                        {
112                                int button = mButtonMap[js[i].code];
113
114                                #ifdef OIS_LINUX_JOY_DEBUG
115                                  cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
116                                #endif
117
118                                //Check to see whether push or released event...
119                                if(js[i].value)
120                                {
121                                        mState.mButtons[button] = true;
122                                        if( mBuffered && mListener )
123                                                if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
124                                }
125                                else
126                                {
127                                        mState.mButtons[button] = false;
128                                        if( mBuffered && mListener )
129                                                if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
130                                }
131                                break;
132                        }
133
134                        case EV_ABS:  //Absolute Axis
135                        {
136                                //A Stick (BrakeDefine is the highest possible Axis)
137                                if( js[i].code <= ABS_BRAKE )
138                                {
139                                        int axis = mAxisMap[js[i].code];
140                                        assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
141
142                                        axisMoved[axis] = true;
143
144                                        //check for rescaling:
145                                        if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
146                                        {       //Scale is perfect
147                                                mState.mAxes[axis].abs = js[i].value;
148                                        }
149                                        else
150                                        {       //Rescale
151                                                float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
152                                                mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
153                                        }
154                                }
155                                else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
156                                {
157                                        //Normalise the POV to between 0-7
158                                        //Even is X Axis, Odd is Y Axis
159                                        unsigned char LinuxPovNumber = js[i].code - 16;
160                                        short OIS_POVIndex = POV_MASK[LinuxPovNumber];
161
162                                        //Handle X Axis first (Even) (left right)
163                                        if((LinuxPovNumber & 0x0001) == 0)
164                                        {
165                                                //Why do this? Because, we use a bit field, and when this axis is east,
166                                                //it can't possibly be west too. So clear out the two X axes, then refil
167                                                //it in with the new direction bit.
168                                                //Clear the East/West Bit Flags first
169                                                mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
170                                                if( js[i].value == -1 ) //Left
171                                                        mState.mPOV[OIS_POVIndex].direction |= Pov::West;
172                                                else if( js[i].value == 1 ) //Right
173                                                        mState.mPOV[OIS_POVIndex].direction |= Pov::East;
174                                        }
175                                        //Handle Y Axis (Odd) (up down)
176                                        else
177                                        {
178                                                //Clear the North/South Bit Flags first
179                                                mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
180                                                if( js[i].value == -1 ) //Up
181                                                        mState.mPOV[OIS_POVIndex].direction |= Pov::North;
182                                                else if( js[i].value == 1 ) //Down
183                                                        mState.mPOV[OIS_POVIndex].direction |= Pov::South;
184                                        }
185
186                                        if( mBuffered && mListener )
187                                                if( mListener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
188                                                        return;
189                                }
190                                break;
191                        }
192
193                       
194                        case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
195        #ifdef OIS_LINUX_JOY_DEBUG
196                                cout << "\nWarning: Relatives axes not supported yet" << endl;
197        #endif
198                                break;
199                        default: break;
200                        }
201                }
202        }
203
204        //All axes and POVs are combined into one movement per pair per captured frame
205        if( mBuffered && mListener )
206        {
207                for( int i = 0; i < 32; ++i )
208                        if( axisMoved[i] )
209                                if( mListener->axisMoved( JoyStickEvent(this,mState), i) == false )
210                                        return;
211        }
212}
213
214//-------------------------------------------------------------------//
215void LinuxJoyStick::setBuffered(bool buffered)
216{
217        if( buffered != mBuffered )
218        {
219                mBuffered = buffered;
220                _initialize();
221        }
222}
223
224//-------------------------------------------------------------------//
225JoyStickInfo LinuxJoyStick::_getJoyInfo()
226{
227        JoyStickInfo js;
228
229        js.devId = mDevID;
230        js.joyFileD = mJoyStick;
231        js.vendor = mVendor;
232        js.axes = (int)mState.mAxes.size();
233        js.buttons = (int)mState.mButtons.size();
234        js.hats = mPOVs;
235        js.button_map = mButtonMap;
236        js.axis_map = mAxisMap;
237        js.axis_range = mRanges;
238
239        return js;
240}
241
242//-------------------------------------------------------------------//
243JoyStickInfoList LinuxJoyStick::_scanJoys()
244{
245        JoyStickInfoList joys;
246
247        //Search through all of the event devices.. and identify which ones are joysticks
248        //xxx move this to InputManager, as it can also scan all other events
249        for(int i = 0; i < 64; ++i )
250        {
251                stringstream s;
252                s << "/dev/input/event" << i;
253                int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
254                if(fd == -1)
255                        continue;
256
257        #ifdef OIS_LINUX_JOY_DEBUG
258                  cout << "Opening " << s.str() << "..." << endl;
259        #endif
260                try
261                {
262                        JoyStickInfo js;
263                        if( EventUtils::isJoyStick(fd, js) )
264                        {
265                                joys.push_back(js);
266                #ifdef OIS_LINUX_JOY_DEBUG
267                  cout << "=> Joystick added to list." << endl;
268                #endif
269                        }
270                        else
271                        {
272                #ifdef OIS_LINUX_JOY_DEBUG
273                  cout << "=> Not a joystick." << endl;
274                #endif
275                                close(fd);
276                        }
277                }
278                catch(...)
279                {
280            #ifdef OIS_LINUX_JOY_DEBUG
281              cout << "Exception caught!!" << endl;
282            #endif
283                        close(fd);
284                }
285        }
286
287        return joys;
288}
289
290//-------------------------------------------------------------------//
291void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys)
292{
293        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
294                close(i->joyFileD);
295        joys.clear();
296}
297
298//-------------------------------------------------------------------//
299Interface* LinuxJoyStick::queryInterface(Interface::IType type)
300{
301        if( ff_effect && type == Interface::ForceFeedback )
302                return ff_effect;
303
304        return 0;
305}
Note: See TracBrowser for help on using the repository browser.