Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/script_trigger/src/ois/linux/LinuxJoyStickEvents.cpp @ 2109

Last change on this file since 2109 was 1219, checked in by rgrieder, 17 years ago

merged input branch back to trunk. Not yet tested on tardis

File size: 8.6 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
40using namespace OIS;
41
42//#define OIS_LINUX_JOY_DEBUG
43
44#ifdef OIS_LINUX_JOY_DEBUG
45# include <iostream>
46  using namespace std;
47#endif
48
49//-------------------------------------------------------------------//
50LinuxJoyStick::LinuxJoyStick(InputManager* creator, bool buffered, const JoyStickInfo& js)
51        : JoyStick(js.vendor, buffered, js.devId, creator)
52{
53        mJoyStick = js.joyFileD;
54
55        mState.mAxes.clear();
56        mState.mAxes.resize(js.axes);
57        mState.mButtons.clear();
58        mState.mButtons.resize(js.buttons);
59
60        mPOVs = js.hats;
61
62        mButtonMap = js.button_map;
63        mAxisMap = js.axis_map;
64        mRanges = js.axis_range;
65
66        ff_effect = 0;
67}
68
69//-------------------------------------------------------------------//
70LinuxJoyStick::~LinuxJoyStick()
71{
72        EventUtils::removeForceFeedback( &ff_effect );
73}
74
75//-------------------------------------------------------------------//
76void LinuxJoyStick::_initialize()
77{
78        //Clear old joy state
79        mState.mAxes.resize(mAxisMap.size());
80        mState.clear();
81
82        //This will create and new us a force feedback structure if it exists
83        EventUtils::enumerateForceFeedback( mJoyStick, &ff_effect );
84
85        if( mJoyStick == -1 )
86                OIS_EXCEPT(E_InputDeviceNonExistant, "LinuxJoyStick::_initialize() >> JoyStick Not Found!");
87}
88
89//-------------------------------------------------------------------//
90void LinuxJoyStick::capture()
91{
92        static const short POV_MASK[8] = {0,0,1,1,2,2,3,3};
93
94        //Used to determine if an axis has been changed and needs an event
95        bool axisMoved[32] = {false, false, false, false, false, false, false, false, false, false, false, false, false,
96                                                  false, false, false, false, false, false, false, false, false, false, false, false, false,
97                                                  false, false, false, false, false, false};
98
99        //We are in non blocking mode - we just read once, and try to fill up buffer
100        input_event js[JOY_BUFFERSIZE];
101        int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
102        if( ret <= 0 )
103                return;
104
105        //Determine how many whole events re read up
106        ret /= sizeof(struct input_event);
107        for(int i = 0; i < ret; ++i)
108        {
109                switch(js[i].type)
110                {
111                case EV_KEY:  //Button
112                {
113                        int button = mButtonMap[js[i].code];
114
115                        #ifdef OIS_LINUX_JOY_DEBUG
116                          std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl;
117                        #endif
118
119                        //Check to see whether push or released event...
120                        if(js[i].value)
121                        {
122                                mState.mButtons[button] = true;
123                                if( mBuffered && mListener )
124                                        if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
125                        }
126                        else
127                        {
128                                mState.mButtons[button] = false;
129                                if( mBuffered && mListener )
130                                        if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
131                        }
132                        break;
133                }
134                case EV_ABS:  //Absoulte 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, not supported. 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                //Relative Axes (Do any joysticks actually have a relative axis?)
193                case EV_REL:
194                default: break;
195                }
196        }
197
198        //All axes and POVs are combined into one movement per pair per captured frame
199        if( mBuffered && mListener )
200        {
201                for( int i = 0; i < 32; ++i )
202                        if( axisMoved[i] )
203                                if( mListener->axisMoved( JoyStickEvent(this,mState), i) == false )
204                                        return;
205        }
206}
207
208//-------------------------------------------------------------------//
209void LinuxJoyStick::setBuffered(bool buffered)
210{
211        if( buffered != mBuffered )
212        {
213                mBuffered = buffered;
214                _initialize();
215        }
216}
217
218//-------------------------------------------------------------------//
219JoyStickInfo LinuxJoyStick::_getJoyInfo()
220{
221        JoyStickInfo js;
222
223        js.devId = mDevID;
224        js.joyFileD = mJoyStick;
225        js.vendor = mVendor;
226        js.axes = (int)mState.mAxes.size();
227        js.buttons = (int)mState.mButtons.size();
228        js.hats = mPOVs;
229        js.button_map = mButtonMap;
230        js.axis_map = mAxisMap;
231        js.axis_range = mRanges;
232
233        return js;
234}
235
236//-------------------------------------------------------------------//
237JoyStickInfoList LinuxJoyStick::_scanJoys()
238{
239        JoyStickInfoList joys;
240
241        //Search through all of the event devices.. and identify which ones are joysticks
242        //xxx move this to InputManager, as it can also scan all other events
243        for(int i = 0; i < 64; ++i )
244        {
245                std::stringstream s;
246                s << "/dev/input/event" << i;
247                int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK );
248                if(fd == -1)
249                        continue;
250               
251        #ifdef OIS_LINUX_JOY_DEBUG
252          std::cout << "\nOpening " << s.str() << "...";
253        #endif
254                try
255                {
256                        JoyStickInfo js;
257                        if( EventUtils::isJoyStick(fd, js) )
258                        {
259                                joys.push_back(js);
260                #ifdef OIS_LINUX_JOY_DEBUG
261                  std::cout << "\n__Joystick added to list";
262                #endif
263                        }
264                        else
265                        {
266                #ifdef OIS_LINUX_JOY_DEBUG
267                  std::cout << "\n__Not a joystick!!";
268                #endif
269                                close(fd);
270                        }
271                }
272                catch(...)
273                {
274            #ifdef OIS_LINUX_JOY_DEBUG
275              std::cout << "\nException caught!!";
276            #endif
277                        close(fd);
278                }
279        }
280
281        return joys;
282}
283
284//-------------------------------------------------------------------//
285void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys)
286{
287        for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
288                close(i->joyFileD);
289        joys.clear();
290}
291
292//-------------------------------------------------------------------//
293Interface* LinuxJoyStick::queryInterface(Interface::IType type)
294{
295        if( ff_effect && type == Interface::ForceFeedback )
296                return ff_effect;
297
298        return 0;
299}
Note: See TracBrowser for help on using the repository browser.