1
0
Fork 0

Import PLIB JS code into FlightGear

- will permit bug-fixing which cannot occur for
  official PLIB.
This commit is contained in:
James Turner 2016-01-12 22:44:28 -06:00
parent 50518862fe
commit 102fe04e91
18 changed files with 1802 additions and 68 deletions

View file

@ -30,6 +30,10 @@ if (ENABLE_HID_INPUT)
add_subdirectory(hidapi)
endif()
if (ENABLE_PLIB_JOYSTICK)
add_subdirectory(joystick)
endif()
if (NOT SYSTEM_CPPUNIT)
add_subdirectory(cppunit)
endif()

44
3rdparty/joystick/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,44 @@
message(STATUS "Enabling legacy joystick code (from PLIB)")
if(APPLE)
# resolve frameworks to full paths
find_library(IOKIT_LIBRARY IOKit)
find_library(CF_LIBRARY CoreFoundation)
set(JS_LIBS ${IOKIT_LIBRARY} ${CF_LIBRARY})
set(JS_SOURCES js.cxx jsMacOSX.cxx)
elseif(WIN32)
set(WINMM_LIBRARY winmm)
set(JS_LIBS ${WINMM_LIBRARY})
set(JS_SOURCES js.cxx jsWindows.cxx)
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(JS_SOURCES js.cxx jsLinux.cxx)
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
find_library(USBHID_LIBRARY usbhid)
# check_function_exists(hidinit)
set(JS_LIBS ${USBHID_LIBRARY})
set(JS_SOURCES js.cxx jsBSD.cxx)
else()
message(WARNING "Unsupported platform for Joystick")
set(JS_SOURCES js.cxx jsNone.cxx)
endif()
add_library(PLIBJoystick STATIC ${JS_SOURCES})
# for logging code at least, more in the future
target_link_libraries(PLIBJoystick SimGearCore)
if(APPLE)
target_link_libraries(PLIBJoystick ${IOKIT_LIBRARY} ${CF_LIBRARY} )
elseif(WIN32)
target_link_libraries(PLIBJoystick ${WINMM_LIBRARY})
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
# no libs here?
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
target_link_libraries(PLIBJoystick ${USBHID_LIBRARY})
else()
# other / none platform
endif()
target_include_directories(PLIBJoystick PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# eof

92
3rdparty/joystick/js.cxx vendored Normal file
View file

@ -0,0 +1,92 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
*/
#include "config.h"
#include "js.h"
#include <simgear/debug/logstream.hxx>
float jsJoystick::fudge_axis ( float value, int axis ) const
{
if ( value < center[axis] )
{
float xx = ( value - center[ axis ] ) /
( center [ axis ] - min [ axis ] ) ;
if ( xx < -saturate [ axis ] )
return -1.0f ;
if ( xx > -dead_band [ axis ] )
return 0.0f ;
xx = ( xx + dead_band [ axis ] ) /
( saturate [ axis ] - dead_band [ axis ] ) ;
return ( xx < -1.0f ) ? -1.0f : xx ;
}
else
{
float xx = ( value - center [ axis ] ) /
( max [ axis ] - center [ axis ] ) ;
if ( xx > saturate [ axis ] )
return 1.0f ;
if ( xx < dead_band [ axis ] )
return 0.0f ;
xx = ( xx - dead_band [ axis ] ) /
( saturate [ axis ] - dead_band [ axis ] ) ;
return ( xx > 1.0f ) ? 1.0f : xx ;
}
}
void jsJoystick::read ( int *buttons, float *axes )
{
if ( error )
{
if ( buttons )
*buttons = 0 ;
if ( axes )
for ( int i = 0 ; i < num_axes ; i++ )
axes[i] = 0.0f ;
return ;
}
float raw_axes [ _JS_MAX_AXES ] ;
rawRead ( buttons, raw_axes ) ;
if ( axes )
for ( int i = 0 ; i < num_axes ; i++ )
axes[i] = fudge_axis ( raw_axes[i], i ) ;
}
void jsSetError(int level, const std::string& msg)
{
SG_LOG(SG_INPUT, static_cast<sgDebugPriority>(level), msg);
}

96
3rdparty/joystick/js.h vendored Normal file
View file

@ -0,0 +1,96 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: js.h 2067 2006-01-30 07:36:01Z bram $
*/
#ifndef __INCLUDED_JS_H__
#define __INCLUDED_JS_H__ 1
#define JS_NEW
#include <string>
#include <cstring>
#include <cstdlib>
#define _JS_MAX_AXES 16
#define _JS_MAX_BUTTONS 32
#define _JS_MAX_HATS 4
#define JS_TRUE 1
#define JS_FALSE 0
class jsJoystick
{
int id ;
protected:
struct os_specific_s *os ;
friend struct os_specific_s ;
int error ;
char name [ 128 ] ;
int num_axes ;
int num_buttons ;
float dead_band [ _JS_MAX_AXES ] ;
float saturate [ _JS_MAX_AXES ] ;
float center [ _JS_MAX_AXES ] ;
float max [ _JS_MAX_AXES ] ;
float min [ _JS_MAX_AXES ] ;
void open () ;
void close () ;
float fudge_axis ( float value, int axis ) const ;
public:
jsJoystick ( int ident = 0 ) ;
~jsJoystick () { close () ; }
const char* getName () const { return name ; }
int getNumAxes () const { return num_axes ; }
int getNumButtons () const { return num_buttons; }
int notWorking () const { return error ; }
void setError () { error = JS_TRUE ; }
float getDeadBand ( int axis ) const { return dead_band [ axis ] ; }
void setDeadBand ( int axis, float db ) { dead_band [ axis ] = db ; }
float getSaturation ( int axis ) const { return saturate [ axis ] ; }
void setSaturation ( int axis, float st ) { saturate [ axis ] = st ; }
void setMinRange ( float *axes ) { memcpy ( min , axes, num_axes * sizeof(float) ) ; }
void setMaxRange ( float *axes ) { memcpy ( max , axes, num_axes * sizeof(float) ) ; }
void setCenter ( float *axes ) { memcpy ( center, axes, num_axes * sizeof(float) ) ; }
void getMinRange ( float *axes ) const { memcpy ( axes, min , num_axes * sizeof(float) ) ; }
void getMaxRange ( float *axes ) const { memcpy ( axes, max , num_axes * sizeof(float) ) ; }
void getCenter ( float *axes ) const { memcpy ( axes, center, num_axes * sizeof(float) ) ; }
void read ( int *buttons, float *axes ) ;
void rawRead ( int *buttons, float *axes ) ;
// bool SetForceFeedBack ( int axe, float force );
} ;
extern void jsInit () ;
void jsSetError(int, const std::string& msg);
#endif

518
3rdparty/joystick/jsBSD.cxx vendored Normal file
View file

@ -0,0 +1,518 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: jsBSD.cxx 2133 2008-07-18 14:32:22Z fayjf $
*/
/*
* Inspired by the X-Mame USB HID joystick driver for NetBSD and
* FreeBSD by Krister Walfridsson <cato@df.lth.se>.
* Incorporates the original analog joystick driver for BSD by
* Stephen Montgomery-Smith <stephen@math.missouri.edu>, with
* NetBSD mods courtesy of Rene Hexel.
*
* Bert Driehuis <driehuis@playbeing.org>
*
* Notes:
* Hats are mapped to two axes for now. A cleaner implementation requires
* an API extension, and to be useful for my devious purposes, FlightGear
* would need to understand that.
*/
#include "js.h"
#if defined(__NetBSD__) || defined(__FreeBSD__)
#define HAVE_USB_JS 1
#endif
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#if defined(__FreeBSD__)
# include <sys/joystick.h>
#else
# include <machine/joystick.h> // For analog joysticks
#endif
#ifdef HAVE_USB_JS
#if defined(__NetBSD__)
#ifdef HAVE_USBHID_H
#include <usbhid.h>
#else
#include <usb.h>
#endif
#elif defined(__FreeBSD__)
extern "C" {
# if __FreeBSD_version < 500000
# include <libusbhid.h>
# else
# define HAVE_USBHID_H 1
# include <usbhid.h>
# endif
}
#endif
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
/* Compatibility with older usb.h revisions */
#if !defined(USB_MAX_DEVNAMES) && defined(MAXDEVNAMES)
#define USB_MAX_DEVNAMES MAXDEVNAMES
#endif
#endif
static int hatmap_x[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 };
static int hatmap_y[9] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 };
struct os_specific_s {
char fname [128 ];
int fd;
int is_analog;
// The following structure members are specific to analog joysticks
struct joystick ajs;
#ifdef HAVE_USB_JS
// The following structure members are specific to USB joysticks
struct hid_item *hids;
int hid_dlen;
int hid_offset;
char *hid_data_buf;
int axes_usage [ _JS_MAX_AXES ] ;
#endif
// We keep button and axes state ourselves, as they might not be updated
// on every read of a USB device
int cache_buttons ;
float cache_axes [ _JS_MAX_AXES ] ;
float axes_minimum [ _JS_MAX_AXES ] ;
float axes_maximum [ _JS_MAX_AXES ] ;
};
// Idents lower than USB_IDENT_OFFSET are for analog joysticks.
#define USB_IDENT_OFFSET 2
#define USBDEV "/dev/usb"
#define UHIDDEV "/dev/uhid"
#define AJSDEV "/dev/joy"
#ifdef HAVE_USB_JS
/*
* findusbdev (and its helper, walkusbdev) try to locate the full name
* of a USB device. If /dev/usbN isn't readable, we punt and return the
* uhidN device name. We warn the user of this situation once.
*/
static char *
walkusbdev(int f, char *dev, char *out, int outlen)
{
struct usb_device_info di;
int i, a;
char *cp;
for (a = 1; a < USB_MAX_DEVICES; a++) {
di.udi_addr = a;
if (ioctl(f, USB_DEVICEINFO, &di) != 0)
return NULL;
for (i = 0; i < USB_MAX_DEVNAMES; i++)
if (di.udi_devnames[i][0] &&
strcmp(di.udi_devnames[i], dev) == 0) {
cp = new char[strlen(di.udi_vendor) + strlen(di.udi_product) + 2];
strcpy(cp, di.udi_vendor);
strcat(cp, " ");
strcat(cp, di.udi_product);
strncpy(out, cp, outlen - 1);
out[outlen - 1] = 0;
delete cp;
return out;
}
}
return NULL;
}
static int
findusbdev(char *name, char *out, int outlen)
{
int i, f;
char buf[50];
char *cp;
static int protection_warned = 0;
for (i = 0; i < 16; i++) {
sprintf(buf, "%s%d", USBDEV, i);
f = open(buf, O_RDONLY);
if (f >= 0) {
cp = walkusbdev(f, name, out, outlen);
close(f);
if (cp)
return 1;
} else if (errno == EACCES) {
if (!protection_warned) {
fprintf(stderr, "Can't open %s for read!\n",
buf);
protection_warned = 1;
}
}
}
return 0;
}
static int joy_initialize_hid(struct os_specific_s *os,
int *num_axes, int *num_buttons)
{
int size, is_joystick;
#ifdef HAVE_USBHID_H
int report_id = 0;
#endif
struct hid_data *d;
struct hid_item h;
report_desc_t rd;
if ((rd = hid_get_report_desc(os->fd)) == 0)
{
fprintf(stderr, "error: %s: %s", os->fname, strerror(errno));
return FALSE;
}
os->hids = NULL;
#ifdef HAVE_USBHID_H
if (ioctl(os->fd, USB_GET_REPORT_ID, &report_id) < 0)
{
fprintf(stderr, "error: %s: %s", os->fname, strerror(errno));
return FALSE;
}
size = hid_report_size(rd, hid_input, report_id);
#else
size = hid_report_size(rd, 0, hid_input);
#endif
os->hid_data_buf = new char[size];
os->hid_dlen = size;
is_joystick = 0;
#ifdef HAVE_USBHID_H
d = hid_start_parse(rd, 1 << hid_input, report_id);
#else
d = hid_start_parse(rd, 1 << hid_input);
#endif
while (hid_get_item(d, &h))
{
int usage, page, interesting_hid;
page = HID_PAGE(h.usage);
usage = HID_USAGE(h.usage);
/* This test is somewhat too simplistic, but this is how MicroSoft
* does, so I guess it works for all joysticks/game pads. */
is_joystick = is_joystick ||
(h.kind == hid_collection &&
page == HUP_GENERIC_DESKTOP &&
(usage == HUG_JOYSTICK || usage == HUG_GAME_PAD));
if (h.kind != hid_input)
continue;
if (!is_joystick)
continue;
interesting_hid = TRUE;
if (page == HUP_GENERIC_DESKTOP)
{
switch(usage) {
case HUG_X:
case HUG_RX:
case HUG_Y:
case HUG_RY:
case HUG_Z:
case HUG_RZ:
case HUG_SLIDER:
if (*num_axes < _JS_MAX_AXES)
{
os->axes_usage[*num_axes] = usage;
os->axes_minimum[*num_axes] = h.logical_minimum;
os->axes_maximum[*num_axes] = h.logical_maximum;
(*num_axes)++;
}
break;
case HUG_HAT_SWITCH:
if (*num_axes + 1 < _JS_MAX_AXES) // Allocate two axes for a hat
{
os->axes_usage[*num_axes] = usage;
(*num_axes)++;
os->axes_usage[*num_axes] = usage;
(*num_axes)++;
}
break;
default:
interesting_hid = FALSE;
}
}
else if (page == HUP_BUTTON)
{
interesting_hid = (usage > 0) && (usage <= _JS_MAX_BUTTONS);
if (interesting_hid && usage - 1 > *num_buttons)
{
*num_buttons = usage - 1;
}
}
if (interesting_hid)
{
h.next = os->hids;
os->hids = new struct hid_item;
*os->hids = h;
}
}
hid_end_parse(d);
return (os->hids != NULL);
}
#endif
void jsJoystick::open ()
{
char *cp;
name [0] = '\0' ;
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
os->cache_axes [ i ] = 0.0f ;
os->cache_buttons = 0 ;
os->fd = ::open ( os->fname, O_RDONLY | O_NONBLOCK) ;
if (os->fd < 0 && errno == EACCES)
fprintf(stderr, "%s exists but is not readable by you\n", os->fname);
error = ( os->fd < 0 ) ;
if ( error )
return ;
num_axes = 0;
num_buttons = 0;
if ( os->is_analog )
{
num_axes = 2 ;
num_buttons = 32 ;
FILE *joyfile ;
char joyfname [ 1024 ] ;
int noargs, in_no_axes ;
float axes [ _JS_MAX_AXES ] ;
int buttons [ _JS_MAX_AXES ] ;
rawRead ( buttons, axes ) ;
error = axes[0] < -1000000000.0f && axes[1] < -1000000000.0f ;
if ( error )
return ;
sprintf( joyfname, "%s/.joy%drc", ::getenv ( "HOME" ), id ) ;
joyfile = fopen ( joyfname, "r" ) ;
error = ( joyfile == NULL ) ;
if ( error )
{
jsSetError ( SG_WARN, "unable to open calibration file %s (%s), joystick %i disabled (you can generate the calibration file with the plib-jscal utility)",
joyfname, strerror ( errno ), id + 1 );
return ;
}
noargs = fscanf ( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
&min [ 0 ], &center [ 0 ], &max [ 0 ],
&min [ 1 ], &center [ 1 ], &max [ 1 ] ) ;
error = noargs != 7 || in_no_axes != _JS_MAX_AXES ;
fclose ( joyfile ) ;
if ( error )
return ;
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
{
dead_band [ i ] = 0.0f ;
saturate [ i ] = 1.0f ;
}
return; // End of analog code
}
#ifdef HAVE_USB_JS
if ( !joy_initialize_hid(os, &num_axes, &num_buttons ) )
{
::close(os->fd);
error = 1;
return;
}
cp = strrchr(os->fname, '/');
if (cp) {
if (findusbdev(&cp[1], name, sizeof(name)) == 0)
strcpy(name, &cp[1]);
}
if ( num_axes > _JS_MAX_AXES )
num_axes = _JS_MAX_AXES ;
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
{
if ( os->axes_usage [ i ] == HUG_HAT_SWITCH )
{
max [ i ] = 1.0f ;
center [ i ] = 0.0f ;
min [ i ] = -1.0f ;
}
else
{
max [ i ] = os->axes_maximum [ i ];
min [ i ] = os->axes_minimum [ i ];
center [ i ] = (max [ i ] + min [ i ]) / 2;
}
dead_band [ i ] = 0.0f ;
saturate [ i ] = 1.0f ;
}
#endif
}
void jsJoystick::close ()
{
if (os) {
if ( ! error )
::close ( os->fd ) ;
#ifdef HAVE_USB_JS
if (os->hids)
delete os->hids;
if (os->hid_data_buf)
delete os->hid_data_buf;
#endif
delete os;
}
}
jsJoystick::jsJoystick ( int ident )
{
id = ident ;
error = 0;
os = new struct os_specific_s;
memset(os, 0, sizeof(struct os_specific_s));
if (ident < USB_IDENT_OFFSET)
os->is_analog = 1;
if (os->is_analog)
sprintf(os->fname, "%s%d", AJSDEV, ident);
else
sprintf(os->fname, "%s%d", UHIDDEV, ident - USB_IDENT_OFFSET);
open () ;
}
void jsJoystick::rawRead ( int *buttons, float *axes )
{
int len, usage, page, d;
struct hid_item *h;
if ( error )
{
if ( buttons )
*buttons = 0 ;
if ( axes )
for ( int i = 0 ; i < num_axes ; i++ )
axes[i] = 1500.0f ;
return ;
}
if ( os->is_analog )
{
int status = ::read ( os->fd, &os->ajs, sizeof(os->ajs) );
if ( status != sizeof(os->ajs) ) {
perror ( os->fname ) ;
setError () ;
return ;
}
if ( buttons != NULL )
*buttons = ( os->ajs.b1 ? 1 : 0 ) | ( os->ajs.b2 ? 2 : 0 ) ;
if ( axes != NULL )
{
if ( os->ajs.x >= -1000000000 )
os->cache_axes[0] = os->ajs.x;
if ( os->ajs.y >= -1000000000 )
os->cache_axes[1] = os->ajs.y;
axes[0] = os->cache_axes[0];
axes[1] = os->cache_axes[1];
}
return;
}
#ifdef HAVE_USB_JS
while ((len = ::read(os->fd, os->hid_data_buf, os->hid_dlen)) == os->hid_dlen)
{
for (h = os->hids; h; h = h->next)
{
d = hid_get_data(os->hid_data_buf, h);
page = HID_PAGE(h->usage);
usage = HID_USAGE(h->usage);
if (page == HUP_GENERIC_DESKTOP)
{
for (int i = 0; i < num_axes; i++)
if (os->axes_usage[i] == usage)
{
if (usage == HUG_HAT_SWITCH)
{
if (d < 0 || d > 8)
d = 0; // safety
os->cache_axes[i] = (float)hatmap_x[d];
os->cache_axes[i + 1] = (float)hatmap_y[d];
}
else
{
os->cache_axes[i] = (float)d;
}
break;
}
}
else if (page == HUP_BUTTON)
{
if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
{
if (d)
os->cache_buttons |= (1 << usage - 1) ;
else
os->cache_buttons &= ~(1 << usage - 1) ;
}
}
}
}
if (len < 0 && errno != EAGAIN)
{
perror( os->fname ) ;
setError () ;
error = 1;
}
if ( buttons != NULL ) *buttons = os->cache_buttons ;
if ( axes != NULL )
memcpy ( axes, os->cache_axes, sizeof(float) * num_axes ) ;
#endif
}
void jsInit () {}

