torcs - 1.2.2

src/interfaces/js.h

Go to the documentation of this file.
00001 /*
00002      PLIB - A Suite of Portable Game Libraries
00003      Copyright (C) 2001  Steve Baker
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Library General Public
00007      License as published by the Free Software Foundation; either
00008      version 2 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Library General Public License for more details.
00014 
00015      You should have received a copy of the GNU Library General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019      For further information visit http://plib.sourceforge.net
00020 
00021      $Id: js.h,v 1.5 2003/09/05 19:38:12 torcs Exp $
00022 */
00023 
00024 #ifndef __INCLUDED_JS_H__
00025 #define __INCLUDED_JS_H__ 1
00026 
00027 #include <plib/ul.h>
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h> // -dw- for memcpy
00032 
00033 #ifdef macintosh
00034 #  include <InputSprocket.h>
00035 #endif
00036 
00037 #define MAX_AXES 12     /* for TORCS */
00038 #define NUM_JOY 8       /* for TORCS */
00039 
00040 /*
00041   FreeBSD port - courtesy of Stephen Montgomery-Smith
00042   <stephen@math.missouri.edu>
00043 
00044   NetBSD mods - courtesy Rene Hexel.
00045 
00046   The next lines are to define BSD
00047   see http://www.freebsd.org/handbook/porting.html for why we do this
00048 */
00049 //lint -save -e620
00050 
00051 #if (defined(__unix__) || defined(unix)) && !defined(USG)
00052 #include <sys/param.h>
00053 #endif
00054 
00055 #ifdef WIN32
00056 #  include <windows.h>
00057 #  if defined( __CYGWIN32__ ) || defined( __CYGWIN__ )
00058 #    define NEAR /* */
00059 #    define FAR  /* */
00060 #  endif
00061 #  include <mmsystem.h>
00062 #  include <string.h>
00063 #else
00064 
00065 #  include <unistd.h>
00066 #  include <fcntl.h>
00067 
00068 #  if defined(__FreeBSD__)
00069 #    include <sys/joystick.h>
00070 #    define JS_DATA_TYPE joystick
00071 #    define JS_RETURN (sizeof(struct JS_DATA_TYPE))
00072 #  elif defined(__NetBSD__)
00073 #    include <machine/joystick.h>
00074 #    define JS_DATA_TYPE joystick
00075 #    define JS_RETURN (sizeof(struct JS_DATA_TYPE))
00076 #  elif defined(__linux__)
00077 #    include <sys/ioctl.h>
00078 #    include <linux/joystick.h>
00079 #    include <errno.h>
00080 
00081      /* check the joystick driver version */
00082 
00083 #    ifdef JS_VERSION
00084 #      if JS_VERSION >= 0x010000
00085 #        define JS_NEW
00086 #      endif
00087 #    endif
00088 
00089 #  else
00090 #    ifndef JS_DATA_TYPE
00091 
00092       /*
00093         Not Windoze and no joystick driver...
00094 
00095         Well - we'll put these values in and that should
00096         allow the code to at least compile. The JS open
00097         routine should error out and shut off all the code
00098         downstream anyway
00099       */
00100 
00101        struct JS_DATA_TYPE
00102        {
00103          int buttons ;
00104          int x ;
00105          int y ;
00106        } ;
00107 
00108 #      define JS_RETURN (sizeof(struct JS_DATA_TYPE))
00109 #    endif
00110 #  endif
00111 #endif
00112 
00113 #define JS_TRUE  1
00114 #define JS_FALSE 0
00115 
00116 #ifdef WIN32
00117 #  define _JS_MAX_AXES 8  /* X,Y,Z,R,U,V,POV_X,POV_Y */
00118 #elif defined (macintosh)
00119 #  define _JS_MAX_AXES 9
00120 #else
00121 #  if defined(__FreeBSD__) || defined(__NetBSD__)
00122 #  define _JS_MAX_AXES 2
00123 #  else
00124 #  define _JS_MAX_AXES 9
00125 #  endif
00126 #endif
00127 
00128 class jsJoystick
00129 {
00130 #ifdef macintosh
00131 
00132    #define  isp_num_axis   9
00133    #define  isp_num_needs  41
00134 
00135    ISpElementReference     isp_elem[isp_num_needs];
00136    ISpNeed isp_needs       [isp_num_needs];
00137 
00138 #endif
00139 
00140 #define NAME_LENGTH 128
00141    char name [ NAME_LENGTH ] ;
00142 
00143 #if defined(__FreeBSD__) || defined(__NetBSD__)
00144   int          id ;
00145 #endif
00146 #ifdef WIN32
00147   JOYINFOEX    js       ;
00148   UINT         js_id    ;
00149 #else
00150 # ifdef JS_NEW
00151   js_event     js          ;
00152   int          tmp_buttons ;
00153   float        tmp_axes [ _JS_MAX_AXES ] ;
00154 # else
00155   JS_DATA_TYPE js ;
00156 # endif
00157   char         fname [ 128 ] ;
00158   char         alt_fname [ 128 ] ;
00159   int          fd       ;
00160 #endif
00161 
00162   int          error    ;
00163   int          num_axes ;
00164   int          num_buttons ;
00165 
00166   float dead_band [ _JS_MAX_AXES ] ;
00167   float saturate  [ _JS_MAX_AXES ] ;
00168   float center    [ _JS_MAX_AXES ] ;
00169   float max       [ _JS_MAX_AXES ] ;
00170   float min       [ _JS_MAX_AXES ] ;
00171 
00172   void open ()
00173   {
00174 
00175     strcpy ( name, "unknown" ) ;
00176 
00177 #ifdef macintosh
00178 
00179    /*
00180      FIXME: get joystick name in Mac
00181    */
00182 
00183    OSStatus err;
00184 
00185    err = ISpStartup ();
00186 
00187         if ( err == noErr ) {
00188 
00189         #define ISP_CHECK_ERR(x) if (x != noErr) { setError(); return; }
00190 
00191         setError ();
00192 
00193       // initialize the needs structure
00194       ISpNeed temp_isp_needs[isp_num_needs] = 
00195       {
00196           {"\pX-Axis",   128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00197           {"\pY-Axis",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00198           {"\pZ-Axis",    128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00199           {"\pR-Axis",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00200           {"\pAxis   4",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00201           {"\pAxis   5",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00202           {"\pAxis   6",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00203           {"\pAxis   7",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00204           {"\pAxis   8",  128, 0, 0, kISpElementKind_Axis,   kISpElementLabel_None, 0, 0, 0, 0 },
00205 
00206           {"\pButton 0",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00207           {"\pButton 1",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00208           {"\pButton 2",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00209           {"\pButton 3",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00210           {"\pButton 4",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00211           {"\pButton 5",    128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00212           {"\pButton 6",   128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00213           {"\pButton 7",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00214           {"\pButton 8",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00215           {"\pButton 9",  128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00216           {"\pButton 10", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00217           {"\pButton 11", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00218           {"\pButton 12", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00219           {"\pButton 13", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00220           {"\pButton 14", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00221           {"\pButton 15", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00222           {"\pButton 16", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00223           {"\pButton 17", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00224           {"\pButton 18", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00225           {"\pButton 19", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00226           {"\pButton 20", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00227           {"\pButton 21", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00228           {"\pButton 22", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00229           {"\pButton 23", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00230           {"\pButton 24", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00231           {"\pButton 25", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00232           {"\pButton 26", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00233           {"\pButton 27", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00234           {"\pButton 28", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00235           {"\pButton 29", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00236           {"\pButton 30", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00237           {"\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
00238       };
00239 
00240       memcpy (isp_needs, temp_isp_needs, sizeof (temp_isp_needs) );
00241 
00242 
00243       // next two calls allow keyboard and mouse to emulate other input devices (gamepads, joysticks, etc)
00244 
00245       /*
00246       err = ISpDevices_ActivateClass (kISpDeviceClass_Keyboard);
00247       ISP_CHECK_ERR(err)
00248 
00249 
00250       err = ISpDevices_ActivateClass (kISpDeviceClass_Mouse);
00251       ISP_CHECK_ERR(err)
00252       */
00253 
00254       err = ISpElement_NewVirtualFromNeeds (isp_num_needs, isp_needs, isp_elem, 0);
00255       ISP_CHECK_ERR(err)
00256 
00257       err = ISpInit (isp_num_needs, isp_needs, isp_elem, 'PLIB', nil, 0, 128, 0);
00258       ISP_CHECK_ERR(err)
00259 
00260       num_buttons = isp_num_needs - isp_num_axis;
00261       num_axes    = isp_num_axis;
00262 
00263       for ( int i = 0; i < num_axes; i++ ) {
00264 
00265          dead_band[i] = 0;
00266          saturate [i] = 1;
00267          center[i]    = kISpAxisMiddle;         
00268          max [i]      = kISpAxisMaximum;
00269          min [i]      = kISpAxisMinimum;
00270       }
00271 
00272       error = false;
00273    }
00274    else {
00275      setError ();
00276      num_buttons = num_axes = 0; 
00277    }
00278 
00279 #elif defined( WIN32 )
00280 
00281     JOYCAPS jsCaps ;
00282 
00283     js . dwFlags = JOY_RETURNALL ;
00284     js . dwSize  = sizeof ( js ) ;
00285 
00286     memset ( &jsCaps, 0, sizeof(jsCaps) ) ;
00287 
00288     error = ( joyGetDevCaps( js_id, &jsCaps, sizeof(jsCaps) )
00289                  != JOYERR_NOERROR ) ;
00290     if ( jsCaps.wNumAxes == 0 )
00291     {
00292       num_axes = 0 ;
00293       setError () ;
00294     }
00295     else
00296     {
00297       // Windows joystick drivers may provide any combination of
00298       // X,Y,Z,R,U,V,POV - not necessarily the first n of these.
00299       if ( jsCaps.wCaps & JOYCAPS_HASPOV ) {
00300         num_axes = _JS_MAX_AXES ;
00301         min[7] = -1.0 ; max[7] = 1.0 ;  // POV Y
00302         min[6] = -1.0 ; max[6] = 1.0 ;  // POV X
00303       } else {
00304         num_axes = 6 ;
00305       }
00306       min[5] = (float)jsCaps.wVmin ; max[5] = (float)jsCaps.wVmax ;
00307       min[4] = (float)jsCaps.wUmin ; max[4] = (float)jsCaps.wUmax ;
00308       min[3] = (float)jsCaps.wRmin ; max[3] = (float)jsCaps.wRmax ;
00309       min[2] = (float)jsCaps.wZmin ; max[2] = (float)jsCaps.wZmax ;
00310       min[1] = (float)jsCaps.wYmin ; max[1] = (float)jsCaps.wYmax ;
00311       min[0] = (float)jsCaps.wXmin ; max[0] = (float)jsCaps.wXmax ;
00312     }
00313 
00314     for ( int i = 0 ; i < num_axes ; i++ )
00315     {
00316       center    [ i ] = ( max[i] + min[i] ) / 2.0f ;
00317       dead_band [ i ] = 0.0f ;
00318       saturate  [ i ] = 1.0f ;
00319     }
00320 
00321     /* Get the device name */
00322     strncpy ( name , jsCaps.szPname , NAME_LENGTH - 1 ) ;
00323     name [ NAME_LENGTH - 1 ] = 0;
00324 
00325 #else
00326 #  if defined(__FreeBSD__) || defined(__NetBSD__)
00327     FILE *joyfile;
00328     char joyfname[1024];
00329     int noargs, in_no_axes;
00330 #  endif
00331 
00332     /* Default for older Linux systems. */
00333 
00334     num_axes    =  2 ;
00335     num_buttons = 32 ;
00336 
00337 #  ifdef JS_NEW
00338     for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
00339       tmp_axes [ i ] = 0.0f ;
00340 
00341     tmp_buttons = 0 ;
00342 #  endif
00343 
00344    // fd = ::open ( fname, O_RDONLY | O_NONBLOCK ) ;
00345     fd = ::open ( fname, O_RDONLY ) ;
00346 
00347     error = ( fd < 0 ) ;
00348 
00349     if ( error )
00350     {
00351         if (alt_fname[0] != 0)
00352         {
00353             fd = ::open ( alt_fname, O_RDONLY ) ;
00354             error = ( fd < 0 ) ;
00355             if ( error )
00356                 return;
00357         }
00358         else
00359             return ;
00360     }
00361     
00362 
00363 #  if defined(__FreeBSD__) || defined(__NetBSD__)
00364 
00365     /*
00366       FIXME: get joystick name for BSD
00367     */
00368 
00369     float axes[_JS_MAX_AXES];
00370     int buttons[_JS_MAX_AXES];
00371     rawRead ( buttons, axes );
00372     error = axes[0] < -1000000000.0f;
00373     if ( error )
00374       return ;
00375 
00376     sprintf(joyfname,"%s/.joy%drc",::getenv( "HOME" ),id);
00377 
00378     joyfile = fopen(joyfname,"r");
00379     error = joyfile == NULL;
00380     if ( error )
00381       return ;
00382     noargs = fscanf(joyfile,"%d%f%f%f%f%f%f",&in_no_axes,
00383                         &min[0],&center[0],&max[0],
00384                         &min[1],&center[1],&max[1]);
00385     error = noargs != 7 || in_no_axes != _JS_MAX_AXES;
00386     fclose(joyfile);
00387     if ( error )
00388       return ;
00389 
00390     for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
00391     {
00392       dead_band [ i ] = 0.0f ;
00393       saturate  [ i ] = 1.0f ;
00394     }
00395 
00396 #  else
00397 
00398     /*
00399       Set the correct number of axes for the linux driver
00400     */
00401 
00402 #  ifdef JS_NEW
00403     ioctl ( fd, JSIOCGAXES   , & num_axes    ) ;
00404     ioctl ( fd, JSIOCGBUTTONS, & num_buttons ) ;
00405     ioctl ( fd, JSIOCGNAME ( NAME_LENGTH ) , name ) ;
00406     fcntl ( fd, F_SETFL, O_NONBLOCK ) ;
00407 
00408     if ( num_axes > _JS_MAX_AXES )
00409       num_axes = _JS_MAX_AXES ;
00410 #   endif
00411 
00412     /*
00413       The Linux driver seems to return 512 for all axes
00414       when no stick is present - but there is a chance
00415       that could happen by accident - so it's gotta happen
00416       on both axes for at least 100 attempts.
00417     */
00418 
00419 #ifndef JS_NEW
00420     int counter = 0 ;
00421 
00422     do
00423     { 
00424       rawRead ( NULL, center ) ;
00425       counter++ ;
00426     } while ( ! error &&
00427                 counter < 100 &&
00428                 center[0] == 512.0f &&
00429                 center[1] == 512.0f ) ;
00430 
00431     if ( counter >= 100 )
00432       setError() ;
00433 #endif
00434 
00435     for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
00436     {
00437 #ifdef JS_NEW
00438       max [ i ] = 32767.0f ;
00439       center [ i ] = 0.0f ;
00440       min [ i ] = -32767.0f ;
00441 #else
00442       max [ i ] = center [ i ] * 2.0f ;
00443       min [ i ] = 0.0f ;
00444 #endif
00445       dead_band [ i ] = 0.0f ;
00446       saturate  [ i ] = 1.0f ;
00447     }
00448 
00449 #  endif
00450 #endif
00451   }
00452 
00453   void close ()
00454   {
00455 #if !defined( WIN32 ) && !defined( macintosh )
00456     if ( ! error )
00457       ::close ( fd ) ;
00458 #endif
00459 
00460 #ifdef macintosh
00461 
00462    ISpSuspend ();
00463    ISpStop ();
00464    ISpShutdown ();   
00465 
00466 #endif
00467   }
00468 
00469   float fudge_axis ( float value, int axis ) const
00470   {
00471     if ( value < center[axis] )
00472     {
00473       float xx = (      value    - center[ axis ] ) /
00474                  ( center [ axis ] - min [ axis ] ) ;
00475 
00476       if ( xx < -saturate [ axis ] )
00477                                 return -1.0f ;
00478 
00479       if ( xx > -dead_band [ axis ] )
00480                                 return 0.0f ;
00481 
00482       xx = (        xx         + dead_band [ axis ] ) /
00483            ( saturate [ axis ] - dead_band [ axis ] ) ;
00484 
00485       return ( xx < -1.0f ) ? -1.0f : xx ;
00486     }
00487     else
00488     {
00489       float xx = (     value    - center [ axis ] ) /
00490                  ( max [ axis ] - center [ axis ] ) ;
00491 
00492       if ( xx > saturate [ axis ] )
00493                                 return 1.0f ;
00494 
00495       if ( xx < dead_band [ axis ] )
00496                                 return 0.0f ;
00497 
00498       xx = (        xx         - dead_band [ axis ] ) /
00499            ( saturate [ axis ] - dead_band [ axis ] ) ;
00500 
00501       return ( xx > 1.0f ) ? 1.0f : xx ;
00502     }
00503   }
00504 
00505 public:
00506 
00507   jsJoystick ( int ident = 0 )
00508   {
00509 #ifndef WIN32
00510     alt_fname [ 0 ] = 0;
00511 #endif
00512 #ifdef WIN32
00513     if ( ident < 32 )
00514         {
00515             js_id = ident ;
00516             open () ;
00517         }
00518     else
00519         {
00520             num_axes = 0 ;
00521             setError () ;
00522         }
00523 #if 0
00524     switch ( ident )
00525     {
00526       case 0  : js_id = JOYSTICKID1 ; open () ; break ;
00527       case 1  : js_id = JOYSTICKID2 ; open () ; break;
00528       default :    num_axes = 0 ; setError () ; break ;
00529     }
00530 #endif
00531 
00532 #else
00533 #  if defined(__FreeBSD__) || defined(__NetBSD__)
00534     id = ident;
00535     sprintf ( fname, "/dev/joy%d", ident ) ;
00536 #  else
00537     sprintf ( fname, "/dev/input/js%d", ident ) ; /* first try */
00538     sprintf ( alt_fname, "/dev/js%d", ident ) ;   /* second try */
00539 #  endif
00540     open () ;
00541 #endif
00542   }
00543 
00544   ~jsJoystick ()
00545   {
00546     close () ;
00547   }
00548 
00549   const char* getName () const { return name ;     }
00550   int   getNumAxes    () const { return num_axes ; }
00551   int   notWorking    () const { return error ;    }
00552   void  setError      () { error = JS_TRUE ; }
00553 
00554   float getDeadBand ( int axis ) const       { return dead_band [ axis ] ; }
00555   void  setDeadBand ( int axis, float db )   { dead_band [ axis ] = db   ; }
00556 
00557   float getSaturation ( int axis ) const     { return saturate [ axis ]  ; }
00558   void  setSaturation ( int axis, float st ) { saturate [ axis ] = st    ; }
00559 
00560   void setMinRange ( float *axes ) { memcpy ( min   , axes, num_axes * sizeof(float) ) ; }
00561   void setMaxRange ( float *axes ) { memcpy ( max   , axes, num_axes * sizeof(float) ) ; }
00562   void setCenter   ( float *axes ) { memcpy ( center, axes, num_axes * sizeof(float) ) ; }
00563 
00564   void getMinRange ( float *axes ) const { memcpy ( axes, min   , num_axes * sizeof(float) ) ; }
00565   void getMaxRange ( float *axes ) const { memcpy ( axes, max   , num_axes * sizeof(float) ) ; }
00566   void getCenter   ( float *axes ) const { memcpy ( axes, center, num_axes * sizeof(float) ) ; }
00567 
00568   void read ( int *buttons, float *axes )
00569   {
00570     if ( error )
00571     {
00572       if ( buttons )
00573         *buttons = 0 ;
00574 
00575       if ( axes )
00576         for ( int i = 0 ; i < num_axes ; i++ )
00577           axes[i] = 0.0f ;
00578     }
00579 
00580     float raw_axes [ _JS_MAX_AXES ] ;
00581 
00582     rawRead ( buttons, raw_axes ) ;
00583 
00584     if ( axes )
00585       for ( int i = 0 ; i < num_axes ; i++ )
00586         axes[i] = fudge_axis ( raw_axes[i], i ) ;
00587   }
00588 
00589   void rawRead ( int *buttons, float *axes )
00590   {
00591     if ( error )
00592     {
00593       if ( buttons )
00594         *buttons = 0 ;
00595 
00596       if ( axes )
00597         for ( int i = 0 ; i < num_axes ; i++ )
00598           axes[i] = 1500.0f ;
00599 
00600       return ;
00601     }
00602 
00603 #ifdef macintosh
00604 
00605       int i;
00606       int err;
00607       UInt32 state;
00608 
00609       if (buttons) {
00610 
00611          *buttons = 0;
00612 
00613          for (i = 0; i < num_buttons; i++) {
00614 
00615             err = ISpElement_GetSimpleState (isp_elem[i + isp_num_axis ], &state);
00616             ISP_CHECK_ERR (err)
00617 
00618             *buttons  |= state << i;   
00619          }
00620       }
00621 
00622       if (axes) {
00623 
00624          for (i = 0; i < num_axes; i++) {
00625 
00626             err = ISpElement_GetSimpleState (isp_elem[ i ], &state);
00627             ISP_CHECK_ERR  (err);
00628 
00629             axes [i] = (float) state;
00630          }
00631       }
00632 
00633 #elif defined ( WIN32 )
00634     MMRESULT status = joyGetPosEx ( js_id, &js ) ;
00635 
00636     if ( status != JOYERR_NOERROR )
00637     {
00638       setError() ;
00639       return ;
00640     }
00641 
00642     if ( buttons )
00643     {
00644       *buttons = (int) js . dwButtons ;
00645     }
00646 
00647     if ( axes )
00648     {
00649       /* WARNING - Fall through case clauses!! */
00650 //lint -save -e616
00651 
00652       switch ( num_axes )
00653       {
00654         case 8:
00655           // Generate two POV axes from the POV hat angle.
00656           // Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in
00657           //   hundredths of a degree, or 0xFFFF when idle.
00658           if ( (js.dwPOV & 0xFFFF) == 0xFFFF ) {
00659             axes[6] = 0.0;
00660             axes[7] = 0.0;
00661           } else {
00662             // This is the contentious bit: how to convert angle to X/Y.
00663                                                 // wk: I know of no define for PI that we could use here:
00664                                                 // SG_PI would pull in sg, M_PI is undefined for MSVC
00665                                                 // But the accuracy of the value of PI is very unimportant at this point.
00666             float s = (float)sin((js.dwPOV & 0xFFFF) * (0.01 * 3.1415926535f / 180));
00667             float c = (float)cos((js.dwPOV & 0xFFFF) * (0.01 * 3.1415926535f / 180));
00668             // Convert to coordinates on a square so that North-East
00669             // is (1,1) not (.7,.7), etc.
00670             // s and c cannot both be zero so we won't divide by zero.
00671             if (fabs(s) < fabs(c)) {
00672               axes[6] = (c < 0.0) ? -s/c : s/c;
00673               axes[7] = (c < 0.0) ? -1.0f : 1.0f;
00674             } else {
00675               axes[6] = (s < 0.0) ? -1.0f : 1.0f;
00676               axes[7] = (s < 0.0) ? -c/s : c/s;
00677             }
00678           }
00679         case 6: axes[5] = (float) js . dwVpos ;
00680         case 5: axes[4] = (float) js . dwUpos ;
00681         case 4: axes[3] = (float) js . dwRpos ;
00682         case 3: axes[2] = (float) js . dwZpos ;
00683         case 2: axes[1] = (float) js . dwYpos ;
00684         case 1: axes[0] = (float) js . dwXpos ;
00685                 break;
00686         default:
00687                 ulSetError ( UL_WARNING, "PLIB_JS: Wrong num_axes. Joystick input is now invalid" ) ;
00688 
00689       }
00690 //lint -restore
00691     }
00692 #else
00693 
00694 # ifdef JS_NEW
00695 
00696     while (1)
00697     {
00698       int status = ::read ( fd, &js, sizeof(js_event) ) ;
00699 
00700       if ( status != sizeof(js_event) )
00701       {
00702         /* use the old values */
00703 
00704         if ( buttons ) *buttons = tmp_buttons ;
00705         if ( axes    ) memcpy ( axes, tmp_axes, sizeof(float) * num_axes ) ;
00706 
00707         if ( errno == EAGAIN )
00708           return ;
00709 
00710         perror( fname ) ;
00711         setError () ;
00712         return ;
00713       }
00714 
00715       switch ( js.type & ~JS_EVENT_INIT )
00716       {
00717         case JS_EVENT_BUTTON :
00718           if ( js.value == 0 ) /* clear the flag */
00719             tmp_buttons &= ~(1 << js.number) ;
00720           else
00721             tmp_buttons |=  (1 << js.number) ;
00722           break ;
00723 
00724         case JS_EVENT_AXIS:
00725           if ( js.number < num_axes )
00726           {
00727             tmp_axes [ js.number ] = (float) js.value ;
00728 
00729             if ( axes )
00730               memcpy ( axes, tmp_axes, sizeof(float) * num_axes ) ;
00731           }
00732           break ;
00733 
00734         default:
00735           ulSetError ( UL_WARNING, "PLIB_JS: Unrecognised /dev/js return!?!" ) ;
00736 
00737           /* use the old values */
00738 
00739           if ( buttons ) *buttons = tmp_buttons ;
00740           if ( axes    ) memcpy ( axes, tmp_axes, sizeof(float) * num_axes ) ;
00741 
00742           return ;
00743       }
00744 
00745       if ( buttons )
00746         *buttons = tmp_buttons ;
00747     }
00748 
00749 # else
00750 
00751     int status = ::read ( fd, &js, JS_RETURN ) ;
00752 
00753     if ( status != JS_RETURN )
00754     {
00755       perror ( fname ) ;
00756       setError () ;
00757       return ;
00758     }
00759 
00760     if ( buttons )
00761 #  if defined(__FreeBSD__) || defined(__NetBSD__)
00762       *buttons = ( js.b1 ? 1 : 0 ) | ( js.b2 ? 2 : 0 ) ;
00763 #  else
00764       *buttons = js.buttons ;
00765 #  endif
00766 
00767     if ( axes )
00768     {
00769       axes[0] = (float) js.x ;
00770       axes[1] = (float) js.y ;
00771     }
00772 # endif
00773 #endif
00774   }
00775 } ;
00776 //lint -restore
00777 
00778 #endif
00779 

Generated at Thu Feb 26 21:52:27 2004 for torcs by doxygen 1.3.3 written by Dimitri van Heesch, © 1997-1999
TORCS © Eric Espié 1999, 2002.