E:/Download/ois-1.0RC1/src/linux/LinuxJoyStickEvents.cpp

Go to the documentation of this file.
00001 /*
00002 The zlib/libpng License
00003 
00004 Copyright (c) 2006 Phillip Castaneda (pjcast -- www.wreckedgames.com)
00005 
00006 This software is provided 'as-is', without any express or implied warranty. In no event will
00007 the authors be held liable for any damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any purpose, including commercial
00010 applications, and to alter it and redistribute it freely, subject to the following
00011 restrictions:
00012 
00013     1. The origin of this software must not be misrepresented; you must not claim that
00014                 you wrote the original software. If you use this software in a product,
00015                 an acknowledgment in the product documentation would be appreciated but is
00016                 not required.
00017 
00018     2. Altered source versions must be plainly marked as such, and must not be
00019                 misrepresented as being the original software.
00020 
00021     3. This notice may not be removed or altered from any source distribution.
00022 */
00023 #include "OISConfig.h"
00024 
00025 #include "linux/LinuxJoyStickEvents.h"
00026 #include "linux/LinuxInputManager.h"
00027 #include "linux/LinuxForceFeedback.h"
00028 #include "linux/EventHelpers.h"
00029 
00030 #include "OISEvents.h"
00031 #include "OISException.h"
00032 
00033 #include <fcntl.h>        //Needed to Open a file descriptor
00034 #include <cassert>      
00035 #include <linux/input.h>
00036 
00037 
00038 #include <sstream>
00039 
00040 using namespace OIS;
00041 
00042 //#define OIS_LINUX_JOY_DEBUG
00043 
00044 #ifdef OIS_LINUX_JOY_DEBUG
00045 # include <iostream>
00046   using namespace std;
00047 #endif
00048 
00049 //-------------------------------------------------------------------//
00050 LinuxJoyStick::LinuxJoyStick(bool buffered, const JoyStickInfo& js)
00051 {
00052         mBuffered = buffered;
00053         mType = OISJoyStick;
00054 
00055         mDevID = js.devId;
00056         mJoyStick = js.joyFileD;
00057         mVendor = js.vendor;
00058         numAxes = js.axes;
00059         numButtons = js.buttons;
00060         numHats = js.hats;
00061         mButtonMap = js.button_map;
00062         mAxisMap = js.axis_map;
00063         mRanges = js.axis_range;
00064 
00065         ff_effect = 0;
00066 }
00067 
00068 //-------------------------------------------------------------------//
00069 LinuxJoyStick::~LinuxJoyStick()
00070 {
00071         EventUtils::removeForceFeedback( &ff_effect );
00072 }
00073 
00074 //-------------------------------------------------------------------//
00075 void LinuxJoyStick::_initialize()
00076 {
00077         //Clear old joy state
00078         mState.mAxes.resize(mAxisMap.size());
00079         mState.clear();
00080 
00081         //This will create and new us a force feedback structure if it exists
00082         EventUtils::enumerateForceFeedback( mJoyStick, &ff_effect );
00083 
00084         if( mJoyStick == -1 )
00085                 OIS_EXCEPT(E_InputDeviceNonExistant, "LinuxJoyStick::_initialize() >> JoyStick Not Found!");
00086 }
00087 
00088 //-------------------------------------------------------------------//
00089 void LinuxJoyStick::capture()
00090 {
00091         static const short POV_MASK[8] = {0,0,1,1,2,2,3,3};
00092 
00093         //Used to determine if an axis has been changed and needs an event
00094         bool axisMoved[32] = {false, false, false, false, false, false, false, false, false, false, false, false, false,
00095                                                   false, false, false, false, false, false, false, false, false, false, false, false, false,
00096                                                   false, false, false, false, false, false};
00097 
00098         //We are in non blocking mode - we just read once, and try to fill up buffer
00099         input_event js[JOY_BUFFERSIZE];
00100         int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
00101         if( ret <= 0 )
00102                 return;
00103 
00104         //Determine how many whole events re read up
00105         ret /= sizeof(struct input_event);
00106         for(int i = 0; i < ret; ++i)
00107         {
00108                 switch(js[i].type)
00109                 {
00110                 case EV_KEY:  //Button
00111                 {
00112                         int button = mButtonMap[js[i].code];
00113 
00114                         #ifdef OIS_LINUX_JOY_DEBUG
00115                           std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl;
00116                         #endif
00117 
00118                         //Check to see whether push or released event...
00119                         if(js[i].value)
00120                         {
00121                                 mState.buttons |= (1 << button);
00122                                 if( mBuffered && listener )
00123                                         if(!listener->buttonPressed(JoyStickEvent(this,mState), button)) return;
00124                         }
00125                         else
00126                         {
00127                                 mState.buttons &= ~(1 << button);
00128                                 if( mBuffered && listener )
00129                                         if(!listener->buttonReleased(JoyStickEvent(this,mState), button)) return;
00130                         }
00131                         break;
00132                 }
00133                 case EV_ABS:  //Absoulte Axis
00134                 {
00135                         //A Stick (BrakeDefine is the highest possible Axis)
00136                         if( js[i].code <= ABS_BRAKE )
00137                         {
00138                                 int axis = mAxisMap[js[i].code];
00139                                 assert( axis < 32 && "Too many axes, not supported. Report this to OIS forums!" );
00140                                 
00141                                 axisMoved[axis] = true;
00142 
00143                                 //check for rescaling:
00144                                 if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
00145                                 {       //Scale is perfect
00146                                         mState.mAxes[axis].abs = js[i].value;
00147                                 }
00148                                 else
00149                                 {       //Rescale
00150                                         float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
00151                                         mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
00152                                 }
00153                         }
00154                         else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
00155                         {
00156                                 //Normalise the POV to between 0-7
00157                                 //Even is X Axis, Odd is Y Axis
00158                                 unsigned char LinuxPovNumber = js[i].code - 16;
00159                                 short OIS_POVIndex = POV_MASK[LinuxPovNumber];
00160 
00161                                 //Handle X Axis first (Even) (left right)
00162                                 if((LinuxPovNumber & 0x0001) == 0)
00163                                 {
00164                                         //Why do this? Because, we use a bit field, and when this axis is east,
00165                                         //it can't possibly be west too. So clear out the two X axes, then refil
00166                                         //it in with the new direction bit.
00167                                         //Clear the East/West Bit Flags first
00168                                         mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
00169                                         if( js[i].value == -1 ) //Left
00170                                                 mState.mPOV[OIS_POVIndex].direction |= Pov::West;
00171                                         else if( js[i].value == 1 ) //Right
00172                                                 mState.mPOV[OIS_POVIndex].direction |= Pov::East;
00173                                 }
00174                                 //Handle Y Axis (Odd) (up down)
00175                                 else
00176                                 {
00177                                         //Clear the North/South Bit Flags first
00178                                         mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
00179                                         if( js[i].value == -1 ) //Up
00180                                                 mState.mPOV[OIS_POVIndex].direction |= Pov::North;
00181                                         else if( js[i].value == 1 ) //Down
00182                                                 mState.mPOV[OIS_POVIndex].direction |= Pov::South;
00183                                 }
00184 
00185                                 if( mBuffered && listener )
00186                                         if( listener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
00187                                                 return;
00188                         }
00189                         break;
00190                 }
00191                 //Relative Axes (Do any joysticks actually have a relative axis?)
00192                 case EV_REL:
00193                 default: break;
00194                 }
00195         }
00196 
00197         //All axes and POVs are combined into one movement per pair per captured frame
00198         if( mBuffered && listener )
00199         {
00200                 for( int i = 0; i < 32; ++i )
00201                         if( axisMoved[i] )
00202                                 if( listener->axisMoved( JoyStickEvent(this,mState), i) == false )
00203                                         return;
00204         }
00205 }
00206 
00207 //-------------------------------------------------------------------//
00208 void LinuxJoyStick::setBuffered(bool buffered)
00209 {
00210         if( buffered != mBuffered )
00211         {
00212                 mBuffered = buffered;
00213                 _initialize();
00214         }
00215 }
00216 
00217 //-------------------------------------------------------------------//
00218 JoyStickInfo LinuxJoyStick::_getJoyInfo()
00219 {
00220         JoyStickInfo js;
00221 
00222         js.devId = mDevID;
00223         js.joyFileD = mJoyStick;
00224         js.vendor = mVendor;
00225         js.axes = numAxes;
00226         js.buttons = numButtons;
00227         js.hats = numHats;
00228         js.button_map = mButtonMap;
00229         js.axis_map = mAxisMap;
00230         js.axis_range = mRanges;
00231 
00232         return js;
00233 }
00234 
00235 //-------------------------------------------------------------------//
00236 JoyStickInfoList LinuxJoyStick::_scanJoys()
00237 {
00238         JoyStickInfoList joys;
00239 
00240         //Search through all of the event devices.. and identify which ones are joysticks
00241         //xxx move this to InputManager, as it can also scan all other events
00242         for(int i = 0; i < 32; ++i )
00243         {
00244                 std::stringstream s;
00245                 s << "/dev/input/event" << i;
00246                 int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK );
00247         #ifdef OIS_LINUX_JOY_DEBUG
00248           std::cout << "\nOpening " << s.str() << "...";
00249         #endif
00250                 try
00251                 {
00252                         JoyStickInfo js;
00253                         if( EventUtils::isJoyStick(fd, js) )
00254                         {
00255                                 joys.push_back(js);
00256                 #ifdef OIS_LINUX_JOY_DEBUG
00257                   std::cout << "\n__Joystick added to list";
00258                 #endif
00259                         }
00260                         else
00261                         {
00262                 #ifdef OIS_LINUX_JOY_DEBUG
00263                   std::cout << "\n__Not a joystick!!";
00264                 #endif
00265                                 close(fd);
00266                         }
00267                 }
00268                 catch(...)
00269                 {
00270             #ifdef OIS_LINUX_JOY_DEBUG
00271               std::cout << "\nException caught!!";
00272             #endif
00273                         close(fd);
00274                 }
00275         }
00276 
00277         return joys;
00278 }
00279 
00280 //-------------------------------------------------------------------//
00281 void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys)
00282 {
00283         for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
00284                 close(i->joyFileD);
00285         joys.clear();
00286 }
00287 
00288 //-------------------------------------------------------------------//
00289 Interface* LinuxJoyStick::queryInterface(Interface::IType type)
00290 {
00291         if( ff_effect && type == Interface::ForceFeedback )
00292                 return ff_effect;
00293 
00294         return 0;
00295 }

Generated on Sat Dec 1 20:13:51 2007 for OIS by  doxygen 1.5.4