202
3rdparty/joystick/jsLinux.cxx vendored Normal file
View file

@ -0,0 +1,202 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: jsLinux.cxx 2017 2005-02-21 07:37:25Z bram $
*/
#include "js.h"
#include <unistd.h>
#include <linux/joystick.h>
#include <simgear/debug/logstream.hxx>
#if defined(JS_VERSION) && JS_VERSION >= 0x010000
#include <sys/param.h>
#include <fcntl.h>
#include <sys/ioctl.h>
struct os_specific_s {
js_event js ;
int tmp_buttons ;
float tmp_axes [ _JS_MAX_AXES ] ;
char fname [ 128 ] ;
int fd ;
};
void jsInit () {}
void jsJoystick::open ()
{
name [0] = '\0' ;
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
os->tmp_axes [ i ] = 0.0f ;
os->tmp_buttons = 0 ;
os->fd = ::open ( os->fname, O_RDONLY ) ;
error = ( os->fd < 0 ) ;
if ( error )
return ;
/*
Set the correct number of axes for the linux driver
*/
/* Melchior Franz's fixes for big-endian Linuxes since writing
* to the upper byte of an uninitialized word doesn't work.
* 9 April 2003
*/
unsigned char u ;
ioctl ( os->fd, JSIOCGAXES , &u ) ;
num_axes = u ;
ioctl ( os->fd, JSIOCGBUTTONS, &u ) ;
num_buttons = u ;
ioctl ( os->fd, JSIOCGNAME ( sizeof(name) ), name ) ;
fcntl ( os->fd, F_SETFL , O_NONBLOCK ) ;
int all_axes = num_axes;
if ( num_axes > _JS_MAX_AXES )
num_axes = _JS_MAX_AXES ;
// Remove any deadband value already done in the kernel.
// Since we have our own deadband management this is save to do so.
struct js_corr* corr = new js_corr[ all_axes ] ;
ioctl ( os->fd, JSIOCGCORR, corr );
for ( int i = 0; i < num_axes ; ++i ) {
if ( corr[ i ] . type == JS_CORR_BROKEN ) {
int nodeadband = ( corr[ i ] . coef[ 0 ] + corr[ i ] . coef[ 1 ] ) / 2 ;
corr[ i ] . coef[ 0 ] = nodeadband ;
corr[ i ] . coef[ 1 ] = nodeadband ;
}
}
ioctl ( os->fd, JSIOCSCORR, corr );
delete [] corr;
for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
{
max [ i ] = 32767.0f ;
center [ i ] = 0.0f ;
min [ i ] = -32767.0f ;
dead_band [ i ] = 0.0f ;
saturate [ i ] = 1.0f ;
}
}
void jsJoystick::close ()
{
if ( ! error )
::close ( os->fd ) ;
delete os;
}
jsJoystick::jsJoystick ( int ident )
{
id = ident ;
os = new struct os_specific_s;
sprintf ( os->fname, "/dev/input/js%d", ident ) ;
if ( access ( os->fname, F_OK ) != 0 )
sprintf ( os->fname, "/dev/js%d", ident ) ;
open () ;
}
void jsJoystick::rawRead ( int *buttons, float *axes )
{
if ( error )
{
if ( buttons )
*buttons = 0 ;
if ( axes )
for ( int i = 0 ; i < num_axes ; i++ )
axes[i] = 1500.0f ;
return ;
}
while (1)
{
int status = ::read ( os->fd, &(os->js), sizeof(js_event) ) ;
if ( status != sizeof(js_event) )
{
/* use the old values */
if ( buttons != NULL ) *buttons = os->tmp_buttons ;
if ( axes != NULL )
memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ;
if ( errno == EAGAIN )
return ;
perror( os->fname ) ;
setError () ;
return ;
}
switch ( os->js.type & ~JS_EVENT_INIT )
{
case JS_EVENT_BUTTON :
if ( os->js.value == 0 ) /* clear the flag */
os->tmp_buttons &= ~(1 << os->js.number) ;
else
os->tmp_buttons |= (1 << os->js.number) ;
break ;
case JS_EVENT_AXIS:
if ( os->js.number < num_axes )
{
os->tmp_axes [ os->js.number ] = (float) os->js.value ;
if ( axes )
memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ;
}
break ;
default:
jsSetError ( SG_WARN, "PLIB_JS: Unrecognised /dev/js return!?!" ) ;
/* use the old values */
if ( buttons != NULL ) *buttons = os->tmp_buttons ;
if ( axes != NULL )
memcpy ( axes, os->tmp_axes, sizeof(float) * num_axes ) ;
return ;
}
if ( buttons != NULL )
*buttons = os->tmp_buttons ;
}
}
#endif

