00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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>
00034 #include <cassert>
00035 #include <linux/input.h>
00036
00037
00038 #include <sstream>
00039
00040 using namespace OIS;
00041
00042
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
00078 mState.mAxes.resize(mAxisMap.size());
00079 mState.clear();
00080
00081
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
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
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
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:
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
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:
00134 {
00135
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
00144 if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
00145 {
00146 mState.mAxes[axis].abs = js[i].value;
00147 }
00148 else
00149 {
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 )
00155 {
00156
00157
00158 unsigned char LinuxPovNumber = js[i].code - 16;
00159 short OIS_POVIndex = POV_MASK[LinuxPovNumber];
00160
00161
00162 if((LinuxPovNumber & 0x0001) == 0)
00163 {
00164
00165
00166
00167
00168 mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
00169 if( js[i].value == -1 )
00170 mState.mPOV[OIS_POVIndex].direction |= Pov::West;
00171 else if( js[i].value == 1 )
00172 mState.mPOV[OIS_POVIndex].direction |= Pov::East;
00173 }
00174
00175 else
00176 {
00177
00178 mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
00179 if( js[i].value == -1 )
00180 mState.mPOV[OIS_POVIndex].direction |= Pov::North;
00181 else if( js[i].value == 1 )
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
00192 case EV_REL:
00193 default: break;
00194 }
00195 }
00196
00197
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
00241
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 }