Allowing recent change to build on older versions of MSVC per e-mail from Eero Pajarr...
[freeglut] / src / freeglut_joystick.c
index 185ef1b..91fe226 100644 (file)
  *  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"
+#ifdef 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
 #    include <IOKit/hid/IOHIDLib.h>
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
 #    define _JS_MAX_AXES  8
 #    include <windows.h>
 #    include <mmsystem.h>
-#    include <string.h>
 #    include <regstr.h>
 
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    define _JS_MAX_AXES 16
+#    ifdef HAVE_SYS_IOCTL_H
+#        include <sys/ioctl.h>
+#    endif
+#    ifdef HAVE_FCNTL_H
+#        include <fcntl.h>
+#    endif
+#    ifdef HAVE_ERRNO_H
+#        include <errno.h>
+#        include <string.h>
+#    endif
 #    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
+#        if defined(__FreeBSD__)
 #            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 */
@@ -232,19 +233,22 @@ static int fghJoystickFindUSBdev(char *name, char *out, int outlen)
   static int protection_warned = 0;
 
   for (i = 0; i < 16; i++) {
-    sprintf(buf, "%s%d", USBDEV, i);
+    snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
     f = open(buf, O_RDONLY);
     if (f >= 0) {
       cp = fghJoystickWalkUSBdev(f, name, out, outlen);
       close(f);
       if (cp)
         return 1;
-    } else if (errno == EACCES) {
+    }
+#ifdef HAVE_ERRNO_H
+    else if (errno == EACCES) {
       if (!protection_warned) {
         fgWarning ( "Can't open %s for read!", buf );
         protection_warned = 1;
       }
     }
+#endif
   }
   return 0;
 }
@@ -262,7 +266,11 @@ static int fghJoystickInitializeHID(struct os_specific_s *os,
 
     if ( ( rd = hid_get_report_desc( os->fd ) ) == 0 )
     {
+#ifdef HAVE_ERRNO_H
         fgWarning ( "error: %s: %s", os->fname, strerror( errno ) );
+#else
+        fgWarning ( "error: %s", os->fname );
+#endif
         return FALSE;
     }
 
@@ -272,7 +280,11 @@ static int fghJoystickInitializeHID(struct os_specific_s *os,
         if( ioctl( os->fd, USB_GET_REPORT_ID, &report_id ) < 0)
         {
             /*** XXX {report_id} may not be the right variable? ***/
+#ifdef HAVE_ERRNO_H
             fgWarning ( "error: %s%d: %s", UHIDDEV, report_id, strerror( errno ) );
+#else
+            fgWarning ( "error: %s%d", UHIDDEV, report_id );
+#endif
             return FALSE;
         }
 
@@ -387,14 +399,14 @@ struct tagSFG_Joystick
          maxReport[_JS_MAX_AXES];
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     JOYCAPS     jsCaps;
     JOYINFOEX   js;
     UINT        js_id;
 #endif
 
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #   if defined(__FreeBSD__) || defined(__NetBSD__)
        struct os_specific_s *os;
 #   endif
@@ -438,7 +450,6 @@ static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick* joy, io_object
 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 );
@@ -458,7 +469,7 @@ static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
  */
 static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
 {
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     MMRESULT status;
 #else
     int status;
@@ -534,7 +545,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
     }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     status = joyGetPosEx( joy->js_id, &joy->js );
 
     if ( status != JOYERR_NOERROR )
@@ -600,7 +611,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    if defined(__FreeBSD__) || defined(__NetBSD__)
     if ( joy->os->is_analog )
     {
@@ -659,14 +670,18 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
                if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
                {
                    if (d)
-                       joy->os->cache_buttons |= (1 << usage - 1);
+                       joy->os->cache_buttons |=  (1 << ( usage - 1 ));
                    else
-                       joy->os->cache_buttons &= ~(1 << usage - 1);
+                       joy->os->cache_buttons &= ~(1 << ( usage - 1 ));
                }
             }
         }
     }
+#ifdef HAVE_ERRNO_H
     if ( len < 0 && errno != EAGAIN )
