/*
===========================================================================
Return to Castle Wolfenstein multiplayer GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
RTCW MP 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 MP 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 MP Source Code. If not, see .
In addition, the RTCW MP 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 MP 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_Printf( "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;
}