Wrecked Games
September 05, 2010, 03:50:02 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: We're just that awesome.
 
   Home   Help Search Members Login Register  
Pages: [1]
  Print  
Author Topic: [PATCH] Linux: don't drop joystick events  (Read 122 times)
mfranz
Newbie
*
Posts: 5


View Profile
« on: July 21, 2010, 08:54:28 AM »

Under Linux OIS drops joystick events! This is especially annoying when a button press event is evaluated, but the respective release is dropped, in which case that button gets stuck. But it also makes axis input sluggish.

The bug is that OIS doesn't follow the described practice from the Linux documentation, which demands that the input buffer always gets fully emptied, which is signaled by return value -1 from read(). Increasing the input buffer doesn't hurt either. The kernel's input buffer has room for 64 events ATM, and that's only 1536 bytes in a 64 bit system.

The buffer should really get allocated in the constructor to avoid needless memory fragmentation. I left that as it is because getting patches in seems next to impossible already now, and the shorter the better. (Is OIS even still maintained?! It sure doesn't look like it!)


Code:
Index: includes/linux/LinuxPrereqs.h
===================================================================
--- includes/linux/LinuxPrereqs.h       (revision 13)
+++ includes/linux/LinuxPrereqs.h       (working copy)
@@ -31,7 +31,7 @@
 #include "OISPrereqs.h"
 
 //! Max number of elements to collect from buffered input
-#define JOY_BUFFERSIZE 10
+#define JOY_BUFFERSIZE 64
 
 namespace OIS
 {


The following patch is not to be committed. It was done with diff -uw to ignore all white-space changes, so that you can see it's really trivial. See below for the actual patch.

Code:
Index: src/linux/LinuxJoyStickEvents.cpp
===================================================================
--- src/linux/LinuxJoyStickEvents.cpp   (revision 13)
+++ src/linux/LinuxJoyStickEvents.cpp   (working copy)
@@ -95,9 +95,10 @@
 
        //We are in non blocking mode - we just read once, and try to fill up buffer
        input_event js[JOY_BUFFERSIZE];
+       while(1) {
        int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
-       if( ret <= 0 )
-               return;
+               if( ret < 0 )
+                       break;
 
        //Determine how many whole events re read up
        ret /= sizeof(struct input_event);
@@ -197,6 +198,7 @@
                default: break;
                }
        }
+       }
 
        //All axes and POVs are combined into one movement per pair per captured frame
        if( mBuffered && mListener )



Here's the full patch. It's only big because of the changed indentation.

Code:
Index: includes/linux/LinuxPrereqs.h
===================================================================
--- includes/linux/LinuxPrereqs.h (revision 13)
+++ includes/linux/LinuxPrereqs.h (working copy)
@@ -31,7 +31,7 @@
 #include "OISPrereqs.h"
 
 //! Max number of elements to collect from buffered input
