185 lines
4 KiB
C++
185 lines
4 KiB
C++
|
#ifndef __INCLUDED_JS_H__
|
||
|
#define __INCLUDED_JS_H__ 1
|
||
|
|
||
|
#ifdef __linux__
|
||
|
# include <stdio.h>
|
||
|
# include <unistd.h>
|
||
|
# include <fcntl.h>
|
||
|
# include <linux/joystick.h>
|
||
|
#endif
|
||
|
|
||
|
#define JS_TRUE 1
|
||
|
#define JS_FALSE 0
|
||
|
|
||
|
/*
|
||
|
This is all set up for the older Linux and BSD drivers
|
||
|
which restrict you to two axes.
|
||
|
*/
|
||
|
|
||
|
#define _JS_MAX_AXES 2
|
||
|
|
||
|
class jsJoystick
|
||
|
{
|
||
|
JS_DATA_TYPE js ;
|
||
|
char fname [ 128 ] ;
|
||
|
int error ;
|
||
|
int fd ;
|
||
|
|
||
|
int num_axes ;
|
||
|
|
||
|
float dead_band [ _JS_MAX_AXES ] ;
|
||
|
float center [ _JS_MAX_AXES ] ;
|
||
|
float max [ _JS_MAX_AXES ] ;
|
||
|
float min [ _JS_MAX_AXES ] ;
|
||
|
|
||
|
void open ()
|
||
|
{
|
||
|
num_axes = _JS_MAX_AXES ;
|
||
|
|
||
|
fd = ::open ( fname, O_RDONLY ) ;
|
||
|
|
||
|
error = ( fd < 0 ) ;
|
||
|
|
||
|
if ( error )
|
||
|
return ;
|
||
|
|
||
|
int counter = 0 ;
|
||
|
|
||
|
/*
|
||
|
The Linux driver seems to return 512 for all axes
|
||
|
when no stick is present - but there is a chance
|
||
|
that could happen by accident - so it's gotta happen
|
||
|
on both axes for at least 100 attempts.
|
||
|
*/
|
||
|
|
||
|
do
|
||
|
{
|
||
|
rawRead ( NULL, center ) ;
|
||
|
counter++ ;
|
||
|
} while ( counter < 100 && center[0] == 512.0f && center[1] == 512.0f ) ;
|
||
|
|
||
|
if ( counter >= 100 )
|
||
|
error = JS_TRUE ;
|
||
|
|
||
|
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
|
||
|
{
|
||
|
max [ i ] = center [ i ] * 2.0f ;
|
||
|
min [ i ] = 0.0f ;
|
||
|
dead_band [ i ] = 0.0f ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void close ()
|
||
|
{
|
||
|
if ( ! error )
|
||
|
::close ( fd ) ;
|
||
|
}
|
||
|
|
||
|
float fudge_axis ( float value, int axis )
|
||
|
{
|
||
|
if ( value < center[axis] )
|
||
|
{
|
||
|
float xx = ( value - center[ axis ] ) /
|
||
|
( center [ axis ] - min [ axis ] ) ;
|
||
|
|
||
|
xx = ( xx > -dead_band [ axis ] ) ? 0.0f :
|
||
|
( ( xx + dead_band [ axis ] ) / ( 1.0f - dead_band [ axis ] ) ) ;
|
||
|
|
||
|
return ( xx < -1.0f ) ? -1.0f : xx ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
float xx = ( value - center [ axis ] ) /
|
||
|
( max [ axis ] - center [ axis ] ) ;
|
||
|
|
||
|
xx = ( xx < dead_band [ axis ] ) ? 0.0f :
|
||
|
( ( xx - dead_band [ axis ] ) / ( 1.0f - dead_band [ axis ] ) ) ;
|
||
|
|
||
|
return ( xx > 1.0f ) ? 1.0f : xx ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
jsJoystick ( int id = 0 )
|
||
|
{
|
||
|
sprintf ( fname, "/dev/js%d", id ) ;
|
||
|
open () ;
|
||
|
}
|
||
|
|
||
|
~jsJoystick ()
|
||
|
{
|
||
|
close () ;
|
||
|
}
|
||
|
|
||
|
int getNumAxes () { return num_axes ; }
|
||
|
int notWorking () { return error ; }
|
||
|
void setError () { error = JS_TRUE ; }
|
||
|
|
||
|
float getDeadBand ( int axis ) { return dead_band [ axis ] ; }
|
||
|
void setDeadBand ( int axis, float db ) { dead_band [ axis ] = db ; }
|
||
|
|
||
|
void setMinRange ( float *axes ) { memcpy ( min , axes, num_axes * sizeof(float) ) ; }
|
||
|
void setMaxRange ( float *axes ) { memcpy ( max , axes, num_axes * sizeof(float) ) ; }
|
||
|
void setCenter ( float *axes ) { memcpy ( center, axes, num_axes * sizeof(float) ) ; }
|
||
|
|
||
|
void getMinRange ( float *axes ) { memcpy ( axes, min , num_axes * sizeof(float) ) ; }
|
||
|
void getMaxRange ( float *axes ) { memcpy ( axes, max , num_axes * sizeof(float) ) ; }
|
||
|
void getCenter ( float *axes ) { memcpy ( axes, center, num_axes * sizeof(float) ) ; }
|
||
|
|
||
|
void read ( int *buttons, float *axes )
|
||
|
{
|
||
|
if ( error )
|
||
|
{
|
||
|
if ( buttons )
|
||
|
*buttons = 0 ;
|
||
|
|
||
|
if ( axes )
|
||
|
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
|
||
|
axes[i] = 0.0f ;
|
||
|
}
|
||
|
|
||
|
float raw_axes [ _JS_MAX_AXES ] ;
|
||
|
|
||
|
rawRead ( buttons, raw_axes ) ;
|
||
|
|
||
|
if ( axes )
|
||
|
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
|
||
|
axes[i] = ( i < num_axes ) ? fudge_axis ( raw_axes[i], i ) : 0.0f ;
|
||
|
}
|
||
|
|
||
|
void rawRead ( int *buttons, float *axes )
|
||
|
{
|
||
|
if ( error )
|
||
|
{
|
||
|
if ( buttons ) *buttons = 0 ;
|
||
|
if ( axes )
|
||
|
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
|
||
|
axes[i] = 1500.0f ;
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
int status = ::read ( fd, &js, JS_RETURN ) ;
|
||
|
|
||
|
if ( status != JS_RETURN )
|
||
|
{
|
||
|
perror ( fname ) ;
|
||
|
setError () ;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if ( buttons )
|
||
|
*buttons = js.buttons ;
|
||
|
|
||
|
if ( axes )
|
||
|
{
|
||
|
axes[0] = (float) js.x ;
|
||
|
axes[1] = (float) js.y ;
|
||
|
}
|
||
|
}
|
||
|
} ;
|
||
|
|
||
|
#endif
|
||
|
|