Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

linux_joystick.c (5078B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 /*
     23 ** linux_joystick.c
     24 **
     25 ** This file contains ALL Linux specific stuff having to do with the
     26 ** Joystick input.  When a port is being made the following functions
     27 ** must be implemented by the port:
     28 **
     29 ** Authors: mkv, bk
     30 **
     31 */
     32 
     33 #include <linux/joystick.h>
     34 #include <sys/types.h>
     35 #include <fcntl.h>
     36 #include <sys/ioctl.h>
     37 #include <unistd.h>  // bk001204
     38 
     39 
     40 #include "../client/client.h"
     41 #include "linux_local.h"
     42 
     43 /* We translate axes movement into keypresses. */
     44 int joy_keys[16] = {
     45      K_LEFTARROW, K_RIGHTARROW,
     46      K_UPARROW, K_DOWNARROW,
     47      K_JOY16, K_JOY17,
     48      K_JOY18, K_JOY19,
     49      K_JOY20, K_JOY21,
     50      K_JOY22, K_JOY23,
     51 
     52      K_JOY24, K_JOY25,
     53      K_JOY26, K_JOY27
     54 };
     55 
     56 /* Our file descriptor for the joystick device. */
     57 static int             joy_fd = -1;
     58 
     59 
     60 // bk001130 - from linux_glimp.c
     61 extern cvar_t *  in_joystick;
     62 extern cvar_t *  in_joystickDebug;
     63 extern cvar_t *  joy_threshold;
     64 
     65 
     66 /**********************************************/
     67 /* Joystick routines.                         */
     68 /**********************************************/
     69 // bk001130 - from cvs1.17 (mkv), removed from linux_glimp.c
     70 void IN_StartupJoystick( void )
     71 {
     72   int i = 0;
     73 
     74   joy_fd = -1;
     75 
     76   if( !in_joystick->integer ) {
     77     Com_Printf( "Joystick is not active.\n" );
     78     return;
     79   }
     80 
     81   for( i = 0; i < 4; i++ ) {
     82     char filename[PATH_MAX];
     83 
     84     snprintf( filename, PATH_MAX, "/dev/js%d", i );
     85 
     86     joy_fd = open( filename, O_RDONLY | O_NONBLOCK );
     87 
     88     if( joy_fd != -1 ) {
     89       struct js_event event;
     90       char axes = 0;
     91       char buttons = 0;
     92       char name[128];
     93       int n = -1;
     94 
     95       Com_Printf( "Joystick %s found\n", filename );
     96 
     97       /* Get rid of initialization messages. */
     98       do {
     99 	n = read( joy_fd, &event, sizeof( event ) );
    100 
    101 	if( n == -1 ) {
    102 	  break;
    103 	}
    104 
    105       } while( ( event.type & JS_EVENT_INIT ) );
    106 
    107       /* Get joystick statistics. */
    108       ioctl( joy_fd, JSIOCGAXES, &axes );
    109       ioctl( joy_fd, JSIOCGBUTTONS, &buttons );
    110 
    111       if( ioctl( joy_fd, JSIOCGNAME( sizeof( name ) ), name ) < 0 ) {
    112 	strncpy( name, "Unknown", sizeof( name ) );
    113       }
    114 
    115       Com_Printf( "Name:    %s\n", name );
    116       Com_Printf( "Axes:    %d\n", axes );
    117       Com_Printf( "Buttons: %d\n", buttons );
    118 
    119       /* Our work here is done. */
    120       return;
    121     }
    122 
    123   }
    124 
    125   /* No soup for you. */
    126   if( joy_fd == -1 ) {
    127     Com_Printf( "No joystick found.\n" );
    128     return;
    129   }
    130 
    131 }
    132 
    133 void IN_JoyMove( void )
    134 {
    135   /* Store instantaneous joystick state. Hack to get around
    136    * event model used in Linux joystick driver.
    137 	 */
    138   static int axes_state[16];
    139   /* Old bits for Quake-style input compares. */
    140   static unsigned int old_axes = 0;
    141   /* Our current goodies. */
    142   unsigned int axes = 0;
    143   int i = 0;
    144 
    145   if( joy_fd == -1 ) {
    146     return;
    147   }
    148 
    149   /* Empty the queue, dispatching button presses immediately
    150 	 * and updating the instantaneous state for the axes.
    151 	 */
    152   do {
    153     int n = -1;
    154     struct js_event event;
    155 
    156     n = read( joy_fd, &event, sizeof( event ) );
    157 
    158     if( n == -1 ) {
    159       /* No error, we're non-blocking. */
    160       break;
    161     }
    162 
    163     if( event.type & JS_EVENT_BUTTON ) {
    164       Sys_QueEvent( 0, SE_KEY, K_JOY1 + event.number, event.value, 0, NULL );
    165     } else if( event.type & JS_EVENT_AXIS ) {
    166 
    167       if( event.number >= 16 ) {
    168 	continue;
    169       }
    170 
    171       axes_state[event.number] = event.value;
    172     } else {
    173       Com_Printf( "Unknown joystick event type\n" );
    174     }
    175 
    176   } while( 1 );
    177 
    178 
    179   /* Translate our instantaneous state to bits. */
    180   for( i = 0; i < 16; i++ ) {
    181     float f = ( (float) axes_state[i] ) / 32767.0f;
    182 
    183     if( f < -joy_threshold->value ) {
    184       axes |= ( 1 << ( i * 2 ) );
    185     } else if( f > joy_threshold->value ) {
    186       axes |= ( 1 << ( ( i * 2 ) + 1 ) );
    187     }
    188 
    189   }
    190 
    191   /* Time to update axes state based on old vs. new. */
    192   for( i = 0; i < 16; i++ ) {
    193 
    194     if( ( axes & ( 1 << i ) ) && !( old_axes & ( 1 << i ) ) ) {
    195       Sys_QueEvent( 0, SE_KEY, joy_keys[i], qtrue, 0, NULL );
    196     }
    197 
    198     if( !( axes & ( 1 << i ) ) && ( old_axes & ( 1 << i ) ) ) {
    199       Sys_QueEvent( 0, SE_KEY, joy_keys[i], qfalse, 0, NULL );
    200     }
    201   }
    202 
    203   /* Save for future generations. */
    204   old_axes = axes;
    205 }
    206 
    207