* Many thanks for Steve Baker for permission to pull from that library.
*/
-#if defined( __FreeBSD__ ) || defined( __NetBSD__ )
-# include <sys/param.h>
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
#include <GL/freeglut.h>
#include "freeglut_internal.h"
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
/*
* Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c"
* interspersed
*/
-#define _JS_MAX_BUTTONS 32
+/* XXX It might be better to poll the operating system for the numbers of buttons and
+ * XXX axes and then dynamically allocate the arrays.
+ */
+#define _JS_MAX_BUTTONS 32
#if TARGET_HOST_MACINTOSH
# define _JS_MAX_AXES 9
# define _JS_MAX_AXES 8
# include <windows.h>
# include <mmsystem.h>
-# include <string.h>
# include <regstr.h>
#endif
#if TARGET_HOST_UNIX_X11
# define _JS_MAX_AXES 16
+# if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+# if HAVE_FCNTL_H
+# include <fcntl.h>
+# endif
+# include <errno.h>
# if defined(__FreeBSD__) || defined(__NetBSD__)
/* XXX The below hack is done until freeglut's autoconf is updated. */
# define HAVE_USB_JS 1
-# include <sys/ioctl.h>
# if defined(__FreeBSD__) && __FreeBSD_version >= 500000
# include <sys/joystick.h>
# else
# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
# endif
-# include <unistd.h>
-# include <fcntl.h>
-# include <errno.h>
-
# if defined(__linux__)
-# include <sys/ioctl.h>
# include <linux/joystick.h>
/* check the joystick driver version */
return 1;
} else if (errno == EACCES) {
if (!protection_warned) {
- fprintf(stderr, "Can't open %s for read!\n",
- buf);
+ fgWarning ( "Can't open %s for read!", buf );
protection_warned = 1;
}
}
if ( ( rd = hid_get_report_desc( os->fd ) ) == 0 )
{
- fprintf( stderr, "error: %s: %s", os->fname, strerror( errno ) );
+ fgWarning ( "error: %s: %s", os->fname, strerror( errno ) );
return FALSE;
}
if( ioctl( os->fd, USB_GET_REPORT_ID, &report_id ) < 0)
{
/*** XXX {report_id} may not be the right variable? ***/
- fprintf( stderr, "error: %s%d: %s",
- UHIDDEV, report_id, strerror( errno ) );
+ fgWarning ( "error: %s%d: %s", UHIDDEV, report_id, strerror( errno ) );
return FALSE;
}
static void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element );
/* callback for CFArrayApply */
static void fghJoystickElementEnumerator ( SFG_Joystick* joy, void *element, void* vjs );
-static void fghJoystickParseElement ( SFG_Joystick* joy, CFDictionaryRef element );
static void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis );
static void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button );
* The static joystick structure pointer
*/
#define MAX_NUM_JOYSTICKS 2
-static int fgNumberOfJoysticks = 0;
static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
break;
default:
- fgWarning ( "%s", "PLIB_JS: Unrecognised /dev/js return!?!" );
+ fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" );
/* use the old values */
rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator);
if (rv != kIOReturnSuccess || !hidIterator) {
- fgWarning( "%s", "no joystick (HID) devices found" );
+ fgWarning( "no joystick (HID) devices found" );
return;
}
rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1);
if (rv != kIOReturnSuccess) {
- fgWarning ( "%s", "error getting device entry parent");
+ fgWarning ( "error getting device entry parent");
return NULL;
}
rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2);
if (rv != kIOReturnSuccess) {
- fgWarning ( "%s", "error getting device entry parent 2");
+ fgWarning ( "error getting device entry parent 2");
return NULL;
}
#endif
rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/,
&cfProperties, kCFAllocatorDefault, kNilOptions);
if (rv != kIOReturnSuccess || !cfProperties) {
- fgWarning ( "%s", "error getting device properties");
+ fgWarning ( "error getting device properties");
return NULL;
}
/** element enumerator function : pass NULL for top-level*/
static void fghJoystickEnumerateElements ( SFG_Joystick *joy, CFTypeRef element )
{
- assert(CFGetTypeID(element) == CFArrayGetTypeID());
+ FREEGLUT_INTERNAL_ERROR_EXIT( (CFGetTypeID(element) == CFArrayGetTypeID(),
+ "Joystick element type mismatch",
+ "fghJoystickEnumerateElements" );
CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)};
CFArrayApplyFunction((CFArrayRef) element, range,
&fghJoystickElementEnumerator, joy );
}
-static void fghJoystickParseElement ( SFG_Joystick *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 ( typ e) {
- 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 */
- printf(" axis\n");
- fghJoystickAddAxisElement((CFDictionaryRef) element);
- break;
-
- case kHIDUsage_GD_Hatswitch:
- printf(" hat\n");
- fghJoystickAddHatElement((CFDictionaryRef) element);
- break;
-
- default:
- printf("input type element has weird usage (%x)\n", usage);
- break;
- }
- } else if (page == kHIDPage_Button) {
- printf(" button\n");
- fghJoystickAddButtonElement((CFDictionaryRef) element);
- } else
- printf("input type element has weird page (%x)\n", page);
- break;
-
- case kIOHIDElementTypeCollection:
- fghJoystickEnumerateElements (
- CFDictionaryGetValue ( element, CFSTR(kIOHIDElementKey) )
- );
- break;
-
- default:
- break;
- }
-}
-
static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis )
{
long cookie, lmin, lmax;
#if TARGET_HOST_MAC_OSX
if( joy->id >= numDevices )
{
- fgWarning( "%s", "device index out of range in fgJoystickOpen()" );
+ fgWarning( "device index out of range in fgJoystickOpen()" );
return;
}
if( rv != kIOReturnSuccess )
{
- fgWarning( "%s", "error creating plugin for io device" );
+ fgWarning( "error creating plugin for io device" );
return;
}
);
if( pluginResult != S_OK )
- fgWarning ( "%s", "QI-ing IO plugin to HID Device interface failed" );
+ fgWarning ( "QI-ing IO plugin to HID Device interface failed" );
( *plugin )->Release( plugin ); /* don't leak a ref */
if( joy->hidDev == NULL )
joy->os->fd = open( joy->os->fname, O_RDONLY | O_NONBLOCK);
if( joy->os->fd < 0 && errno == EACCES )
- fgWarning ( "%s exists but is not readable by you\n", joy->os->fname );
+ fgWarning ( "%s exists but is not readable by you", joy->os->fname );
joy->error =( joy->os->fd < 0 );
/*
* This function replaces the constructor method in the JS library.
*/
-void fgJoystickInit( int ident )
+static void fghJoystickInit( int ident )
{
if( ident >= MAX_NUM_JOYSTICKS )
- fgError( "Too large a joystick number" );
+ fgError( "Too large a joystick number: %d", ident );
if( fgJoystick[ ident ] )
- fgError( "illegal attempt to initialize joystick device" );
+ fgError( "illegal attempt to initialize joystick device again" );
fgJoystick[ ident ] =
( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 );
IOReturn rv = IOMasterPort( bootstrap_port, &masterPort );
if( rv != kIOReturnSuccess )
{
- fgWarning( "%s", "error getting master Mach port" );
+ fgWarning( "error getting master Mach port" );
return;
}
fghJoystickFindDevices( masterPort );
!CFStringGetCString( ( CFStringRef )ref, name, 128,
CFStringGetSystemEncoding( ) ) )
{
- fgWarning( "%s", "error getting device name" );
+ fgWarning( "error getting device name" );
name[ 0 ] = '\0';
}
#endif
}
/*
+ * Try initializing all the joysticks (well, both of them)
+ */
+void fgInitialiseJoysticks ( void )
+{
+ /* Initialization courtesy of OpenGLUT -- do we want it? */
+ if( !fgState.JoysticksInitialised )
+ {
+ int ident ;
+ for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+ fghJoystickInit( ident );
+
+ fgState.JoysticksInitialised = GL_TRUE;
+ }
+}
+
+/*
*
*/
void fgJoystickClose( void )
}
/*
- * PWO: These jsJoystick class methods have not been implemented.
+ * Implementation for glutDeviceGet(GLUT_HAS_JOYSTICK)
+ */
+int fgJoystickDetect( void )
+{
+ int ident;
+
+ fgInitialiseJoysticks ();
+
+ if ( !fgJoystick )
+ return 0;
+
+ if ( !fgState.JoysticksInitialised )
+ return 0;
+
+ for( ident=0; ident<MAX_NUM_JOYSTICKS; ident++ )
+ if( fgJoystick[ident] && !fgJoystick[ident]->error )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Joystick information functions
*/
int glutJoystickGetNumAxes( int ident )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumAxes" );
return fgJoystick[ ident ]->num_axes;
}
+int glutJoystickGetNumButtons( int ident )
+{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumButtons" );
+ return fgJoystick[ ident ]->num_buttons;
+}
int glutJoystickNotWorking( int ident )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickNotWorking" );
return fgJoystick[ ident ]->error;
}
float glutJoystickGetDeadBand( int ident, int axis )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetDeadBand" );
return fgJoystick[ ident ]->dead_band [ axis ];
}
void glutJoystickSetDeadBand( int ident, int axis, float db )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetDeadBand" );
fgJoystick[ ident ]->dead_band[ axis ] = db;
}
float glutJoystickGetSaturation( int ident, int axis )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetSaturation" );
return fgJoystick[ ident ]->saturate[ axis ];
}
void glutJoystickSetSaturation( int ident, int axis, float st )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetSaturation" );
fgJoystick[ ident ]->saturate [ axis ] = st;
}
void glutJoystickSetMinRange( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMinRange" );
memcpy( fgJoystick[ ident ]->min, axes,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}
void glutJoystickSetMaxRange( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMaxRange" );
memcpy( fgJoystick[ ident ]->max, axes,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}
void glutJoystickSetCenter( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetCenter" );
memcpy( fgJoystick[ ident ]->center, axes,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}
void glutJoystickGetMinRange( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMinRange" );
memcpy( axes, fgJoystick[ ident ]->min,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}
void glutJoystickGetMaxRange( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMaxRange" );
memcpy( axes, fgJoystick[ ident ]->max,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}
void glutJoystickGetCenter( int ident, float *axes )
{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetCenter" );
memcpy( axes, fgJoystick[ ident ]->center,
fgJoystick[ ident ]->num_axes * sizeof( float ) );
}