-#define JOY_BUFFERSIZE 10
+#define JOY_BUFFERSIZE 64
 
 namespace OIS
 {
Index: src/linux/LinuxJoyStickEvents.cpp
===================================================================
--- src/linux/LinuxJoyStickEvents.cpp (revision 13)
+++ src/linux/LinuxJoyStickEvents.cpp (working copy)
@@ -95,107 +95,109 @@
 
  //We are in non blocking mode - we just read once, and try to fill up buffer
  input_event js[JOY_BUFFERSIZE];
- int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
- if( ret <= 0 )
- return;
+ while(1) {
+ int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
+ if( ret < 0 )
+ break;
 
- //Determine how many whole events re read up
- ret /= sizeof(struct input_event);
- for(int i = 0; i < ret; ++i)
- {
- switch(js[i].type)
+ //Determine how many whole events re read up
+ ret /= sizeof(struct input_event);
+ for(int i = 0; i < ret; ++i)
  {
- case EV_KEY:  //Button
- {
- int button = mButtonMap[js[i].code];
-
- #ifdef OIS_LINUX_JOY_DEBUG
-   cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
- #endif
-
- //Check to see whether push or released event...
- if(js[i].value)
+ switch(js[i].type)
  {
- mState.mButtons[button] = true;
- if( mBuffered && mListener )
- if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
- }
- else
+ case EV_KEY:  //Button
  {
- mState.mButtons[button] = false;
- if( mBuffered && mListener )
- if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
- }
- break;
- }
+ int button = mButtonMap[js[i].code];
 
- case EV_ABS:  //Absolute Axis
- {
- //A Stick (BrakeDefine is the highest possible Axis)
- if( js[i].code <= ABS_BRAKE )
- {
- int axis = mAxisMap[js[i].code];
- assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
+ #ifdef OIS_LINUX_JOY_DEBUG
+   cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
+ #endif
 
- axisMoved[axis] = true;
-
- //check for rescaling:
- if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
- { //Scale is perfect
- mState.mAxes[axis].abs = js[i].value;
+ //Check to see whether push or released event...
+ if(js[i].value)
+ {
+ mState.mButtons[button] = true;
+ if( mBuffered && mListener )
+ if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
  }
  else
- { //Rescale
- float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
- mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
+ {
+ mState.mButtons[button] = false;
+ if( mBuffered && mListener )
+ if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
  }
+ break;
  }
- else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
+
+ case EV_ABS:  //Absolute Axis
  {
- //Normalise the POV to between 0-7
- //Even is X Axis, Odd is Y Axis
- unsigned char LinuxPovNumber = js[i].code - 16;
- short OIS_POVIndex = POV_MASK[LinuxPovNumber];
+ //A Stick (BrakeDefine is the highest possible Axis)
+ if( js[i].code <= ABS_BRAKE )
+ {
+ int axis = mAxisMap[js[i].code];
+ assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
 
- //Handle X Axis first (Even) (left right)
- if((LinuxPovNumber & 0x0001) == 0)
- {
- //Why do this? Because, we use a bit field, and when this axis is east,
- //it can't possibly be west too. So clear out the two X axes, then refil
- //it in with the new direction bit.
- //Clear the East/West Bit Flags first
- mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
- if( js[i].value == -1 ) //Left
- mState.mPOV[OIS_POVIndex].direction |= Pov::West;
- else if( js[i].value == 1 ) //Right
- mState.mPOV[OIS_POVIndex].direction |= Pov::East;
+ axisMoved[axis] = true;
+
+ //check for rescaling:
+ if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
+ { //Scale is perfect
+ mState.mAxes[axis].abs = js[i].value;
+ }
+ else
+ { //Rescale
+ float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
+ mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
+ }
  }
- //Handle Y Axis (Odd) (up down)
- else
+ else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
  {
- //Clear the North/South Bit Flags first
- mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
- if( js[i].value == -1 ) //Up
- mState.mPOV[OIS_POVIndex].direction |= Pov::North;
- else if( js[i].value == 1 ) //Down
- mState.mPOV[OIS_POVIndex].direction |= Pov::South;
+ //Normalise the POV to between 0-7
+ //Even is X Axis, Odd is Y Axis
+ unsigned char LinuxPovNumber = js[i].code - 16;
+ short OIS_POVIndex = POV_MASK[LinuxPovNumber];
+
+ //Handle X Axis first (Even) (left right)
+ if((LinuxPovNumber & 0x0001) == 0)
+ {
+ //Why do this? Because, we use a bit field, and when this axis is east,
+ //it can't possibly be west too. So clear out the two X axes, then refil
+ //it in with the new direction bit.
+ //Clear the East/West Bit Flags first
+ mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
+ if( js[i].value == -1 ) //Left
+ mState.mPOV[OIS_POVIndex].direction |= Pov::West;
+ else if( js[i].value == 1 ) //Right
+ mState.mPOV[OIS_POVIndex].direction |= Pov::East;
+ }
+ //Handle Y Axis (Odd) (up down)
+ else
+ {
+ //Clear the North/South Bit Flags first
+ mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
+ if( js[i].value == -1 ) //Up
+ mState.mPOV[OIS_POVIndex].direction |= Pov::North;
+ else if( js[i].value == 1 ) //Down
+ mState.mPOV[OIS_POVIndex].direction |= Pov::South;
+ }
+
+ if( mBuffered && mListener )
+ if( mListener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
+ return;
  }
+ break;
+ }
 
- if( mBuffered && mListener )
- if( mListener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
- return;
+
+ case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
+ #ifdef OIS_LINUX_JOY_DEBUG
+     cout << "\nWarning: Relatives axes not supported yet" << endl;
+ #endif
+ break;
+ default: break;
  }
- break;
  }
-
-
- case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
-#ifdef OIS_LINUX_JOY_DEBUG
-     cout << "\nWarning: Relatives axes not supported yet" << endl;
-#endif
- break;
- default: break;
- }
  }
 
  //All axes and POVs are combined into one movement per pair per captured frame
Logged
pjcast
Administrator
Veteran
*****
Posts: 2544



View Profile WWW
« Reply #1 on: July 25, 2010, 05:29:23 PM »

Applied to SVN head. I don't have Linux setup at the moment, but will test tomorrow to make sure nothing broke.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!