endif()
else(EVENT_INPUT)
set(ENABLE_PLIB_JOYSTICK 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)
+ find_library(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 JS libs")
+ endif()
endif(EVENT_INPUT)
if (MSVC_3RDPARTY_DIR)
endif(LIBSVN_FOUND)
endif(ENABLE_LIBSVN)
-find_package(PLIB REQUIRED puaux pu js fnt)
+find_package(PLIB REQUIRED puaux pu fnt)
find_package(SimGear 2.2.0 REQUIRED)
check_include_file(unistd.h HAVE_UNISTD_H)
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)
- find_library(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)
FGMacOSXEventInput.cxx
)
+set (JS_INPUT_SOURCES
+ js.cxx
+ jsBSD.cxx
+ jsLinux.cxx
+ jsMacOSX.cxx
+ jsWindows.cxx
+ jsNone.cxx
+ )
+
set(SOURCES
FGButton.cxx
FGCommonInput.cxx
FGJoystickInput.cxx
FGKeyboardInput.cxx
FGMouseInput.cxx
- input.cxx
+ input.cxx
)
-
+
+#
+# we still have a dependency on ul from plib!
+
if(EVENT_INPUT)
list(APPEND SOURCES ${EVENT_INPUT_SOURCES})
+else()
+ list(APPEND SOURCES ${JS_INPUT_SOURCES})
endif()
-
+
set(FGJS_SOURCES
fgjs.cxx
jsinput.cxx
endif(WIN32)
target_link_libraries(fgjs
+ fgInput
${SOCKETS_LIBRARY}
${SIMGEAR_LIBRARIES}
${PLIB_LIBRARIES}
+ ${JS_LIBS}
${ZLIB_LIBRARY})
-add_executable(js_demo js_demo.cxx)
+add_executable(js_demo js_demo.cxx )
-target_link_libraries(js_demo
- ${SIMGEAR_LIBRARIES}
+target_link_libraries(js_demo
+ fgInput
+ ${JS_LIBS}
${PLIB_LIBRARIES}
- ${ZLIB_LIBRARY})
+ )
flightgear_component(Input "${SOURCES}")
continue;
}
- const char * name = js->getName();
+ std::string name = js->getName();
SGPropertyNode_ptr js_node = js_nodes->getChild("js", i);
if (js_node) {
if (!js_node || js->notWorking())
continue;
-#ifdef WIN32
- JOYCAPS jsCaps ;
- joyGetDevCaps( i, &jsCaps, sizeof(jsCaps) );
- unsigned int nbuttons = jsCaps.wNumButtons;
+ int nbuttons = js->getNumButtons();
if (nbuttons > MAX_JOYSTICK_BUTTONS) nbuttons = MAX_JOYSTICK_BUTTONS;
-#else
- unsigned int nbuttons = MAX_JOYSTICK_BUTTONS;
-#endif
int naxes = js->getNumAxes();
if (naxes > MAX_JOYSTICK_AXES) naxes = MAX_JOYSTICK_AXES;
#include "FGCommonInput.hxx"
#include "FGButton.hxx"
+#include "FGjs.hxx"
#include <simgear/structure/subsystem_mgr.hxx>
-#include <plib/js.h>
+
////////////////////////////////////////////////////////////////////////
// The Joystick Input Class
--- /dev/null
+/*
+ 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
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> // -dw- for memcpy
+#include <string>
+
+#define _JS_MAX_AXES 16
+#define _JS_MAX_BUTTONS 32
+#define _JS_MAX_HATS 4
+
+class jsJoystick
+{
+ int id ;
+protected:
+ struct os_specific_s *os ;
+ friend struct os_specific_s ;
+ bool error ;
+ std::string name;
+ 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 ;
+ void rawRead ( int *buttons, float *axes ) ;
+
+public:
+
+ jsJoystick ( int ident = 0 ) ;
+ ~jsJoystick () { close () ; }
+
+ std::string getName () const { return name ; }
+ int getNumAxes () const { return num_axes ; }
+ int getNumButtons () const { return num_buttons; }
+ bool notWorking () const { return error ; }
+ void setError () { error = 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 ) ;
+ // bool SetForceFeedBack ( int axe, float force );
+} ;
+
+extern void jsInit () ;
+
+#endif
+
+
js_demo_LDFLAGS = $(plib_FRAMEWORK)
fgjs_LDFLAGS = $(plib_FRAMEWORK)
else
-js_demo_PLIB_LIBS = -lplibjs -lplibul
-fgjs_PLIB_LIBS = -lplibjs -lplibul
js_demo_LDFLAGS =
fgjs_LDFLAGS=
endif
FGMouseInput.cxx FGMouseInput.hxx \
FGKeyboardInput.cxx FGKeyboardInput.hxx \
FGJoystickInput.cxx FGJoystickInput.hxx \
+ js.cxx jsBSD.cxx jsLinux.cxx jsMacOSX.cxx jsNone.cxx FGjs.hxx \
$(libInput_Event_SOURCES)
bin_PROGRAMS = js_demo fgjs
-js_demo_SOURCES = js_demo.cxx
+js_demo_SOURCES = js_demo.cxx
-js_demo_LDADD = $(js_demo_PLIB_LIBS) $(base_LIBS) $(joystick_LIBS)
+js_demo_LDADD = $(base_LIBS) -L. -lInput -lplibul
fgjs_SOURCES = fgjs.cxx jsinput.cxx jsinput.h jssuper.cxx jssuper.h
-fgjs_LDADD = $(js_demo_PLIB_LIBS) $(base_LIBS) $(joystick_LIBS) \
+fgjs_LDADD = $(base_LIBS) $(joystick_LIBS) -L. -lInput -lplibul \
-lsgprops -lsgmisc -lsgio -lsgdebug -lsgstructure -lsgxml -lz $(network_LIBS)
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/Main \
--- /dev/null
+/*
+ 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 "FGjs.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 ) ;
+}
+
+
+
--- /dev/null
+/*
+ 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 2063 2006-01-05 21:21:55Z 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.
+ */
+
+
+#ifdef __FreeBSD__
+
+#include "FGjs.h"
+
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/joystick.h>
+#ifdef HAVE_USB_JS
+
+extern "C" {
+# if __FreeBSD_version < 500000
+# include <libusbhid.h>
+# else
+# define HAVE_USBHID_H 1
+# include <usbhid.h>
+# 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 ] ;
+};
+
+// 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"
+
+/*
+ * 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;
+ (*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);
+}
+
+void jsJoystick::open ()
+{
+ char *cp;
+
+ 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 )
+ {
+ ulSetError ( UL_WARNING, "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 ], ¢er [ 0 ], &max [ 0 ],
+ &min [ 1 ], ¢er [ 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
+ }
+
+ if ( !joy_initialize_hid(os, &num_axes, &num_buttons ) )
+ {
+ ::close(os->fd);
+ error = 1;
+ return;
+ }
+
+ cp = strrchr(os->fname, '/');
+ char tmpname[128];
+ if (cp) {
+ if (findusbdev(&cp[1], tmpname, sizeof(tmpname)) == 0)
+ strcpy(name, &cp[1]);
+ }
+ name = tmpname;
+
+ if ( num_axes > _JS_MAX_AXES )
+ num_axes = _JS_MAX_AXES ;
+
+ for ( int i = 0 ; i < _JS_MAX_AXES ; i++ )
+ {
+ // We really should get this from the HID, but that data seems
+ // to be quite unreliable for analog-to-USB converters. Punt for
+ // now.
+ if ( os->axes_usage [ i ] == HUG_HAT_SWITCH )
+ {
+ max [ i ] = 1.0f ;
+ center [ i ] = 0.0f ;
+ min [ i ] = -1.0f ;
+ }
+ else
+ {
+ max [ i ] = 255.0f ;
+ center [ i ] = 127.0f ;
+ min [ i ] = 0.0f ;
+ }
+ dead_band [ i ] = 0.0f ;
+ saturate [ i ] = 1.0f ;
+ }
+}
+
+void jsJoystick::close ()
+{
+ if (os) {
+ if ( ! error )
+ ::close ( os->fd ) ;
+ if (os->hids)
+ delete os->hids;
+ if (os->hid_data_buf)
+ delete os->hid_data_buf;
+ 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;
+ }
+
+ 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 ) ;
+}
+
+void jsInit () {}
+
+#endif
--- /dev/null
+/*
+ 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 $
+*/
+
+
+#ifdef linux
+
+#include "FGjs.hxx"
+
+#include <linux/joystick.h>
+
+#if defined(JS_VERSION) && JS_VERSION >= 0x010000
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <plib/ul.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 ;
+ char tmpname[256];
+ ioctl ( os->fd, JSIOCGNAME ( sizeof(tmpname) ), tmpname ) ;
+ fcntl ( os->fd, F_SETFL , O_NONBLOCK ) ;
+ name = tmpname;
+ 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:
+ ulSetError ( UL_WARNING, "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
+#endif
--- /dev/null
+/*
+ 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 2118 2007-09-14 22:23:32Z fayjf $
+*/
+
+#ifdef __APPLE__
+
+#include "FGjs.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
+
+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) {
+ ulSetError(UL_WARNING, "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) {
+ ulSetError(UL_WARNING, "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(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"));
+ char tmpname[128];
+ if (!ref || !CFStringGetCString ((CFStringRef) ref, tmpname, sizeof(tmpname), CFStringGetSystemEncoding ())) {
+ ulSetError(UL_WARNING, "error getting device name");
+ tmpname[0] = '\0';
+ }
+ name = tmpname;
+ //printf("Joystick name: %s \n", name);
+ open();
+}
+
+void jsJoystick::open()
+{
+ // create device interface
+ IOReturn rv;
+ SInt32 score;
+ IOCFPlugInInterface **plugin;
+
+ rv = IOCreatePlugInInterfaceForService(ioDevices[id],
+ kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugin, &score);
+
+ if (rv != kIOReturnSuccess) {
+ ulSetError(UL_WARNING, "error creting plugin for io device");
+ return;
+ }
+
+ HRESULT pluginResult = (*plugin)->QueryInterface(plugin,
+ CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID*)&(os->hidDev) );
+
+ if (pluginResult != S_OK)
+ ulSetError(UL_WARNING, "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) {
+ ulSetError(UL_WARNING, "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;
+
+ rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/,
+ &cfProperties, kCFAllocatorDefault, kNilOptions);
+ if (rv != kIOReturnSuccess || !cfProperties) {
+ ulSetError(UL_WARNING, "error getting device properties");
+ return NULL;
+ }
+
+ return cfProperties;
+}
+
+void jsJoystick::close()
+{
+ 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()) {
+ ulSetError(UL_WARNING, "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:
+ ulSetError(UL_WARNING, "input type element has weird usage (%lx)\n", usage);
+ break;
+ }
+ } else if (page == kHIDPage_Button) {
+ //printf(" button\n");
+ /*joy->os->*/addButtonElement(joy, (CFDictionaryRef) element);
+ } else
+ ulSetError(UL_WARNING, "input type element has weird usage (%lx)\n", 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)
+{
+ *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 |= 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;
+ }
+ }
+}
+
+#endif
--- /dev/null
+/*
+ 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 $
+*/
+
+
+#if !defined(linux) && !defined(_WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__)
+#include "FGjs.hxx"
+
+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 () {}
+
+#endif
+
--- /dev/null
+/*
+ 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 2114 2006-12-21 20:53:13Z fayjf $
+*/
+
+#include "FGjs.hxx"
+#include <windows.h>
+#include <regstr.h>
+#include <sstream>
+#include <math.h>
+
+#include <plib/ul.h>
+
+#if defined (_WIN32)
+
+#define _JS_MAX_AXES_WIN 8 /* X,Y,Z,R,U,V,POV_X,POV_Y */
+
+struct os_specific_s {
+ std::string regKey;
+ static std::string getOEMProductName ( jsJoystick* joy);
+};
+
+
+// Inspired by
+// http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
+
+std::string
+os_specific_s::getOEMProductName (jsJoystick* joy)
+{
+ if ( joy->error ) return "" ;
+
+ char charbuf [ 256 ] ;
+
+ HKEY hKey ;
+ DWORD dwcb ;
+ LONG lr ;
+ std::string name;
+
+ // Open .. MediaResources\CurrentJoystickSettings
+ std::string key=REGSTR_PATH_JOYCONFIG;
+ key+= "\\" + joy->os->regKey + "\\" + REGSTR_KEY_JOYCURR;
+
+ bool hkcu = false;
+
+ if ( ERROR_SUCCESS != RegOpenKeyEx ( HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE, &hKey)) {
+ hkcu = true;
+ if ( ERROR_SUCCESS != RegOpenKeyEx ( HKEY_CURRENT_USER, key.c_str(), 0, KEY_QUERY_VALUE, &hKey))
+ return "" ;
+ }
+ // Get OEM Key name
+ dwcb = sizeof( charbuf) ;
+
+ std::ostringstream value;
+ value << "Joystick" << joy->id+1 << REGSTR_VAL_JOYOEMNAME;
+ // JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based.
+
+ lr = RegQueryValueEx ( hKey, value.str().c_str(), 0, 0, (LPBYTE) charbuf, &dwcb);
+ RegCloseKey ( hKey ) ;
+
+ if ( lr != ERROR_SUCCESS ) return "" ;
+
+ // Open OEM Key from ...MediaProperties
+ value.str("");
+ value << REGSTR_PATH_JOYOEM << "\\" << charbuf;
+
+ if (hkcu) {
+ lr = RegOpenKeyEx ( HKEY_CURRENT_USER, value.str().c_str(), 0, KEY_QUERY_VALUE, &hKey ) ;
+ } else {
+ lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, value.str().c_str(), 0, KEY_QUERY_VALUE, &hKey ) ;
+ }
+ if ( lr != ERROR_SUCCESS )
+ return "" ;
+
+ dwcb = sizeof( charbuf) ;
+
+ lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) charbuf, &dwcb ) ;
+ RegCloseKey ( hKey ) ;
+
+ if ( lr != ERROR_SUCCESS ) return "" ;
+ name = std::string( charbuf, dwcb-1);
+ return name;
+}
+
+
+void jsJoystick::open ()
+{
+ JOYCAPS jsCaps ;
+
+ name [0] = '\0' ;
+
+
+
+ memset ( &jsCaps, 0, sizeof(jsCaps)) ;
+
+ error = ( joyGetDevCaps( id, &jsCaps, sizeof(jsCaps) )
+ != JOYERR_NOERROR ) ;
+
+ os->regKey = jsCaps.szRegKey;
+
+ num_buttons = jsCaps.wNumButtons ;
+ if ( 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.
+ name = os->getOEMProductName ( this);
+
+ if (name == "") {
+ ulSetError ( UL_WARNING,
+ "JS: Failed to read joystick name from registry" ) ;
+
+ name = jsCaps.szPname;
+ }
+
+ // Windows joystick drivers may provide any combination of
+ // X,Y,Z,R,U,V,POV - not necessarily the first n of these.
+ if ( 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) jsCaps.wVmin ; max [ 5 ] = (float) jsCaps.wVmax ;
+ min [ 4 ] = (float) jsCaps.wUmin ; max [ 4 ] = (float) jsCaps.wUmax ;
+ min [ 3 ] = (float) jsCaps.wRmin ; max [ 3 ] = (float) jsCaps.wRmax ;
+ min [ 2 ] = (float) jsCaps.wZmin ; max [ 2 ] = (float) jsCaps.wZmax ;
+ min [ 1 ] = (float) jsCaps.wYmin ; max [ 1 ] = (float) jsCaps.wYmax ;
+ min [ 0 ] = (float) jsCaps.wXmin ; max [ 0 ] = (float) 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()) {
+ open();
+ }
+ else {
+ num_axes = 0;
+ setError();
+ }
+}
+
+
+void jsJoystick::rawRead ( int *buttons, float *axes )
+{
+ JOYINFOEX js;
+
+ js.dwFlags = JOY_RETURNALL ;
+ js.dwSize = sizeof ( JOYINFOEX) ;
+
+ if ( error )
+ {
+ if ( buttons )
+ *buttons = 0 ;
+
+ if ( axes )
+ for ( int i = 0 ; i < num_axes ; i++ )
+ axes[i] = 1500.0f ;
+
+ return ;
+ }
+
+
+ MMRESULT status = joyGetPosEx ( id, &js ) ;
+
+ if ( status != JOYERR_NOERROR )
+ {
+ setError() ;
+ return ;
+ }
+
+ if ( buttons != NULL )
+ *buttons = (int) 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 ( ( 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 ( ( js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180 ) ) ;
+ float c = (float) cos ( ( 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) js . dwVpos ;
+ case 5: axes[4] = (float) js . dwUpos ;
+ case 4: axes[3] = (float) js . dwRpos ;
+ case 3: axes[2] = (float) js . dwZpos ;
+ case 2: axes[1] = (float) js . dwYpos ;
+ case 1: axes[0] = (float) js . dwXpos ;
+ break;
+
+ default:
+ ulSetError ( UL_WARNING, "PLIB_JS: Wrong num_axes. Joystick input is now invalid" ) ;
+ }
+ }
+}
+
+void jsInit() {}
+
+#endif
# include <config.h>
#endif
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
+#ifdef _WIN32
+#include <windows.h>
#endif
#include <string.h> // plib/js.h should really include this !!!!!!
-#include <plib/js.h>
+#include "Input/FGjs.hxx"
#define Z 8
{ useful[i] = ! ( js[i]->notWorking () );
if ( useful[i] ) {
t++;
- printf ( "Joystick %i: \"%s\"\n", i, js[i]->getName() ) ;
+ printf ( "Joystick %i: \"%s\"\n", i, js[i]->getName().c_str() ) ;
} else printf ( "Joystick %i not detected\n", i ) ;
}
if ( t == 0 ) exit ( 1 ) ;
#include <simgear/compiler.h>
#include <iostream>
-
+#include <math.h>
using std::cout;
using std::cin;
using std::endl;
#include "jsinput.h"
+#include <plib/ul.h>
jsInput::jsInput(jsSuper *j) {
jss=j;
# include <config.h>
#endif
-#include <string.h> // plib/js.h should really include this !!!!!!
-#include <plib/js.h>
+#include "FGjs.hxx"
#define MAX_JOYSTICKS 8
target_link_libraries(fgfs
${FG_LIBS}
+ ${JS_LIBS}
${SIMGEAR_LIBRARIES}
${OPENSCENEGRAPH_LIBRARIES}
${OPENAL_LIBRARY}
if HAVE_FRAMEWORK_PLIB
fgfs_PLIB_FW = $(plib_FRAMEWORK)
else
-fgfs_PLIB_LIBS = -lplibpuaux -lplibpu -lplibfnt -lplibjs \
+fgfs_PLIB_LIBS = -lplibpuaux -lplibpu -lplibfnt \
-lplibsg -lplibul
endif
${OPENSCENEGRAPH_LIBRARIES}
${OPENGL_LIBRARIES}
${ZLIB_LIBRARIES}
- ${PLIB_LIBRARIES})
+ ${PLIB_LIBRARIES}
+ ${JS_LIBS})
install(TARGETS fgviewer RUNTIME DESTINATION bin)