+#else
+    if ( len < 0 )
+#endif
     {
         perror( joy->os->fname );
         joy->error = 1;
@@ -685,6 +700,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
 
         if ( status != sizeof( struct js_event ) )
         {
+#ifdef HAVE_ERRNO_H
             if ( errno == EAGAIN )
             {
                 /* Use the old values */
@@ -695,6 +711,7 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
                             sizeof( float ) * joy->num_axes );
                 return;
             }
+#endif
 
             fgWarning ( "%s", joy->fname );
             joy->error = GL_TRUE;
@@ -925,73 +942,15 @@ static void fghJoystickElementEnumerator ( SFG_Joystick *joy, void *element, voi
 /** 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:
-                fgWarning ( "input type element has weird usage (%x)", usage);
-                break;
-            }
-        } else if (page == kHIDPage_Button) {
-            printf(" button\n");
-            fghJoystickAddButtonElement((CFDictionaryRef) element);
-        } else
-            fgWarning ( "input type element has weird page (%x)", page);
-        break;
-
-    case kIOHIDElementTypeCollection:
-        fghJoystickEnumerateElements (
-            CFDictionaryGetValue ( element, CFSTR(kIOHIDElementKey) )
-        );
-        break;
-
-    default:
-        break;
-    }
-}
-
 static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis )
 {
     long cookie, lmin, lmax;
@@ -1036,11 +995,11 @@ static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button
 }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
 /* Inspired by
    http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
  */
-#    if defined(_MSC_VER)
+#    if FREEGLUT_LIB_PRAGMAS
 #        pragma comment (lib, "advapi32.lib")
 #    endif
 
@@ -1058,9 +1017,9 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
         return 0;
 
     /* Open .. MediaResources\CurrentJoystickSettings */
-    sprintf ( buffer, "%s\\%s\\%s",
-              REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,
-              REGSTR_KEY_JOYCURR );
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",
+                REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,
+                REGSTR_KEY_JOYCURR );
 
     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
 
@@ -1070,7 +1029,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
     dwcb = sizeof(OEMKey);
 
     /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */
-    sprintf ( buffer, "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME );
+    _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME );
 
     lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);
     RegCloseKey ( hKey );
@@ -1078,7 +1037,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
     if ( lr != ERROR_SUCCESS ) return 0;
 
     /* Open OEM Key from ...MediaProperties */
-    sprintf ( buffer, "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
 
     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );
 
@@ -1100,7 +1059,7 @@ static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_
 
 static void fghJoystickOpen( SFG_Joystick* joy )
 {
-    int i;
+    int i = 0;
 #if TARGET_HOST_MACINTOSH
     OSStatus err;
 #endif
@@ -1114,17 +1073,22 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         CFDictionaryRef props;
     CFTypeRef topLevelElement;
 #endif
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    if defined( __FreeBSD__ ) || defined( __NetBSD__ )
        char *cp;
 #    endif
 #    ifdef JS_NEW
        unsigned char u;
 #    else
-       int counter;
+#      if defined( __linux__ ) || TARGET_HOST_SOLARIS
+         int counter = 0;
+#      endif
 #    endif
 #endif
 
+    /* Silence gcc, the correct #ifdefs would be too fragile... */
+    (void)i;
+
     /*
      * Default values (for no joystick -- each conditional will reset the
      * error flag)
@@ -1283,7 +1247,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
     CFRelease( props );
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     joy->js.dwFlags = JOY_RETURNALL;
     joy->js.dwSize  = sizeof( joy->js );
 
@@ -1345,7 +1309,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #if defined( __FreeBSD__ ) || defined( __NetBSD__ )
     for( i = 0; i < _JS_MAX_AXES; i++ )
         joy->os->cache_axes[ i ] = 0.0f;
@@ -1354,8 +1318,10 @@ static void fghJoystickOpen( SFG_Joystick* joy )
 
     joy->os->fd = open( joy->os->fname, O_RDONLY | O_NONBLOCK);
 
+#ifdef HAVE_ERRNO_H
     if( joy->os->fd < 0 && errno == EACCES )
         fgWarning ( "%s exists but is not readable by you", joy->os->fname );
+#endif
 
     joy->error =( joy->os->fd < 0 );
 
@@ -1381,7 +1347,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
         if( joy->error )
             return;
 
-        sprintf( joyfname, "%s/.joy%drc", getenv( "HOME" ), joy->id );
+        snprintf( joyfname, sizeof(joyfname), "%s/.joy%drc", getenv( "HOME" ), joy->id );
 
         joyfile = fopen( joyfname, "r" );
         joy->error =( joyfile == NULL );
@@ -1450,7 +1416,7 @@ static void fghJoystickOpen( SFG_Joystick* joy )
 #    endif
 #endif
 
-#if defined( __linux__ )
+#if defined( __linux__ ) || TARGET_HOST_SOLARIS
     /* Default for older Linux systems. */
     joy->num_axes    =  2;
     joy->num_buttons = 32;
@@ -1544,7 +1510,7 @@ static void fghJoystickInit( int ident )
 
 #if TARGET_HOST_MACINTOSH
     fgJoystick[ ident ]->id = ident;
-    sprintf( fgJoystick[ ident ]->fname, "/dev/js%d", ident ); /* FIXME */
+    snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); /* FIXME */
     fgJoystick[ ident ]->error = GL_FALSE;
 #endif
 