464
3rdparty/joystick/jsMacOSX.cxx vendored Normal file
View file

@ -0,0 +1,464 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: jsMacOSX.cxx 2165 2011-01-22 22:56:03Z fayjf $
*/
#include "js.h"
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
#include <mach/mach_error.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/IOCFPlugIn.h>
#include <CoreFoundation/CoreFoundation.h>
#ifdef MACOS_10_0_4
# include <IOKit/hidsystem/IOHIDUsageTables.h>
#else
/* The header was moved here in MacOS X 10.1 */
# include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
#endif
#include <simgear/debug/logstream.hxx>
static const int kNumDevices = 32;
static int numDevices = -1;
static io_object_t ioDevices[kNumDevices];
static int NS_hat[8] = {1, 1, 0, -1, -1, -1, 0, 1};
static int WE_hat[8] = {0, 1, 1, 1, 0, -1, -1, -1};
struct os_specific_s {
IOHIDDeviceInterface ** hidDev;
IOHIDElementCookie buttonCookies[41];
IOHIDElementCookie axisCookies[_JS_MAX_AXES];
IOHIDElementCookie hatCookies[_JS_MAX_HATS];
int num_hats;
long hat_min[_JS_MAX_HATS];
long hat_max[_JS_MAX_HATS];
void enumerateElements(jsJoystick* joy, CFTypeRef element);
static void elementEnumerator( const void *element, void* vjs);
/// callback for CFArrayApply
void parseElement(jsJoystick* joy, CFDictionaryRef element);
void addAxisElement(jsJoystick* joy, CFDictionaryRef axis);
void addButtonElement(jsJoystick* joy, CFDictionaryRef button);
void addHatElement(jsJoystick* joy, CFDictionaryRef hat);
};
static void findDevices(mach_port_t);
static CFDictionaryRef getCFProperties(io_object_t);
void jsInit()
{
if (numDevices < 0) {
numDevices = 0;
mach_port_t masterPort;
IOReturn rv = IOMasterPort(bootstrap_port, &masterPort);
if (rv != kIOReturnSuccess) {
jsSetError(SG_WARN, "error getting master Mach port");
return;
}
findDevices(masterPort);
}
}
/** open the IOKit connection, enumerate all the HID devices, add their
interface references to the static array. We then use the array index
as the device number when we come to open() the joystick. */
static void findDevices(mach_port_t masterPort)
{
CFMutableDictionaryRef hidMatch = NULL;
IOReturn rv = kIOReturnSuccess;
io_iterator_t hidIterator;
// build a dictionary matching HID devices
hidMatch = IOServiceMatching(kIOHIDDeviceKey);
rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator);
if (rv != kIOReturnSuccess || !hidIterator) {
jsSetError(SG_WARN, "no joystick (HID) devices found");
return;
}
// iterate
io_object_t ioDev;
while ((ioDev = IOIteratorNext(hidIterator))) {
// filter out keyboard and mouse devices
CFDictionaryRef properties = getCFProperties(ioDev);
long usage, page;
CFTypeRef refPage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsagePageKey));
CFTypeRef refUsage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsageKey));
CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage);
CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page);
// keep only joystick devices
if ( (page == kHIDPage_GenericDesktop) &&
((usage == kHIDUsage_GD_Joystick) ||
(usage == kHIDUsage_GD_GamePad)
// || (usage == kHIDUsage_GD_MultiAxisController)
// || (usage == kHIDUsage_GD_Hatswitch)
)
)
{
// add it to the array
ioDevices[numDevices++] = ioDev;
}
}
IOObjectRelease(hidIterator);
}
jsJoystick::jsJoystick(int ident) :
id(ident),
os(NULL),
error(JS_FALSE),
num_axes(0),
num_buttons(0)
{
if (ident >= numDevices) {
setError();
return;
}
os = new struct os_specific_s;
os->num_hats = 0;
// get the name now too
CFDictionaryRef properties = getCFProperties(ioDevices[id]);
CFTypeRef ref = CFDictionaryGetValue (properties, CFSTR(kIOHIDProductKey));
if (!ref)
ref = CFDictionaryGetValue (properties, CFSTR("USB Product Name"));
if (!ref || !CFStringGetCString ((CFStringRef) ref, name, 128, CFStringGetSystemEncoding ())) {
jsSetError(SG_WARN, "error getting device name");
name[0] = '\0';
}
//printf("Joystick name: %s \n", name);
open();
}
void jsJoystick::open()
{
#if 0 // test already done in the constructor
if (id >= numDevices) {
jsSetError(SG_WARN, "device index out of range in jsJoystick::open");
return;
}
#endif
// create device interface
IOReturn rv;
SInt32 score;
IOCFPlugInInterface **plugin;
rv = IOCreatePlugInInterfaceForService(ioDevices[id],
kIOHIDDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugin, &score);
if (rv != kIOReturnSuccess) {
jsSetError(SG_WARN, "error creting plugin for io device");
return;
}
HRESULT pluginResult = (*plugin)->QueryInterface(plugin,
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID*)&(os->hidDev) );
if (pluginResult != S_OK)
jsSetError(SG_WARN, "QI-ing IO plugin to HID Device interface failed");
(*plugin)->Release(plugin); // don't leak a ref
if (os->hidDev == NULL) return;
// store the interface in this instance
rv = (*(os->hidDev))->open(os->hidDev, 0);
if (rv != kIOReturnSuccess) {
jsSetError(SG_WARN, "error opening device interface");
return;
}
CFDictionaryRef props = getCFProperties(ioDevices[id]);
// recursively enumerate all the bits (buttons, axes, hats, ...)
CFTypeRef topLevelElement =
CFDictionaryGetValue (props, CFSTR(kIOHIDElementKey));
os->enumerateElements(this, topLevelElement);
CFRelease(props);
// for hats to be implemented as axes: must be the last axes:
for (int h = 0; h<2*os->num_hats; h++)
{
int index = num_axes++;
dead_band [ index ] = 0.0f ;
saturate [ index ] = 1.0f ;
center [ index ] = 0.0f;
max [ index ] = 1.0f;
min [ index ] = -1.0f;
}
}
CFDictionaryRef getCFProperties(io_object_t ioDev)
{
IOReturn rv;
CFMutableDictionaryRef cfProperties;
#if 0
// comment copied from darwin/SDL_sysjoystick.c
/* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
* get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
*/
io_registry_entry_t parent1, parent2;
rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1);
if (rv != kIOReturnSuccess) {
jsSetError(SG_WARN, "error getting device entry parent");
return NULL;
}
rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2);
if (rv != kIOReturnSuccess) {
jsSetError(SG_WARN, "error getting device entry parent 2");
return NULL;
}
#endif
rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/,
&cfProperties, kCFAllocatorDefault, kNilOptions);
if (rv != kIOReturnSuccess || !cfProperties) {
jsSetError(SG_WARN, "error getting device properties");
return NULL;
}
return cfProperties;
}
void jsJoystick::close()
{
if (!os)
return;
if (os->hidDev != NULL) (*(os->hidDev))->close(os->hidDev);
if (os) delete os;
}
/** element enumerator function : pass NULL for top-level*/
void os_specific_s::enumerateElements(jsJoystick* joy, CFTypeRef element)
{
assert(CFGetTypeID(element) == CFArrayGetTypeID());
CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)};
CFArrayApplyFunction((CFArrayRef) element, range,
&elementEnumerator, joy);
}
void os_specific_s::elementEnumerator( const void *element, void* vjs)
{
if (CFGetTypeID((CFTypeRef) element) != CFDictionaryGetTypeID()) {
jsSetError(SG_WARN, "element enumerator passed non-dictionary value");
return;
}
static_cast<jsJoystick*>(vjs)->
os->parseElement( static_cast<jsJoystick*>(vjs), (CFDictionaryRef) element);
}
void os_specific_s::parseElement(jsJoystick* joy, CFDictionaryRef element)
{
CFTypeRef refPage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsagePageKey));
CFTypeRef refUsage = CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementUsageKey));
long type, page, usage;
CFNumberGetValue((CFNumberRef)
CFDictionaryGetValue ((CFDictionaryRef) element, CFSTR(kIOHIDElementTypeKey)),
kCFNumberLongType, &type);
switch (type) {
case kIOHIDElementTypeInput_Misc:
case kIOHIDElementTypeInput_Axis:
case kIOHIDElementTypeInput_Button:
//printf("got input element...");
CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage);
CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page);
if (page == kHIDPage_GenericDesktop) {
switch (usage) /* look at usage to determine function */
{
case kHIDUsage_GD_X:
case kHIDUsage_GD_Y:
case kHIDUsage_GD_Z:
case kHIDUsage_GD_Rx:
case kHIDUsage_GD_Ry:
case kHIDUsage_GD_Rz:
case kHIDUsage_GD_Slider: // for throttle / trim controls
case kHIDUsage_GD_Dial:
//printf(" axis\n");
/*joy->os->*/addAxisElement(joy, (CFDictionaryRef) element);
break;
case kHIDUsage_GD_Hatswitch:
//printf(" hat\n");
/*joy->os->*/addHatElement(joy, (CFDictionaryRef) element);
break;
default:
SG_LOG(SG_INPUT, SG_WARN, "input type element has weird usage:" << usage);
break;
}
} else if (page == kHIDPage_Simulation) {
switch (usage) /* look at usage to determine function */
{
case kHIDUsage_Sim_Rudder:
case kHIDUsage_Sim_Throttle:
//printf(" axis\n");
/*joy->os->*/addAxisElement(joy, (CFDictionaryRef) element);
break;
default:
SG_LOG(SG_INPUT, SG_WARN, "Simulation page input type element has weird usage:" << usage);
}
} else if (page == kHIDPage_Button) {
//printf(" button\n");
/*joy->os->*/addButtonElement(joy, (CFDictionaryRef) element);
} else if (page == kHIDPage_PID) {
SG_LOG(SG_INPUT, SG_WARN, "Force feedback and related data ignored");
} else
SG_LOG(SG_INPUT, SG_WARN, "input type element has weird usage:" << usage);
break;
case kIOHIDElementTypeCollection:
/*joy->os->*/enumerateElements(joy,
CFDictionaryGetValue(element, CFSTR(kIOHIDElementKey))
);
break;
default:
break;
}
}
void os_specific_s::addAxisElement(jsJoystick* joy, CFDictionaryRef axis)
{
long cookie, lmin, lmax;
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (axis, CFSTR(kIOHIDElementCookieKey)),
kCFNumberLongType, &cookie);
int index = joy->num_axes++;
/*joy->os->*/axisCookies[index] = (IOHIDElementCookie) cookie;
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (axis, CFSTR(kIOHIDElementMinKey)),
kCFNumberLongType, &lmin);
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (axis, CFSTR(kIOHIDElementMaxKey)),
kCFNumberLongType, &lmax);
joy->min[index] = lmin;
joy->max[index] = lmax;
joy->dead_band[index] = 0.0;
joy->saturate[index] = 1.0;
joy->center[index] = (lmax - lmin) * 0.5 + lmin;
}
void os_specific_s::addButtonElement(jsJoystick* joy, CFDictionaryRef button)
{
long cookie;
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (button, CFSTR(kIOHIDElementCookieKey)),
kCFNumberLongType, &cookie);
/*joy->os->*/buttonCookies[joy->num_buttons++] = (IOHIDElementCookie) cookie;
// anything else for buttons?
}
void os_specific_s::addHatElement(jsJoystick* joy, CFDictionaryRef hat)
{
long cookie, lmin, lmax;
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (hat, CFSTR(kIOHIDElementCookieKey)),
kCFNumberLongType, &cookie);
int index = /*joy->*/num_hats++;
/*joy->os->*/hatCookies[index] = (IOHIDElementCookie) cookie;
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (hat, CFSTR(kIOHIDElementMinKey)),
kCFNumberLongType, &lmin);
CFNumberGetValue ((CFNumberRef)
CFDictionaryGetValue (hat, CFSTR(kIOHIDElementMaxKey)),
kCFNumberLongType, &lmax);
hat_min[index] = lmin;
hat_max[index] = lmax;
// do we map hats to axes or buttons?
// axes; there is room for that: Buttons are limited to 32.
// (a joystick with 2 hats will use 16 buttons!)
}
void jsJoystick::rawRead(int *buttons, float *axes)
{
if (buttons)
*buttons = 0;
IOHIDEventStruct hidEvent;
for (int b=0; b<num_buttons; ++b) {
(*(os->hidDev))->getElementValue(os->hidDev, os->buttonCookies[b], &hidEvent);
if (hidEvent.value && buttons)
*buttons |= 1 << b;
}
// real axes:
int real_num_axes = num_axes - 2*os->num_hats;
for (int a=0; a<real_num_axes; ++a) {
(*(os->hidDev))->getElementValue(os->hidDev, os->axisCookies[a], &hidEvent);
axes[a] = hidEvent.value;
}
// hats:
for (int h=0; h < os->num_hats; ++h) {
(*(os->hidDev))->getElementValue(os->hidDev, os->hatCookies[h], &hidEvent);
long result = ( hidEvent.value - os->hat_min[h] ) * 8;
result /= ( os->hat_max[h] - os->hat_min[h] + 1 );
if ( (result>=0) && (result<8) )
{
axes[h+real_num_axes+1] = NS_hat[result];
axes[h+real_num_axes] = WE_hat[result];
}
else
{
axes[h+real_num_axes] = 0;
axes[h+real_num_axes+1] = 0;
}
}
}

