/* =========================================================================== Return to Castle Wolfenstein single player GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). RTCW SP Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RTCW SP Source Code 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 General Public License for more details. You should have received a copy of the GNU General Public License along with RTCW SP Source Code. If not, see . In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ /* ** linux_joystick.c ** ** This file contains ALL Linux specific stuff having to do with the ** Joystick input. When a port is being made the following functions ** must be implemented by the port: ** ** Authors: mkv, bk ** */ #include #include #include #include // bk001204 #include "../client/client.h" #include "linux_local.h" // TTimo moved joystick.h include here, conflicts in client.h with wkey_t #include /* We translate axes movement into keypresses. */ int joy_keys[16] = { K_LEFTARROW, K_RIGHTARROW, K_UPARROW, K_DOWNARROW, K_JOY16, K_JOY17, K_JOY18, K_JOY19, K_JOY20, K_JOY21, K_JOY22, K_JOY23, K_JOY24, K_JOY25, K_JOY26, K_JOY27 }; /* Our file descriptor for the joystick device. */ static int joy_fd = -1; // bk001130 - from linux_glimp.c extern cvar_t * in_joystick; extern cvar_t * in_joystickDebug; extern cvar_t * joy_threshold; /**********************************************/ /* Joystick routines. */ /**********************************************/ // bk001130 - from cvs1.17 (mkv), removed from linux_glimp.c void IN_StartupJoystick( void ) { int i = 0; joy_fd = -1; if ( !in_joystick->integer ) { Com_DPrintf( "Joystick is not active.\n" ); return; } for ( i = 0; i < 4; i++ ) { char filename[PATH_MAX]; snprintf( filename, PATH_MAX, "/dev/js%d", i ); joy_fd = open( filename, O_RDONLY | O_NONBLOCK ); if ( joy_fd != -1 ) { struct js_event event; char axes = 0; char buttons = 0; char name[128]; int n = -1; Com_Printf( "Joystick %s found\n", filename ); /* Get rid of initialization messages. */ do { n = read( joy_fd, &event, sizeof( event ) ); if ( n == -1 ) { break; } } while ( ( event.type & JS_EVENT_INIT ) ); /* Get joystick statistics. */ ioctl( joy_fd, JSIOCGAXES, &axes ); ioctl( joy_fd, JSIOCGBUTTONS, &buttons ); if ( ioctl( joy_fd, JSIOCGNAME( sizeof( name ) ), name ) < 0 ) { strncpy( name, "Unknown", sizeof( name ) ); } Com_Printf( "Name: %s\n", name ); Com_Printf( "Axes: %d\n", axes ); Com_Printf( "Buttons: %d\n", buttons ); /* Our work here is done. */ return; } } /* No soup for you. */ if ( joy_fd == -1 ) { Com_Printf( "No joystick found.\n" ); return; } } void IN_JoyMove( void ) { /* Store instantaneous joystick state. Hack to get around * event model used in Linux joystick driver. */ static int axes_state[16]; /* Old bits for Quake-style input compares. */ static unsigned int old_axes = 0; /* Our current goodies. */ unsigned int axes = 0; int i = 0; if ( joy_fd == -1 ) { return; } /* Empty the queue, dispatching button presses immediately * and updating the instantaneous state for the axes. */ do { int n = -1; struct js_event event; n = read( joy_fd, &event, sizeof( event ) ); if ( n == -1 ) { /* No error, we're non-blocking. */ break; } if ( event.type & JS_EVENT_BUTTON ) { Sys_QueEvent( 0, SE_KEY, K_JOY1 + event.number, event.value, 0, NULL ); } else if ( event.type & JS_EVENT_AXIS ) { if ( event.number >= 16 ) { continue; } axes_state[event.number] = event.value; } else { Com_Printf( "Unknown joystick event type\n" ); } } while ( 1 ); /* Translate our instantaneous state to bits. */ for ( i = 0; i < 16; i++ ) { float f = ( (float) axes_state[i] ) / 32767.0f; if ( f < -joy_threshold->value ) { axes |= ( 1 << ( i * 2 ) ); } else if ( f > joy_threshold->value ) { axes |= ( 1 << ( ( i * 2 ) + 1 ) ); } } /* Time to update axes state based on old vs. new. */ for ( i = 0; i < 16; i++ ) { if ( ( axes & ( 1 << i ) ) && !( old_axes & ( 1 << i ) ) ) { Sys_QueEvent( 0, SE_KEY, joy_keys[i], qtrue, 0, NULL ); } if ( !( axes & ( 1 << i ) ) && ( old_axes & ( 1 << i ) ) ) { Sys_QueEvent( 0, SE_KEY, joy_keys[i], qfalse, 0, NULL ); } } /* Save for future generations. */ old_axes = axes; }