@@ -1591,7 +1557,7 @@ static void fghJoystickInit( int ident )
     }
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
     switch( ident )
     {
     case 0:
@@ -1609,7 +1575,7 @@ static void fghJoystickInit( int ident )
     }
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #    if defined( __FreeBSD__ ) || defined( __NetBSD__ )
     fgJoystick[ ident ]->id = ident;
     fgJoystick[ ident ]->error = GL_FALSE;
@@ -1619,18 +1585,18 @@ static void fghJoystickInit( int ident )
     if( ident < USB_IDENT_OFFSET )
         fgJoystick[ ident ]->os->is_analog = 1;
     if( fgJoystick[ ident ]->os->is_analog )
-        sprintf( fgJoystick[ ident ]->os->fname, "%s%d", AJSDEV, ident );
+        snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", AJSDEV, ident );
     else
-        sprintf( fgJoystick[ ident ]->os->fname, "%s%d", UHIDDEV,
+        snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", UHIDDEV,
                  ident - USB_IDENT_OFFSET );
 #    elif defined( __linux__ )
     fgJoystick[ ident ]->id = ident;
     fgJoystick[ ident ]->error = GL_FALSE;
 
-    sprintf( fgJoystick[ident]->fname, "/dev/input/js%d", ident );
+    snprintf( fgJoystick[ident]->fname, sizeof(fgJoystick[ident]->fname), "/dev/input/js%d", ident );
 
     if( access( fgJoystick[ ident ]->fname, F_OK ) != 0 )
-        sprintf( fgJoystick[ ident ]->fname, "/dev/js%d", ident );
+        snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident );
 #    endif
 #endif
 
@@ -1642,15 +1608,14 @@ static void fghJoystickInit( int ident )
  */
 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 );
+    if( !fgState.JoysticksInitialised )
+    {
+        int ident ;
+        for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ )
+            fghJoystickInit( ident );
 
-    fgState.JoysticksInitialised = GL_TRUE;
-  }
+        fgState.JoysticksInitialised = GL_TRUE;
+    }
 }
 
 /*
@@ -1675,11 +1640,11 @@ void fgJoystickClose( void )
                 close( fgJoystick[ ident ]->hidDev );
 #endif
 
-#if TARGET_HOST_WIN32
+#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
             /* Do nothing special */
 #endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 #if defined( __FreeBSD__ ) || defined( __NetBSD__ )
             if( fgJoystick[ident]->os )
             {
@@ -1741,21 +1706,18 @@ void fgJoystickPollWindow( SFG_Window* window )
  */
 int fgJoystickDetect( void )
 {
-  int ident;
-
-  fgInitialiseJoysticks ();
+    int ident;
 
-  if ( !fgJoystick )
-    return 0;
+    fgInitialiseJoysticks ();
 
-  if ( !fgState.JoysticksInitialised )
-    return 0;
+    if ( !fgState.JoysticksInitialised )
+        return 0;
 
-  for( ident=0; ident<MAX_NUM_JOYSTICKS; ident++ )
-    if( fgJoystick[ident] && !fgJoystick[ident]->error )
-      return 1;
+    for( ident=0; ident<MAX_NUM_JOYSTICKS; ident++ )
+        if( fgJoystick[ident] && !fgJoystick[ident]->error )
+            return 1;
 
-  return 0;
+    return 0;
 }
 
 /*
@@ -1763,63 +1725,76 @@ int fgJoystickDetect( void )
  */
 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 ) );
 }