54
3rdparty/joystick/jsNone.cxx vendored Normal file
View file

@ -0,0 +1,54 @@
/*
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: jsNone.cxx 1960 2004-09-21 11:45:55Z smokydiamond $
*/
#include "js.h"
struct os_specific_s ;
void jsJoystick::open ()
{
error = TRUE ;
num_axes = num_buttons = 0 ;
}
void jsJoystick::close ()
{
error = TRUE ;
}
jsJoystick::jsJoystick ( int ident )
{
error = TRUE ;
num_axes = num_buttons = 0 ;
os = NULL;
}
void jsJoystick::rawRead ( int *buttons, float *axes )
{
if ( buttons != NULL ) *buttons = 0 ;
}
void jsInit () {}

274
3rdparty/joystick/jsWindows.cxx vendored Normal file
View file

@ -0,0 +1,274 @@
/*
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information visit http://plib.sourceforge.net
$Id: jsWindows.cxx 2164 2011-01-22 22:47:30Z fayjf $
*/
#include "js.h"
#include <Windows.h>
#include <cstring>
#include <RegStr.h> // for REGSTR_PATH_JOYCONFIG, etc
#define _JS_MAX_AXES_WIN 8 /* X,Y,Z,R,U,V,POV_X,POV_Y */
struct os_specific_s {
JOYCAPS jsCaps ;
JOYINFOEX js ;
UINT js_id ;
static bool getOEMProductName ( jsJoystick* joy, char *buf, int buf_sz ) ;
};
// Inspired by
// http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
bool os_specific_s::getOEMProductName ( jsJoystick* joy, char *buf, int buf_sz )
{
if ( joy->error ) return false ;
union
{
char key [ 256 ] ;
char value [ 256 ] ;
} ;
char OEMKey [ 256 ] ;
HKEY hKey ;
DWORD dwcb ;
LONG lr ;
int hkcu = 0;
// Open .. MediaResources\CurrentJoystickSettings
sprintf ( key, "%s\\%s\\%s",
REGSTR_PATH_JOYCONFIG, joy->os->jsCaps.szRegKey,
REGSTR_KEY_JOYCURR ) ;
lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, &hKey) ;
if ( lr != ERROR_SUCCESS )
{
hkcu = 1;
// XP/Vista/7 seem to have moved it to "current user"
lr = RegOpenKeyEx ( HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &hKey) ;
if ( lr != ERROR_SUCCESS ) return false ;
}
// Get OEM Key name
dwcb = sizeof(OEMKey) ;
// JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based.
sprintf ( value, "Joystick%d%s", joy->os->js_id + 1, REGSTR_VAL_JOYOEMNAME ) ;
lr = RegQueryValueEx ( hKey, value, 0, 0, (LPBYTE) OEMKey, &dwcb);
RegCloseKey ( hKey ) ;
if ( lr != ERROR_SUCCESS ) return false ;
// Open OEM Key from ...MediaProperties
sprintf ( key, "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey ) ;
if (!hkcu)
lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, &hKey) ;
else
lr = RegOpenKeyEx ( HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &hKey) ;
if ( lr != ERROR_SUCCESS )
{
return false ;
}
// Get OEM Name
dwcb = buf_sz ;
lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,
&dwcb ) ;
RegCloseKey ( hKey ) ;
if ( lr != ERROR_SUCCESS ) return false ;
return true ;
}
void jsJoystick::open ()
{
name [0] = '\0' ;
os->js . dwFlags = JOY_RETURNALL ;
os->js . dwSize = sizeof ( os->js ) ;
memset ( &(os->jsCaps), 0, sizeof(os->jsCaps) ) ;
error = ( joyGetDevCaps( os->js_id, &(os->jsCaps), sizeof(os->jsCaps) )
!= JOYERR_NOERROR ) ;
num_buttons = os->jsCaps.wNumButtons ;
if ( os->jsCaps.wNumAxes == 0 )
{
num_axes = 0 ;
setError () ;
}
else
{
// Device name from jsCaps is often "Microsoft PC-joystick driver",
// at least for USB. Try to get the real name from the registry.
if ( ! os->getOEMProductName ( this, name, sizeof(name) ) )
{
jsSetError ( SG_WARN,
"JS: Failed to read joystick name from registry" ) ;
strncpy ( name, os->jsCaps.szPname, sizeof(name) ) ;
}
// Windows joystick drivers may provide any combination of
// X,Y,Z,R,U,V,POV - not necessarily the first n of these.
if ( os->jsCaps.wCaps & JOYCAPS_HASPOV )
{
num_axes = _JS_MAX_AXES_WIN ;
min [ 7 ] = -1.0 ; max [ 7 ] = 1.0 ; // POV Y
min [ 6 ] = -1.0 ; max [ 6 ] = 1.0 ; // POV X
}
else
num_axes = 6 ;
min [ 5 ] = (float) os->jsCaps.wVmin ; max [ 5 ] = (float) os->jsCaps.wVmax ;
min [ 4 ] = (float) os->jsCaps.wUmin ; max [ 4 ] = (float) os->jsCaps.wUmax ;
min [ 3 ] = (float) os->jsCaps.wRmin ; max [ 3 ] = (float) os->jsCaps.wRmax ;
min [ 2 ] = (float) os->jsCaps.wZmin ; max [ 2 ] = (float) os->jsCaps.wZmax ;
min [ 1 ] = (float) os->jsCaps.wYmin ; max [ 1 ] = (float) os->jsCaps.wYmax ;
min [ 0 ] = (float) os->jsCaps.wXmin ; max [ 0 ] = (float) os->jsCaps.wXmax ;
}
for ( int i = 0 ; i < num_axes ; i++ )
{
center [ i ] = ( max[i] + min[i] ) / 2.0f ;
dead_band [ i ] = 0.0f ;
saturate [ i ] = 1.0f ;
}
}
void jsJoystick::close ()
{
delete os;
}
jsJoystick::jsJoystick ( int ident )
{
id = ident ;
os = new struct os_specific_s;
if (ident >= 0 && ident < (int)joyGetNumDevs()) {
os->js_id = JOYSTICKID1 + ident;
open();
}
else {
num_axes = 0;
setError();
}
}
void jsJoystick::rawRead ( int *buttons, float *axes )
{
if ( error )
{
if ( buttons )
*buttons = 0 ;
if ( axes )
for ( int i = 0 ; i < num_axes ; i++ )
axes[i] = 1500.0f ;
return ;
}
MMRESULT status = joyGetPosEx ( os->js_id, &(os->js) ) ;
if ( status != JOYERR_NOERROR )
{
setError() ;
return ;
}
if ( buttons != NULL )
*buttons = (int) os->js.dwButtons ;
if ( axes != NULL )
{
/* WARNING - Fall through case clauses!! */
switch ( num_axes )
{
case 8:
// Generate two POV axes from the POV hat angle.
// Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in
// hundredths of a degree, or 0xFFFF when idle.
if ( ( os->js.dwPOV & 0xFFFF ) == 0xFFFF )
{
axes [ 6 ] = 0.0 ;
axes [ 7 ] = 0.0 ;
}
else
{
// This is the contentious bit: how to convert angle to X/Y.
// wk: I know of no define for PI that we could use here:
// SG_PI would pull in sg, M_PI is undefined for MSVC
// But the accuracy of the value of PI is very unimportant at
// this point.
float s = (float) sin ( ( os->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180 ) ) ;
float c = (float) cos ( ( os->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180 ) ) ;
// Convert to coordinates on a square so that North-East
// is (1,1) not (.7,.7), etc.
// s and c cannot both be zero so we won't divide by zero.
if ( fabs ( s ) < fabs ( c ) )
{
axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ;
axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f ;
}
else
{
axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f ;
axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ;
}
}
case 6: axes[5] = (float) os->js . dwVpos ;
case 5: axes[4] = (float) os->js . dwUpos ;
case 4: axes[3] = (float) os->js . dwRpos ;
case 3: axes[2] = (float) os->js . dwZpos ;
case 2: axes[1] = (float) os->js . dwYpos ;
case 1: axes[0] = (float) os->js . dwXpos ;
break;
default:
jsSetError ( SG_WARN, "PLIB_JS: Wrong num_axes. Joystick input is now invalid" ) ;
}
}
}
void jsInit() {}

