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