Linux Joystick Control Broken 1.5
by Demolishun · in Torque Game Engine · 03/11/2007 (4:38 pm) · 12 replies
This really stumping me. I am trying to get my gamepads to work under Linux. So far I can plug in my gamepads: 2 xbox, and 1 standard HID. I can see their values using jstest. It seems work well. Then I open Torque and get this message in the console near the top of HID:
and this for Xbox versions:
Now, I used this resource to grab events for GuiCanvas:
www.garagegames.com/mg/forums/result.thread.php?qt=21049
My code looks like this so far:
You will notice that I filtered out certain axis update events because all 3 joysticks were streaming those events at me causing the Con::printf function fill up my console.log to many megabytes in less than a minute. However, I never get any other events besides those that I filtered out for testing.
It acts as though the Linux to SDL interface is borked. I started walking through the code that handles this here: x86UNIXInputManager.cc.
Anybody deal with this yet? What version of SDL "should" I be using?
joystick0: HID 050d:0803 Input initialized
and this for Xbox versions:
joystick0: X-Box pad Input initialized
Now, I used this resource to grab events for GuiCanvas:
www.garagegames.com/mg/forums/result.thread.php?qt=21049
My code looks like this so far:
else if( event->deviceType == JoystickDeviceType)
{
// ignore these events - some wierd events from gamepad?
if(event->objType >= 0x20B || event->objType <= 0x211 || event->objType == 0x6D60)
{
return false;
}
// Do NOT PUT THE gLastEventTime change here, it will pick up the analog stick noise
//copy the modifier into the new event
mLastEvent.modifier = event->modifier;
GuiControl *ctrl = static_cast<GuiControl*>( last() ); // Send events to the top level GUI
const char *retval = "";
Con::printf("js event: objtype:%X action:%X",event->objType,event->action);
if( event->objType == SI_BUTTON )
{
// TODO: Add a 'back' feature for XBox -pw
if( event->action == SI_MAKE )
{
if( Con::getBoolVariable( "$playingDemo" )
&& !Con::getBoolVariable( "$gamePaused" ) )
{
Con::evaluate( "onDemoPlayDone(true);" );
return true;
}
switch( event->objInst )
{
case KEY_BUTTON0:
gLastButtonPressControlerInst = event->deviceInst;
retval = Con::executef( ctrl, 1, "onA" );
break;
// ... etc, etc
default:
return false;
}
}
// This block is duplicated because we don't want
// this being called if there wasn't a valid action (IE analog noise)
gLastEventTime = Sim::getCurrentTime();
if( dStrcmp( retval, "" ) == 0 )
retval = Con::executef( ctrl, 1, "onAction" );
if( dStrcmp( retval, "" ) )
return true;
}
else if( event->objType == SI_POV )
{
if( event->action == SI_MAKE )
{
switch( event->objInst )
{
case SI_UPOV:
retval = Con::executef( ctrl, 1, "onUp" );
break;
case SI_LPOV:
retval = Con::executef( ctrl, 1, "onLeft" );
break;
case SI_DPOV:
retval = Con::executef( ctrl, 1, "onDown" );
break;
case SI_RPOV:
retval = Con::executef( ctrl, 1, "onRight" );
break;
default:
return false;
}
}
gLastEventTime = Sim::getCurrentTime();
if( dStrcmp( retval, "" ) == 0 )
retval = Con::executef( ctrl, 1, "onAction" );
if( dStrcmp( retval, "" ) )
return true;
}
}You will notice that I filtered out certain axis update events because all 3 joysticks were streaming those events at me causing the Con::printf function fill up my console.log to many megabytes in less than a minute. However, I never get any other events besides those that I filtered out for testing.
It acts as though the Linux to SDL interface is borked. I started walking through the code that handles this here: x86UNIXInputManager.cc.
Anybody deal with this yet? What version of SDL "should" I be using?
About the author
I love programming, I love programming things that go click, whirr, boom. For organized T3D Links visit: http://demolishun.com/?page_id=67
#2
It looks like everything is there to process SDL joystick events using the standard event structure for Linux. Why one would do the processing the way it is being done now is beyond me.
03/11/2007 (7:46 pm)
Well, here is an interesting tidbit from the docs in the SDL website:Quote:
Note: Joystick event handling is preferred
Note: Even if joystick event processing is enabled, individual joysticks must be opened before they generate events
Warning: Calling this function may eat all events currently in SDL's event queue.
It looks like everything is there to process SDL joystick events using the standard event structure for Linux. Why one would do the processing the way it is being done now is beyond me.
#3
tdn.garagegames.com/wiki/Image:X86UNIXInputManager.zip
I fixed it. It now uses SDL only and works very well. It also does not produce a stream of useless input for the axis that just costs processing time. Way TOO MANY events were being pushed for the joystick code.
Please test this out and let me know if it needs adjustment.
So far I am only supporting buttons, axis, and hats just like the existing code.
03/11/2007 (8:25 pm)
Here:tdn.garagegames.com/wiki/Image:X86UNIXInputManager.zip
I fixed it. It now uses SDL only and works very well. It also does not produce a stream of useless input for the axis that just costs processing time. Way TOO MANY events were being pushed for the joystick code.
Please test this out and let me know if it needs adjustment.
So far I am only supporting buttons, axis, and hats just like the existing code.
#4
03/12/2007 (6:41 am)
Can't wait to try this later tonight.
#5
I have tried in the past a madcatz Xbox pad, an original MS Xbox pad and a Logitech Rumblepad 2 and all of them do not provide the dpad events so i ended working around it in the scripts.
03/12/2007 (6:51 am)
Forgot to ask does the dpad work like the dpad should or does it show up as 2 axis with -1 and 1 values ? I have tried in the past a madcatz Xbox pad, an original MS Xbox pad and a Logitech Rumblepad 2 and all of them do not provide the dpad events so i ended working around it in the scripts.
#6
Thanks for the feedback,
Frank
03/12/2007 (12:19 pm)
The dpad shows up as analog inputs. This is at the Linux driver level and I don't have a way to fix that yet. However, Torque can tell it is an Xbox controller. So maybe we can hack the lower level to tell it is a dpad for the Xbox controllers under Linux. Not sure how hard that would be, but we could figure it out. Let me look at it a bit. Also, if you are a programmer go look at the code I posted and see what you can make of it.Thanks for the feedback,
Frank
#7
gentoo-wiki.com/HOWTO_Xbox_360_controller_on_Linux
ubuntuforums.org/showthread.php?t=318382&highlight=xbox360
BTW, my xpad I was using was a wireless pelican xbox controller modified for USB connector. This is not a typical setup so I would not expect a programmer to design their game to support it. However, since the Xbox 360 controller is a USB controller (although not standard) there are drivers for it on PC platforms including Linux.
The above instructions tell you how to install a kernel driver for Linux 2.6.16 and later (I think). It works great.
The hat switch shows up as discrete rather than analog.
There may be a way in the Linux version of Torque to determine the joystick and setup based upon manufacturer, but right now the two kernel drivers I tried came back different data in the name call. The latest driver now seems to be using the manufacturer's string. I am not sure if there is good way to get the information we need. There is a joystick mapping scheme that allows axis events to be renamed using this method:
$Pref::Input::Joystick%d::Axis%d
Where the joystick would be some number 0 to n and the axis some number 0 to n. The string stored in this pref looks like this: "TorqueAxisName MinValue MaxValue"
You will have to play with this, but you could use this in conjunction with the console methods:
enableJoystick()
disableJoystick()
This should allow you to create a dialog where you can select each joystick's profile by selecting from a list. Another addition could be adding a console method that returns information about each joystick connected in order to allow the user to make an informed decision about settings. I will look into that part as it should be fairly simple.
Cheers
03/12/2007 (3:13 pm)
Here is some stuff I had to reference for setting up the 360 controller on my machine:gentoo-wiki.com/HOWTO_Xbox_360_controller_on_Linux
ubuntuforums.org/showthread.php?t=318382&highlight=xbox360
BTW, my xpad I was using was a wireless pelican xbox controller modified for USB connector. This is not a typical setup so I would not expect a programmer to design their game to support it. However, since the Xbox 360 controller is a USB controller (although not standard) there are drivers for it on PC platforms including Linux.
The above instructions tell you how to install a kernel driver for Linux 2.6.16 and later (I think). It works great.
The hat switch shows up as discrete rather than analog.
There may be a way in the Linux version of Torque to determine the joystick and setup based upon manufacturer, but right now the two kernel drivers I tried came back different data in the name call. The latest driver now seems to be using the manufacturer's string. I am not sure if there is good way to get the information we need. There is a joystick mapping scheme that allows axis events to be renamed using this method:
$Pref::Input::Joystick%d::Axis%d
Where the joystick would be some number 0 to n and the axis some number 0 to n. The string stored in this pref looks like this: "TorqueAxisName MinValue MaxValue"
You will have to play with this, but you could use this in conjunction with the console methods:
enableJoystick()
disableJoystick()
This should allow you to create a dialog where you can select each joystick's profile by selecting from a list. Another addition could be adding a console method that returns information about each joystick connected in order to allow the user to make an informed decision about settings. I will look into that part as it should be fairly simple.
Cheers
#8
Add this to x86UNIXInputManager.h:
This will allow a console function to check by index what the controller is:
Let me know how you fare.
Thanks,
Frank
03/12/2007 (4:13 pm)
Add this to the bottom of x86UNIXInputManager.cc:[b]//-----------------------------------------------------------------------------
// fhc
const char* UInputManager::getJoystickName(U32 deviceID)
{
for (Vector<JoystickInputDevice*>::iterator iter = mJoystickList.begin();
iter != mJoystickList.end();
++iter)
{
if ((*iter)->getDeviceID() == deviceID)
return (*iter)->getName();
}
return( "" );
};
ConsoleFunction( getJoystickName, const char *, 2, 2, "getJoystickName(%index)" )
{
UInputManager* mgr = dynamic_cast<UInputManager*>( Input::getManager() );
if(mgr)
return mgr->getJoystickName(U32(dAtof(argv[1])));
else
return "";
}[/b]Add this to x86UNIXInputManager.h:
const char* getJoystickAxesString( U32 deviceID );
bool joystickDetected() { return mJoystickList.size() > 0; }
[b]const char* getJoystickName(U32 deviceID); //fhc NEW FUNCTION, everything else for location reference[/b]
private:
typedef SimGroup Parent;This will allow a console function to check by index what the controller is:
echo(getJoystickName(0));
Let me know how you fare.
Thanks,
Frank
#9
03/12/2007 (4:24 pm)
I went ahead and update the file in TDN with the changes. Now you just download that to get the recent changes.
#10
1. For all the drivers I tested: xpad (two versions) and HID SI_POV is never generated. That means there is no standard way to get hat switch information.
2. Mapping inputs should take into account different hardware by doing the following:
a. Build profiles for specific devices.
b. Make no assumptions that would keep someone from playing your game because of hardware choice (do not hard code).
c. Allow for custom profiles for known and unknown controllers.
d. Provide a way for customers to build and submit profiles to you for inclusion in an update or a later release.
3. This is a hell of a lot of fun to figure out!
I think for number 2 and 3 that these apply to all platforms that TGE runs on.
Now, my next step is to figure out a decent mapping scheme for my game. This stuff has really sidetracked my development, but I feel like I really got something important done.
03/12/2007 (5:56 pm)
I have now had some time to play with the joystick code under Linux to find out some key things as far as "state of the art":1. For all the drivers I tested: xpad (two versions) and HID SI_POV is never generated. That means there is no standard way to get hat switch information.
2. Mapping inputs should take into account different hardware by doing the following:
a. Build profiles for specific devices.
b. Make no assumptions that would keep someone from playing your game because of hardware choice (do not hard code).
c. Allow for custom profiles for known and unknown controllers.
d. Provide a way for customers to build and submit profiles to you for inclusion in an update or a later release.
3. This is a hell of a lot of fun to figure out!
I think for number 2 and 3 that these apply to all platforms that TGE runs on.
Now, my next step is to figure out a decent mapping scheme for my game. This stuff has really sidetracked my development, but I feel like I really got something important done.
#11
I haven't had chance since yesterday to play with this hoping for a little time tonight. Nice work so far.
03/13/2007 (4:28 am)
Wow :) I haven't had chance since yesterday to play with this hoping for a little time tonight. Nice work so far.
#12
I just added the hooks into the Move structure to be able to have direct joystick input along side the normal input into the player.cc object. So the player pitch would match the position on the gamepad. It sucks for control. It is better to use the offset method where the players pitch changes while the axis is off center and ceases changing when it is not. Not as nice as a mouse input, but a lot easier to control. To be fair, the 1 to 1 control "might" work for a regular joystick, but the moment you take your hand off the controller it will recenter the pitch.
BTW, I am doing these changes to be able to have side by side control of the mouse and gamepad. You can pick up either controller at any time and control you game without switching modes. Both sets up inputs have their own set of variables and feedback functions in script.
I am thinking up a new widget for calibration and setting up controller profiles. I will do everything I can to make this cross platform so I will do as much of the work outside of the platform specific code. I have read a lot of the issues with calibration, offsets, etc. What I think is needed is a nice, robust, and easy to work with solution for using joysticks, gamepads, mouse, etc in the game and the GUI screens. I will start with a setup screen that will detect all inputs for setting up feedback functions.
03/16/2007 (12:10 pm)
Direct control of an axis using the full span of the input. (1 to 1 joy axis to player axis) DON'T DO IT! I just added the hooks into the Move structure to be able to have direct joystick input along side the normal input into the player.cc object. So the player pitch would match the position on the gamepad. It sucks for control. It is better to use the offset method where the players pitch changes while the axis is off center and ceases changing when it is not. Not as nice as a mouse input, but a lot easier to control. To be fair, the 1 to 1 control "might" work for a regular joystick, but the moment you take your hand off the controller it will recenter the pitch.
BTW, I am doing these changes to be able to have side by side control of the mouse and gamepad. You can pick up either controller at any time and control you game without switching modes. Both sets up inputs have their own set of variables and feedback functions in script.
I am thinking up a new widget for calibration and setting up controller profiles. I will do everything I can to make this cross platform so I will do as much of the work outside of the platform specific code. I have read a lot of the issues with calibration, offsets, etc. What I think is needed is a nice, robust, and easy to work with solution for using joysticks, gamepads, mouse, etc in the game and the GUI screens. I will start with a setup screen that will detect all inputs for setting up feedback functions.
Torque Owner Demolishun
DemolishunConsulting Rocks!
www.garagegames.com/products/111/
Link to test program written for Linux Debian Etch:
demolishun.net/images/testjoy.zip
This example works great. Need to track down issues in Torque.