View file

@ -222,7 +222,10 @@ option(ENABLE_QT "Set to ON to build the internal Qt launcher" ON)
option(ENABLE_TRAFFIC "Set to ON to build the external traffic generator modules" ON)
option(ENABLE_FGQCANVAS "Set to ON to build the Qt-based remote canvas application" OFF)
option(ENABLE_DEMCONVERT "Set to ON to build the dem conversion tool (default)" ON)
option(ENABLE_HID_INPUT "Set to ON to build HID-based input code (default)" OFF)
option(ENABLE_HID_INPUT "Set to ON to build HID-based input code" OFF)
option(ENABLE_PLIB_JOYSTICK "Set to ON to enable legacy joystick code (default)" ON)
# Test-suite options.
option(ENABLE_AUTOTESTING "Set to ON to execute the test suite after building the test_suite target (default)" ON)
@ -281,12 +284,6 @@ if(EVENT_INPUT)
message(STATUS "Enabling HID-API input")
list(APPEND EVENT_INPUT_LIBRARIES hidapi)
endif()
# Keep PLIB INPUT enabled as long as EventInput does not replace current joystick configurations.
set(ENABLE_PLIB_JOYSTICK 1)
else(EVENT_INPUT)
message(STATUS "Event-based input disabled by config")
set(ENABLE_PLIB_JOYSTICK 1)
endif(EVENT_INPUT)
# check required dependencies
@ -404,7 +401,7 @@ else()
endif (ENABLE_QT)
##############################################################################
find_package(PLIB REQUIRED puaux pu js fnt)
find_package(PLIB REQUIRED puaux pu fnt)
# FlightGear and SimGear versions need to match major + minor
# split version string into components, note CMAKE_MATCH_0 is the entire regexp match

