E:/Download/ois-1.0RC1/src/linux/EventHelpers.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 "linux/EventHelpers.h"
00024 #include "linux/LinuxPrereqs.h"
00025 #include "linux/LinuxForceFeedback.h"
00026 #include "OISException.h"
00027 #include "OISJoyStick.h"
00028 
00029 #include <linux/input.h>
00030 
00031 //#define OIS_LINUX_JOY_DEBUG
00032 
00033 #ifdef OIS_LINUX_JOY_DEBUG
00034 # include <iostream>
00035   using namespace std;
00036 #endif
00037 
00038 using namespace OIS;
00039 
00040 struct DeviceComponentInfo
00041 {
00042         std::vector<int> buttons, relAxes, absAxes, hats;
00043 };
00044 
00045 bool inline isBitSet(unsigned long bits[], unsigned int bit)
00046 {
00047         return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1;
00048 }
00049 //-----------------------------------------------------------------------------//
00050 DeviceComponentInfo getComponentInfo( int deviceID )
00051 {
00052         unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1];
00053         memset( info, 0, sizeof(info) );
00054 
00055         DeviceComponentInfo components;
00056 
00057         //Read "all" (hence 0) components of the device - read into first entry
00058         ioctl(deviceID, EVIOCGBIT(0, EV_MAX), info[0]);
00059 
00060         for (int i = 0; i < EV_MAX; i++)
00061         {
00062                 if( isBitSet(info[0], i) )
00063                 {
00064                         memset( info[1], 0, sizeof(info) / 2 );
00065                         ioctl(deviceID, EVIOCGBIT(i, KEY_MAX), info[1]);
00066                         for (int j = 0; j < KEY_MAX; j++)
00067                         {
00068                                 if( isBitSet(info[1], j) )
00069                                 {
00070                                         if(i == EV_ABS)
00071                                         {
00072                                                 //input_absinfo abInfo;
00073                                                 //ioctl( fd, EVIOCGABS(j), abInfo );
00074                                                 if( j >= ABS_HAT0X && j <= ABS_HAT3Y )
00075                                                 {
00076                                                         components.hats.push_back(j);
00077                                                 }
00078                                                 else
00079                                                 {
00080                                                         components.absAxes.push_back(j);
00081                                                         //input_absinfo absinfo;
00082                                                         //ioctl(deviceID, EVIOCGABS(j), &absinfo);
00083                                                         //We cannot actually change these values :|
00084                                                         //absinfo.minimum = JoyStick::MIN_AXIS;
00085                                                         //absinfo.maximum = JoyStick::MAX_AXIS;
00086                                                         //ioctl(deviceID, EVIOCSABS(j), &absinfo);
00087                                                 }
00088                                         }
00089                                         else if(i == EV_REL)
00090                                         {
00091                                                 components.relAxes.push_back(j);
00092                                         }
00093                                         else if(i == EV_KEY)
00094                                         {
00095                                                 components.buttons.push_back(j);
00096                                         }
00097                                 }
00098                         }
00099                 }
00100         }
00101 
00102         return components;
00103 }
00104 
00105 //-----------------------------------------------------------------------------//
00106 bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
00107 {
00108         if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" );
00109 
00110         DeviceComponentInfo info = getComponentInfo( deviceID );
00111 
00112         int buttons = 0;
00113         bool joyButtonFound = false;
00114         js.button_map.clear();
00115 
00116         #ifdef OIS_LINUX_JOY_DEBUG
00117           cout << "\n\nDisplaying ButtonMapping Status:";
00118         #endif
00119         for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
00120         {
00121                 //Check to ensure we find at least one joy only button
00122                 if( (*i >= BTN_JOYSTICK && *i <= BTN_THUMBR) || (*i >= BTN_WHEEL && *i <= BTN_GEAR_UP ) )
00123                         joyButtonFound = true;
00124 
00125                 js.button_map[*i] = buttons++;
00126 
00127                 #ifdef OIS_LINUX_JOY_DEBUG
00128                   cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1);
00129                 #endif
00130         }
00131 
00132         //Joy Buttons found, so it must be a joystick or pad
00133         if( joyButtonFound )
00134         {
00135                 js.joyFileD = deviceID;
00136                 js.vendor = getName(deviceID);
00137                 js.buttons = buttons;
00138                 js.axes = info.relAxes.size() + info.absAxes.size();
00139                 js.hats = info.hats.size();
00140 
00141                 //Map the Axes
00142                 #ifdef OIS_LINUX_JOY_DEBUG
00143                   cout << "\n\nDisplaying AxisMapping Status:";
00144                 #endif
00145                 int axes = 0;
00146                 for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
00147                 {
00148                         js.axis_map[*i] = axes;
00149 
00150                         input_absinfo absinfo;
00151                         ioctl(deviceID, EVIOCGABS(*i), &absinfo);
00152                         js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
00153 
00154                         #ifdef OIS_LINUX_JOY_DEBUG
00155                           cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes;
00156                         #endif
00157 
00158                         ++axes;
00159                 }
00160         }
00161 
00162         return joyButtonFound;
00163 }
00164 
00165 //-----------------------------------------------------------------------------//
00166 std::string EventUtils::getName( int deviceID )
00167 {
00168         char name[OIS_DEVICE_NAME];
00169         ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name);
00170         return std::string(name);
00171 }
00172 
00173 //-----------------------------------------------------------------------------//
00174 void EventUtils::enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff )
00175 {
00176         //Linux Event to OIS Event Mappings
00177         std::map<int, Effect::EType> typeMap;
00178         typeMap[FF_CONSTANT] = Effect::Constant;
00179         typeMap[FF_RAMP]     = Effect::Ramp;
00180         typeMap[FF_SPRING]   = Effect::Spring;
00181         typeMap[FF_FRICTION] = Effect::Friction;
00182         typeMap[FF_SQUARE]   = Effect::Square;
00183         typeMap[FF_TRIANGLE] = Effect::Triangle;
00184         typeMap[FF_SINE]     = Effect::Sine;
00185         typeMap[FF_SAW_UP]   = Effect::SawToothUp;
00186         typeMap[FF_SAW_DOWN] = Effect::SawToothDown;
00187         typeMap[FF_DAMPER]   = Effect::Damper;
00188         typeMap[FF_INERTIA]  = Effect::Inertia;
00189         typeMap[FF_CUSTOM]   = Effect::Custom;
00190 
00191         std::map<int, Effect::EForce> forceMap;
00192         forceMap[FF_CONSTANT] = Effect::ConstantForce;
00193         forceMap[FF_RAMP] = Effect::RampForce;
00194         forceMap[FF_PERIODIC] = Effect::PeriodicForce;
00195         forceMap[FF_CUSTOM] = Effect::CustomForce;
00196 
00197         //Remove any previously existing memory and create fresh
00198         removeForceFeedback( ff );
00199         *ff = new LinuxForceFeedback();
00200 
00201         unsigned long info[4] = {0,0,0,0};
00202         unsigned long subinfo[4]= {0,0,0,0};
00203 
00204         //Read overall force feedback components of the device
00205         ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(long)*4), info);
00206 
00207         //FF Axes
00208         //if( isBitSet(info, ABS_X) ) //X Axis
00209         //if( isBitSet(info, ABS_Y) ) //Y Axis
00210         //if( isBitSet(info, ABS_WHEEL) ) //Wheel
00211 
00212         //FF Effects
00213         for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ )
00214         {
00215                 if(isBitSet(info, effect))
00216                 {
00217                         //std::cout << "\tEffect Type: " << effect << std::endl;
00218                         memset(subinfo, 0, sizeof(subinfo));
00219                         //Read any info about this supported effect
00220                         ioctl(deviceID, EVIOCGBIT(effect, sizeof(long)*4), subinfo);
00221                         for( int force = 0; force < FF_MAX; force++ )
00222                         {
00223                                 if(isBitSet(subinfo, force))
00224                                         (*ff)->_addEffectTypes( forceMap[force], typeMap[effect] );
00225                         }
00226                 }
00227         }
00228 
00229         //Check to see if any effects were added, else destroy the pointer
00230         const ForceFeedback::SupportedEffectList &list = (*ff)->getSupportedEffects();
00231         if( list.size() == 0 )
00232                 removeForceFeedback( ff );
00233 }
00234 
00235 //-----------------------------------------------------------------------------//
00236 void EventUtils::removeForceFeedback( LinuxForceFeedback** ff )
00237 {
00238         delete *ff;
00239         *ff = 0;
00240 }

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