/* PLIB - A Suite of Portable Game Libraries Copyright (C) 1998,2002 Steve Baker This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information visit http://plib.sourceforge.net $Id: jsLinux.cxx,v 1.1 2007/01/02 21:48:42 jsd Exp jsd $ */ #include "js.h" #if defined (UL_LINUX) #include #if defined(JS_VERSION) && JS_VERSION >= 0x010000 #include #include #include # include struct os_specific_s { js_event js ; v_bool tmp_buttons ; v_float tmp_axes ; char fname [ 128 ] ; int fd ; }; void jsInit () {} void jsJoystick::open () { name [0] = '\0' ; os->fd = ::open ( os->fname, O_RDONLY ) ; error = ( os->fd < 0 ) ; if ( error ) return ; /* Set the correct number of axes for the linux driver */ /* Melchior Franz's fixes for big-endian Linuxes since writing * to the upper byte of an uninitialized word doesn't work. * 9 April 2003 */ unsigned char u ; ioctl ( os->fd, JSIOCGAXES , &u ) ; num_axes = u ; ioctl ( os->fd, JSIOCGBUTTONS, &u ) ; num_buttons = u + JS_SHIFT; ioctl ( os->fd, JSIOCGNAME ( sizeof(name) ), name ) ; fcntl ( os->fd, F_SETFL , O_NONBLOCK ) ; if ( num_axes > _JS_MAX_AXES ) num_axes = _JS_MAX_AXES ; // Remove any deadband value already done in the kernel. // Since we have our own deadband management this is safe to do. struct js_corr corr [ _JS_MAX_AXES ] ; ioctl ( os->fd, JSIOCGCORR, corr ); for ( int i = 0; i < num_axes ; ++i ) { if ( corr[ i ] . type == JS_CORR_BROKEN ) { int nodeadband = ( corr[ i ] . coef[ 0 ] + corr[ i ] . coef[ 1 ] ) / 2 ; corr[ i ] . coef[ 0 ] = nodeadband ; corr[ i ] . coef[ 1 ] = nodeadband ; } } ioctl ( os->fd, JSIOCSCORR, corr ); dead_band.resize(num_axes); saturate.resize(num_axes); center.resize(num_axes); max.resize(num_axes); min.resize(num_axes); for ( int i = 0 ; i < num_axes ; i++ ) { max [ i ] = 32767.0f ; center [ i ] = 0.0f ; min [ i ] = -32767.0f ; dead_band [ i ] = 0.0f ; saturate [ i ] = 1.0f ; } } void jsJoystick::close () { if ( ! error ) ::close ( os->fd ) ; delete os; } jsJoystick::jsJoystick ( int ident ) { id = ident ; os = new struct os_specific_s; sprintf ( os->fname, "/dev/input/js%d", ident ) ; if ( access ( os->fname, F_OK ) != 0 ) sprintf ( os->fname, "/dev/js%d", ident ) ; open () ; } void jsJoystick::rawRead ( v_bool& buttons, v_float& axes ) { if ( error ) { buttons.clear(); axes.clear(); return ; } while (1) { int status = ::read ( os->fd, &(os->js), sizeof(js_event) ) ; if ( status != sizeof(js_event) ) { /* use the old values */ buttons = os->tmp_buttons ; axes = os->tmp_axes; if ( errno == EAGAIN ) return ; perror( os->fname ) ; setError () ; return ; } os->tmp_buttons.resize(num_buttons, 0); os->tmp_axes.resize(num_axes, 0); unsigned int chan = os->js.number; if (chan != 0) { // never mess with button channel zero if (os->tmp_buttons[0]) chan += JS_SHIFT; } switch ( os->js.type & ~JS_EVENT_INIT ) { case JS_EVENT_BUTTON : os->tmp_buttons[chan] = os->js.value; break ; case JS_EVENT_AXIS: os->tmp_axes [ chan ] = (float) os->js.value ; break ; default: ulSetError ( UL_WARNING, "PLIB_JS: Unrecognised /dev/js return!?!" ) ; /* use the old values */ break; } buttons = os->tmp_buttons ; axes = os->tmp_axes; return ; } } // For compatibility with old callers. // Can handle at most 32 buttons (the number of bits in an int). void jsJoystick::rawRead ( int *buttons, float *axes ) { if ( error ) { if ( buttons ) *buttons = 0 ; if ( axes ) for ( int i = 0 ; i < num_axes ; i++ ) axes[i] = 1500.0f ; return ; } v_bool mybuttons; v_float myaxes; rawRead(mybuttons, myaxes); if (buttons) { *buttons = 0; unsigned int bbb(1); // the walking bit unsigned int lim(8*sizeof(*buttons)); if (mybuttons.size() < lim) lim = mybuttons.size(); for (unsigned int ii = 0; ii < lim; ii++) { if (mybuttons[ii]) *buttons |= bbb; bbb <<= 1; } } if (axes) for (int ii = 0; ii < num_axes; ii++) { axes[ii] = myaxes[ii]; } // that's all } #endif #endif