View file

@ -1,7 +1,7 @@
# Locate PLIB
# This module defines
# PLIB_LIBRARIES
# PLIB_FOUND, if false, do not try to link to PLIB
# PLIB_FOUND, if false, do not try to link to PLIB
# PLIB_INCLUDE_DIR, where to find the headers
#
# $PLIBDIR is an environment variable that would
@ -28,14 +28,14 @@ include(SelectLibraryConfigurations)
set(save_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
set(CMAKE_FIND_FRAMEWORK ONLY)
FIND_PATH(PLIB_INCLUDE_DIR ul.h
PATH_SUFFIXES include/plib include
PATH_SUFFIXES include/plib include
PATHS ${ADDITIONAL_LIBRARY_PATHS}
)
set(CMAKE_FIND_FRAMEWORK ${save_FIND_FRAMEWORK})
if(NOT PLIB_INCLUDE_DIR)
FIND_PATH(PLIB_INCLUDE_DIR plib/ul.h
PATH_SUFFIXES include
PATH_SUFFIXES include
HINTS $ENV{PLIBDIR}
PATHS ${ADDITIONAL_LIBRARY_PATHS}
)
@ -51,7 +51,7 @@ FIND_LIBRARY(PLIB_LIBRARIES
PATHS ${ADDITIONAL_LIBRARY_PATHS}
)
if (MSVC)
if (MSVC)
set (PUNAME "pui")
else (MSVC)
set (PUNAME "pu")
@ -65,7 +65,7 @@ macro(find_static_component comp libs)
else(MSVC)
set(compLib "plib${comp}")
endif(MSVC)
string(TOUPPER "PLIB_${comp}" compLibBase)
set( compLibName ${compLibBase}_LIBRARY )
@ -97,13 +97,13 @@ macro(find_static_component comp libs)
endif()
endmacro()
if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND")
if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND")
set(PLIB_LIBRARIES "") # clear value
# based on the contents of deps, add other required PLIB
# static library dependencies. Eg PUI requires FNT
set(outDeps ${PLIB_FIND_COMPONENTS})
foreach(c ${PLIB_FIND_COMPONENTS})
if (${c} STREQUAL "pu")
# handle MSVC confusion over pu/pui naming, by removing
@ -116,7 +116,7 @@ if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND")
list(APPEND outDeps "sg")
endif()
endforeach()
list(APPEND outDeps "ul") # everything needs ul
list(REMOVE_DUPLICATES outDeps) # clean up
@ -127,30 +127,5 @@ if(${PLIB_LIBRARIES} STREQUAL "PLIB_LIBRARIES-NOTFOUND")
endforeach()
endif()
list(FIND outDeps "js" haveJs)
if(${haveJs} GREATER -1)
message(STATUS "adding runtime JS dependencies")
if(APPLE)
# resolve frameworks to full paths
find_library(IOKIT_LIBRARY IOKit)
find_library(CF_LIBRARY CoreFoundation)
set(JS_LIBS ${IOKIT_LIBRARY} ${CF_LIBRARY})
elseif(WIN32)
set(WINMM_LIBRARY winmm)
set(JS_LIBS ${WINMM_LIBRARY})
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
# anything needed here?
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
find_library(USBHID_LIBRARY usbhid)
# check_function_exists(hidinit)
set(JS_LIBS ${USBHID_LIBRARY})
else()
message(WARNING "Unsupported platform for PLIB JS libs")
endif()
list(APPEND PLIB_LIBRARIES ${JS_LIBS})
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PLIB DEFAULT_MSG PLIB_LIBRARIES PLIB_INCLUDE_DIR)

