Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource2/src/ois/linux/LinuxJoyStickEvents.cpp @ 5669

Last change on this file since 5669 was 5668, checked in by rgrieder, 15 years ago

Updated OIS library (still 1.2, but CVS version).
There have been some little fixes and support for force feedback on Linux (but this doesn't concern us for now…)

  • Property svn:eol-style set to native
File size: 8.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 "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
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        int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
99        if( ret <= 0 )
100                return;
101
102        //Determine how many whole events re read up
103        ret /= sizeof(struct input_event);
104        for(int i = 0; i < ret; ++i)
105        {
106                switch(js[i].type)
107                {
108                case EV_KEY:  //Button
109                {
110                        int button = mButtonMap[js[i].code];
111
112                        #ifdef OIS_LINUX_JOY_DEBUG
113                          cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
114                        #endif
115
116                        //Check to see whether push or released event...
117                        if(js[i].value)
118                        {
119                                mState.mButtons[button] = true;
120                                if( mBuffered && mListener )
121                                        if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
122                        }
123                        else
124                        {
125                                mState.mButtons[button] = false;
126                                if( mBuffered && mListener )
127                                        if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
128                        }
129                        break;
130                }
131
132                case EV_ABS:  //Absolute Axis
133                {
134                        //A Stick (BrakeDefine is the highest possible Axis)
135                        if( js[i].code <= ABS_BRAKE )
136                        {
137                                int axis = mAxisMap[js[i].code];
138                                assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
139
140                                axisMoved[axis] = true;
141
142                                //check for rescaling:
143                                if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
144                                {       //Scale is perfect
145                                        mState.mAxes[axis].abs = js[i].value;
146                                }
147                                else
148                                {       //Rescale
149                                        float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
150                                        mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
151                                }
152                        }
153                        else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
154                        {
155                                //Normalise the POV to between 0-7
156                                //Even is X Axis, Odd is Y Axis
157                                unsigned char LinuxPovNumber = js[i].code - 16;
158                                short OIS_POVIndex = POV_MASK[LinuxPovNumber];
159
160                                //Handle X Axis first (Even) (left right)
161                                if((LinuxPovNumber & 0x0001) == 0)
162                                {
163                                        //Why do this? Because, we use a bit field, and when this axis is east,
164                                        //it can't possibly be west too. So clear out the two X axes, then refil
165                                        //it in with the new direction bit.
166                                        //Clear the East/West Bit Flags first
167                                        mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
168                                        if( js[i].value == -1 ) //Left
169                                                mState.mPOV[OIS_POVIndex].direction |= Pov::West;
170                                        else if( js[i].value == 1 ) //Right
171                                                mState.mPOV[OIS_POVIndex].direction |= Pov::East;
172                                }
173                                //Handle Y Axis (Odd) (up down)
174                                else
175                                {
176                                        //Clear the North/South Bit Flags first
177                                        mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
178                                        if( js[i].value == -1 ) //Up
179                                                mState.mPOV[OIS_POVIndex].direction |= Pov::North;
180                                        else if( js[i].value == 1 ) //Down
181                                                mState.mPOV[OIS_POVIndex].direction |= Pov::South;
182                                }
183
184                                if( mBuffered && mListener )
185                                        if( mListener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
186                                                return;
187                        }
188                        break;
189                }
190
191               
192                case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
193#ifdef OIS_LINUX_JOY_DEBUG
194                    cout << "\nWarning: Relatives axes not supported yet" << endl;
195#endif
196                        break;
197                default: break;
198                }
199        }
200
201        //All axes and POVs are combined into one movement per pair per captured frame
202        if( mBuffered && mListener )
203        {
204                for( int i = 0; i < 32; ++i )
205                        if( axisMoved[i] )
206                                if( mListener->axisMoved( JoyStickEvent(this,mState), i) == false )
207                                        return;
208        }
209}
210
211//-------------------------------------------------------------------//
212void LinuxJoyStick::setBuffered(bool buffered)
213{
214        if( buffered != mBuffered )
215        {
216                mBuffered = buffered;
217                _initialize();
218        }
219}
220
221//-------------------------------------------------------------------//
222JoyStickInfo LinuxJoyStick::_getJoyInfo()
223{
224        JoyStickInfo js;
225
226        js.devId = mDevID;
227        js.joyFileD = mJoyStick;
228        js.vendor = mVendor;
229        js.axes = (int)mState.mAxes.size();
230        js.buttons = (int)mState.mButtons.size();
231        js.hats = mPOVs;
232        js.button_map = mButtonMap;
233        js.axis_map = mAxisMap;
234        js.axis_range = mRanges;
235
236        return js;
237}
238
239//-------------------------------------------------------------------//
240JoyStickInfoList LinuxJoyStick::_scanJoys()
241{
242        JoyStickInfoList joys;
243
244        //Search through all of the event devices.. and identify which ones are joysticks
245        //xxx move this to InputManager, as it can also scan all other events
246        for(int i = 0; i < 64; ++i )
247        {
248                stringstream s;
249                s << "/dev/input/event" << i;
250                int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
251                if(fd == -1)
252                        continue;
253
254        #ifdef OIS_LINUX_JOY_DEBUG
255                  cout << "Opening " << s.str() << "..." << endl;
256        #endif
257                try
258                {
259                        JoyStickInfo js;
260                        if( EventUtils::isJoyStick(fd, js) )
261                        {
262                                joys.push_back(js);
263                #ifdef OIS_LINUX_JOY_DEBUG
264                  cout << "=> Joystick added to list." << endl;
265                #endif
266                        }
267                        else
268                        {
269                #ifdef OIS_LINUX_JOY_DEBUG
270                  cout << "=> Not a joystick." << endl;
271                #endif
272                                close(fd);
273                        }
274                }
275                catch(...)
276                {
277            #ifdef OIS_LINUX_JOY_DEBUG
278              cout << "Exception caught!!" << endl;
279            #endif
280                        close(fd);
281                }
282        }
283
284        return joys;
285}
286
287//-------------------------------------------------------------------//
288void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys)
289{
290        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
291                close(i->joyFileD);
292        joys.clear();
293}
294
295//-------------------------------------------------------------------//
296Interface* LinuxJoyStick::queryInterface(Interface::IType type)
297{
298        if( ff_effect && type == Interface::ForceFeedback )
299                return ff_effect;
300
301        return 0;
302}
Note: See TracBrowser for help on using the repository browser.