View file

@ -56,6 +56,9 @@ function(setup_fgfs_libraries target)
${SIMGEAR_LIBRARIES}
)
if (ENABLE_PLIB_JOYSTICK)
target_link_libraries(${target} PLIBJoystick)
endif()
if(ENABLE_FLITE)
if(SYSTEM_HTS_ENGINE)

View file

@ -51,6 +51,7 @@
#cmakedefine ENABLE_FLITE
#cmakedefine ENABLE_HID_INPUT
#cmakedefine ENABLE_PLIB_JOYSTICK
#cmakedefine HAVE_QT

View file

@ -15,13 +15,11 @@ if (ENABLE_HID_INPUT)
list(APPEND EVENT_INPUT_HEADERS FGHIDEventInput.hxx)
endif()
set(SOURCES
FGButton.cxx
FGCommonInput.cxx
FGDeviceConfigurationMap.cxx
FGEventInput.cxx
FGJoystickInput.cxx
FGKeyboardInput.cxx
FGMouseInput.cxx
input.cxx
@ -32,19 +30,23 @@ set(HEADERS
FGCommonInput.hxx
FGDeviceConfigurationMap.hxx
FGEventInput.hxx
FGJoystickInput.hxx
FGKeyboardInput.hxx
FGMouseInput.hxx
input.hxx
)
if (ENABLE_PLIB_JOYSTICK)
list(APPEND SOURCES FGJoystickInput.cxx)
list(APPEND HEADERS FGJoystickInput.hxx)
endif()
if(EVENT_INPUT)
list(APPEND SOURCES ${EVENT_INPUT_SOURCES})
list(APPEND SOURCES ${EVENT_INPUT_HEADERS})
list(APPEND HEADERS ${EVENT_INPUT_HEADERS})
include_directories(${UDEV_INCLUDE_DIR})
endif()
if(ENABLE_FGJS)
if(ENABLE_FGJS AND ENABLE_PLIB_JOYSTICK)
set(FGJS_SOURCES
fgjs.cxx
jsinput.cxx
@ -53,18 +55,18 @@ if(ENABLE_FGJS)
add_executable(fgjs ${FGJS_SOURCES})
target_link_libraries(fgjs
SimGearCore
${PLIB_LIBRARIES}
SimGearCore
PLIBJoystick
)
install(TARGETS fgjs RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(ENABLE_JS_DEMO)
if(ENABLE_JS_DEMO AND ENABLE_PLIB_JOYSTICK)
add_executable(js_demo js_demo.cxx)
target_link_libraries(js_demo
SimGearCore
${PLIB_LIBRARIES}
PLIBJoystick
)
install(TARGETS js_demo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View file

@ -31,7 +31,10 @@
#include <Main/fg_props.hxx>
#include "FGMouseInput.hxx"
#include "FGKeyboardInput.hxx"
#if defined(ENABLE_PLIB_JOYSTICK)
#include "FGJoystickInput.hxx"
#endif
#ifdef WITH_EVENTINPUT
#if defined( SG_WINDOWS )
@ -71,11 +74,14 @@ FGInput::FGInput ()
set_subsystem( "input-keyboard", new FGKeyboardInput() );
}
#if defined(ENABLE_PLIB_JOYSTICK)
if( fgGetBool("/sim/input/no-joystick-input",false) ) {
SG_LOG(SG_INPUT,SG_ALERT,"Joystick input disabled!");
} else {
set_subsystem( "input-joystick", new FGJoystickInput() );
}
#endif
#ifdef INPUTEVENT_CLASS
if( fgGetBool("/sim/input/no-event-input",false) ) {
SG_LOG(SG_INPUT,SG_ALERT,"Event input disabled!");

View file

@ -28,6 +28,8 @@ using std::endl;
#include "jsinput.h"
#include <simgear/timing/timestamp.hxx>
jsInput::jsInput(jsSuper *j) {
jss=j;
pretty_display=true;
@ -109,7 +111,7 @@ int jsInput::getInput() {
fflush ( stdout ) ;
}
ulMilliSecondSleep(1);
SGTimeStamp::sleepForMSec(1);
}
if(button_bits != 0) {
for(int i=0;i<=31;i++) {
@ -138,12 +140,12 @@ void jsInput::findDeadBand() {
}
} while( jss->nextJoystick() );
ulClock clock;
SGTimeStamp clock = SGTimeStamp::now();
cout << 10;
cout.flush();
for (int j = 9; j >= 0; j--) {
double start_time = clock.getAbsTime();
clock.stamp();
do {
jss->firstJoystick();
do {
@ -159,9 +161,8 @@ void jsInput::findDeadBand() {
} while( jss->nextJoystick());
ulMilliSecondSleep(1);
clock.update();
} while (clock.getAbsTime() - start_time < 1.0);
SGTimeStamp::sleepForMSec(1);
} while (clock.elapsedMSec() < 1000);
cout << " - " << j;
cout.flush();

View file

@ -23,6 +23,8 @@
#ifndef _JSINPUT_H
#define _JSINPUT_H
#include <cmath> // for fabs
#include "jssuper.h"
class jsInput {

View file

@ -25,8 +25,7 @@
# include <config.h>
#endif
#include <string.h> // plib/js.h should really include this !!!!!!
#include <plib/js.h>
#include "js.h"
#define MAX_JOYSTICKS 8
@ -37,28 +36,28 @@ class jsSuper {
int currentJoystick;
int first, last;
jsJoystick* js[MAX_JOYSTICKS];
public:
public:
jsSuper(void);
~jsSuper(void);
inline int getNumJoysticks(void) { return activeJoysticks; }
inline int atFirst(void) { return currentJoystick == first; }
inline int atLast(void) { return currentJoystick == last; }
inline void firstJoystick(void) { currentJoystick=first; }
inline void lastJoystick(void) { currentJoystick=last; }
int nextJoystick(void);
int prevJoystick(void);
inline jsJoystick* getJoystick(int Joystick)
inline jsJoystick* getJoystick(int Joystick)
{ currentJoystick=Joystick; return js[Joystick]; }
inline jsJoystick* getJoystick(void) { return js[currentJoystick]; }
inline int getCurrentJoystickId(void) { return currentJoystick; }
};
#endif
#endif