X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2FCommon%2Ffreeglut_joystick.c;h=76f854252de32e01321d22d58c0282327fc60742;hb=57b0e0aeb1ffe8075226749cdd484d250966d0cf;hp=bf5bf95b7c138a73cb9c8c5485b7da450596aa03;hpb=e511ea0b35c08dd69bf1d8b898b68187c6fdd2ee;p=freeglut diff --git a/src/Common/freeglut_joystick.c b/src/Common/freeglut_joystick.c index bf5bf95..76f8542 100644 --- a/src/Common/freeglut_joystick.c +++ b/src/Common/freeglut_joystick.c @@ -37,98 +37,6 @@ # include #endif -/* - * Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c" - * interspersed - */ - -/* 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 -#endif - -#if TARGET_HOST_MAC_OSX -# define _JS_MAX_AXES 16 -# include -# include -# include -#endif - -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) -# define _JS_MAX_AXES 8 -# include -# include -# include - -#endif - -#if TARGET_HOST_POSIX_X11 -# define _JS_MAX_AXES 16 -# ifdef HAVE_SYS_IOCTL_H -# include -# endif -# ifdef HAVE_FCNTL_H -# include -# endif -# ifdef HAVE_ERRNO_H -# include -# include -# endif -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) -/* XXX The below hack is done until freeglut's autoconf is updated. */ -# define HAVE_USB_JS 1 - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -# include -# else -/* - * XXX NetBSD/amd64 systems may find that they have to steal the - * XXX /usr/include/machine/joystick.h from a NetBSD/i386 system. - * XXX I cannot comment whether that works for the interface, but - * XXX it lets you compile...(^& I do not think that we can do away - * XXX with this header. - */ -# include /* For analog joysticks */ -# endif -# define JS_DATA_TYPE joystick -# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) -# endif - -# if defined(__linux__) -# include - -/* check the joystick driver version */ -# if defined(JS_VERSION) && JS_VERSION >= 0x010000 -# define JS_NEW -# endif -# else /* Not BSD or Linux */ -# ifndef JS_RETURN - - /* - * We'll put these values in and that should - * allow the code to at least compile when there is - * no support. The JS open routine should error out - * and shut off all the code downstream anyway and if - * the application doesn't use a joystick we'll be fine. - */ - - struct JS_DATA_TYPE - { - int buttons; - int x; - int y; - }; - -# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) -# endif -# endif -#endif - #define JS_TRUE 1 #define JS_FALSE 0 @@ -376,65 +284,6 @@ static int fghJoystickInitializeHID(struct os_specific_s *os, #endif /* - * Definition of "SFG_Joystick" structure -- based on JS's "jsJoystick" object class. - * See "js.h" lines 80-178. - */ -typedef struct tagSFG_Joystick SFG_Joystick; -struct tagSFG_Joystick -{ -#if TARGET_HOST_MACINTOSH -#define ISP_NUM_AXIS 9 -#define ISP_NUM_NEEDS 41 - ISpElementReference isp_elem [ ISP_NUM_NEEDS ]; - ISpNeed isp_needs [ ISP_NUM_NEEDS ]; -#endif - -#if TARGET_HOST_MAC_OSX - IOHIDDeviceInterface ** hidDev; - IOHIDElementCookie buttonCookies[41]; - IOHIDElementCookie axisCookies[_JS_MAX_AXES]; - long minReport[_JS_MAX_AXES], - maxReport[_JS_MAX_AXES]; -#endif - -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - JOYCAPS jsCaps; - JOYINFOEX js; - UINT js_id; -#endif - - -#if TARGET_HOST_POSIX_X11 -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) - struct os_specific_s *os; -# endif - -# ifdef JS_NEW - struct js_event js; - int tmp_buttons; - float tmp_axes [ _JS_MAX_AXES ]; -# else - struct JS_DATA_TYPE js; -# endif - - char fname [ 128 ]; - int fd; -#endif - - int id; - GLboolean 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 ]; -}; - -/* * Functions associated with the "jsJoystick" class in PLIB */ #if TARGET_HOST_MAC_OSX @@ -456,6 +305,9 @@ static void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat ); /* External function declarations (mostly platform-specific) */ +extern void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ); +extern void fgPlatformJoystickOpen( SFG_Joystick* joy ); +extern void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ); extern void fgPlatformJoystickClose ( int ident ); /* @@ -465,66 +317,10 @@ extern void fgPlatformJoystickClose ( int ident ); static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ]; /* - * Platform-Specific Code - */ - -#if TARGET_HOST_MACINTOSH -void fgPlatformJoystickClose ( int ident ) -{ - ISpSuspend( ); - ISpStop( ); - ISpShutdown( ); -} -#endif - -#if TARGET_HOST_MAC_OSX -void fgPlatformJoystickClose ( int ident ) -{ - ( *( fgJoystick[ ident ]->hidDev ) )-> - close( fgJoystick[ ident ]->hidDev ); -} -#endif - -#if TARGET_HOST_POSIX_X11 -void fgPlatformJoystickClose ( int ident ) -{ -#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) - if( fgJoystick[ident]->os ) - { - if( ! fgJoystick[ ident ]->error ) - close( fgJoystick[ ident ]->os->fd ); -#ifdef HAVE_USB_JS - if( fgJoystick[ ident ]->os->hids ) - free (fgJoystick[ ident ]->os->hids); - if( fgJoystick[ ident ]->os->hid_data_buf ) - free( fgJoystick[ ident ]->os->hid_data_buf ); -#endif - free( fgJoystick[ident]->os ); - } -#endif - - if( ! fgJoystick[ident]->error ) - close( fgJoystick[ ident ]->fd ); -} -#endif - - - -/* * Read the raw joystick data */ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) { -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - MMRESULT status; -#else - int status; -#endif - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) - int len; -#endif - int i; /* Defaults */ @@ -538,373 +334,89 @@ static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) if( joy->error ) return; -#if TARGET_HOST_MACINTOSH - if ( buttons ) + fgPlatformJoystickRawRead ( joy, buttons, axes ); +} + +/* + * Correct the joystick axis data + */ +static float fghJoystickFudgeAxis( SFG_Joystick* joy, float value, int axis ) +{ + if( value < joy->center[ axis ] ) { - *buttons = 0; + float xx = ( value - joy->center[ axis ] ) / ( joy->center[ axis ] - + joy->min[ axis ] ); - for ( i = 0; i < joy->num_buttons; i++ ) - { - UInt32 state; - int err = ISpElement_GetSimpleState ( isp_elem [ i + isp_num_axis ], &state); - ISP_CHECK_ERR(err) + if( xx < -joy->saturate[ axis ] ) + return -1.0f; - *buttons |= state << i; - } - } + if( xx > -joy->dead_band [ axis ] ) + return 0.0f; - if ( axes ) - { - for ( i = 0; i < joy->num_axes; i++ ) - { - UInt32 state; - int err = ISpElement_GetSimpleState ( isp_elem [ i ], &state ); - ISP_CHECK_ERR(err) + xx = ( xx + joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - + joy->dead_band[ axis ] ); - axes [i] = (float) state; - } + return ( xx < -1.0f ) ? -1.0f : xx; } -#endif - -#if TARGET_HOST_MAC_OSX - if ( buttons != NULL ) + else { - *buttons = 0; + float xx = ( value - joy->center [ axis ] ) / ( joy->max[ axis ] - + joy->center[ axis ] ); - for ( i = 0; i < joy->num_buttons; i++ ) - { - IOHIDEventStruct hidEvent; - (*(joy->hidDev))->getElementValue ( joy->hidDev, buttonCookies[i], &hidEvent ); - if ( hidEvent.value ) - *buttons |= 1 << i; - } - } + if( xx > joy->saturate[ axis ] ) + return 1.0f; - if ( axes != NULL ) - { - for ( i = 0; i < joy->num_axes; i++ ) - { - IOHIDEventStruct hidEvent; - (*(joy->hidDev))->getElementValue ( joy->hidDev, axisCookies[i], &hidEvent ); - axes[i] = hidEvent.value; - } - } -#endif + if( xx < joy->dead_band[ axis ] ) + return 0.0f; -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - status = joyGetPosEx( joy->js_id, &joy->js ); + xx = ( xx - joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - + joy->dead_band[ axis ] ); - if ( status != JOYERR_NOERROR ) - { - joy->error = GL_TRUE; - return; + return ( xx > 1.0f ) ? 1.0f : xx; } +} - if ( buttons ) - *buttons = joy->js.dwButtons; +/* + * Read the corrected joystick data + */ +static void fghJoystickRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + float raw_axes[ _JS_MAX_AXES ]; + int i; - if ( axes ) + if( joy->error ) { - /* - * WARNING - Fall through case clauses!! - */ - switch ( joy->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 ( ( joy->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 ( ( joy->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) ); - float c = (float) cos ( ( joy->js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) ); - - /* 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 ; - } - } + if( buttons ) + *buttons = 0; - case 6: axes[5] = (float) joy->js.dwVpos; - case 5: axes[4] = (float) joy->js.dwUpos; - case 4: axes[3] = (float) joy->js.dwRpos; - case 3: axes[2] = (float) joy->js.dwZpos; - case 2: axes[1] = (float) joy->js.dwYpos; - case 1: axes[0] = (float) joy->js.dwXpos; - } + if( axes ) + for ( i=0; inum_axes; i++ ) + axes[ i ] = 0.0f; } -#endif -#if TARGET_HOST_POSIX_X11 -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) - if ( joy->os->is_analog ) - { - int status = read ( joy->os->fd, &joy->os->ajs, sizeof(joy->os->ajs) ); - if ( status != sizeof(joy->os->ajs) ) { - perror ( joy->os->fname ); - joy->error = GL_TRUE; - return; - } - if ( buttons != NULL ) - *buttons = ( joy->os->ajs.b1 ? 1 : 0 ) | ( joy->os->ajs.b2 ? 2 : 0 ); + fghJoystickRawRead( joy, buttons, raw_axes ); - if ( axes != NULL ) - { - axes[0] = (float) joy->os->ajs.x; - axes[1] = (float) joy->os->ajs.y; - } + if( axes ) + for( i=0; inum_axes; i++ ) + axes[ i ] = fghJoystickFudgeAxis( joy, raw_axes[ i ], i ); +} - return; - } +/* + * Happy happy happy joy joy joy (happy new year toudi :D) + */ -# ifdef HAVE_USB_JS - while ( ( len = read ( joy->os->fd, joy->os->hid_data_buf, joy->os->hid_dlen ) ) == joy->os->hid_dlen ) - { - struct hid_item *h; - for ( h = joy->os->hids; h; h = h->next ) - { - int d = hid_get_data ( joy->os->hid_data_buf, h ); +#if TARGET_HOST_MAC_OSX +/** 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 int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort ) +{ + CFMutableDictionaryRef hidMatch = NULL; + IOReturn rv = kIOReturnSuccess; - int page = HID_PAGE ( h->usage ); - int usage = HID_USAGE ( h->usage ); - - if ( page == HUP_GENERIC_DESKTOP ) - { - int i; - for ( i = 0; i < joy->num_axes; i++ ) - if (joy->os->axes_usage[i] == usage) - { - if (usage == HUG_HAT_SWITCH) - { - if (d < 0 || d > 8) - d = 0; /* safety */ - joy->os->cache_axes[i] = (float)hatmap_x[d]; - joy->os->cache_axes[i + 1] = (float)hatmap_y[d]; - } - else - { - joy->os->cache_axes[i] = (float)d; - } - break; - } - } - else if (page == HUP_BUTTON) - { - if (usage > 0 && usage < _JS_MAX_BUTTONS + 1) - { - if (d) - joy->os->cache_buttons |= (1 << ( usage - 1 )); - else - 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; - } - if ( buttons != NULL ) *buttons = joy->os->cache_buttons; - if ( axes != NULL ) - memcpy ( axes, joy->os->cache_axes, sizeof(float) * joy->num_axes ); -# endif -# endif - -# ifdef JS_NEW - - while ( 1 ) - { - status = read ( joy->fd, &joy->js, sizeof(struct js_event) ); - - if ( status != sizeof( struct js_event ) ) - { -#ifdef HAVE_ERRNO_H - if ( errno == EAGAIN ) - { - /* Use the old values */ - if ( buttons ) - *buttons = joy->tmp_buttons; - if ( axes ) - memcpy( axes, joy->tmp_axes, - sizeof( float ) * joy->num_axes ); - return; - } -#endif - - fgWarning ( "%s", joy->fname ); - joy->error = GL_TRUE; - return; - } - - switch ( joy->js.type & ~JS_EVENT_INIT ) - { - case JS_EVENT_BUTTON: - if( joy->js.value == 0 ) /* clear the flag */ - joy->tmp_buttons &= ~( 1 << joy->js.number ); - else - joy->tmp_buttons |= ( 1 << joy->js.number ); - break; - - case JS_EVENT_AXIS: - if ( joy->js.number < joy->num_axes ) - { - joy->tmp_axes[ joy->js.number ] = ( float )joy->js.value; - - if( axes ) - memcpy( axes, joy->tmp_axes, sizeof(float) * joy->num_axes ); - } - break; - - default: - fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" ); - - /* use the old values */ - - if ( buttons != NULL ) *buttons = joy->tmp_buttons; - if ( axes != NULL ) - memcpy ( axes, joy->tmp_axes, sizeof(float) * joy->num_axes ); - - return; - } - - if( buttons ) - *buttons = joy->tmp_buttons; - } -# else - - status = read( joy->fd, &joy->js, JS_RETURN ); - - if ( status != JS_RETURN ) - { - fgWarning( "%s", joy->fname ); - joy->error = GL_TRUE; - return; - } - - if ( buttons ) -# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) - *buttons = ( joy->js.b1 ? 1 : 0 ) | ( joy->js.b2 ? 2 : 0 ); /* XXX Should not be here -- BSD is handled earlier */ -# else - *buttons = joy->js.buttons; -# endif - - if ( axes ) - { - axes[ 0 ] = (float) joy->js.x; - axes[ 1 ] = (float) joy->js.y; - } -# endif -#endif -} - -/* - * Correct the joystick axis data - */ -static float fghJoystickFudgeAxis( SFG_Joystick* joy, float value, int axis ) -{ - if( value < joy->center[ axis ] ) - { - float xx = ( value - joy->center[ axis ] ) / ( joy->center[ axis ] - - joy->min[ axis ] ); - - if( xx < -joy->saturate[ axis ] ) - return -1.0f; - - if( xx > -joy->dead_band [ axis ] ) - return 0.0f; - - xx = ( xx + joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - - joy->dead_band[ axis ] ); - - return ( xx < -1.0f ) ? -1.0f : xx; - } - else - { - float xx = ( value - joy->center [ axis ] ) / ( joy->max[ axis ] - - joy->center[ axis ] ); - - if( xx > joy->saturate[ axis ] ) - return 1.0f; - - if( xx < joy->dead_band[ axis ] ) - return 0.0f; - - xx = ( xx - joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - - joy->dead_band[ axis ] ); - - return ( xx > 1.0f ) ? 1.0f : xx; - } -} - -/* - * Read the corrected joystick data - */ -static void fghJoystickRead( SFG_Joystick* joy, int* buttons, float* axes ) -{ - float raw_axes[ _JS_MAX_AXES ]; - int i; - - if( joy->error ) - { - if( buttons ) - *buttons = 0; - - if( axes ) - for ( i=0; inum_axes; i++ ) - axes[ i ] = 0.0f; - } - - fghJoystickRawRead( joy, buttons, raw_axes ); - - if( axes ) - for( i=0; inum_axes; i++ ) - axes[ i ] = fghJoystickFudgeAxis( joy, raw_axes[ i ], i ); -} - -/* - * Happy happy happy joy joy joy (happy new year toudi :D) - */ - - -#if TARGET_HOST_MAC_OSX -/** 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 int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort ) -{ - CFMutableDictionaryRef hidMatch = NULL; - IOReturn rv = kIOReturnSuccess; - - io_iterator_t hidIterator; - io_object_t ioDev; + io_iterator_t hidIterator; + io_object_t ioDev; /* build a dictionary matching HID devices */ hidMatch = IOServiceMatching(kIOHIDDeviceKey); @@ -1006,7 +518,7 @@ static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ), kCFNumberLongType, &cookie); - axisCookies[index] = (IOHIDElementCookie) cookie; + joy->pJoystick.axisCookies[index] = (IOHIDElementCookie) cookie; CFNumberGetValue ((CFNumberRef) CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ), @@ -1030,7 +542,7 @@ static void fghJoystickAddButtonElement ( SFG_Joystick *joy, CFDictionaryRef but CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ), kCFNumberLongType, &cookie); - joy->buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie; + joy->pJoystick.buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie; /* anything else for buttons? */ } @@ -1041,109 +553,48 @@ static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button } #endif -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) -/* Inspired by - http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp +/* + * Platform-Specific Code */ -# if FREEGLUT_LIB_PRAGMAS -# pragma comment (lib, "advapi32.lib") -# endif -static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz ) +#if TARGET_HOST_MACINTOSH +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) { - char buffer [ 256 ]; - - char OEMKey [ 256 ]; - - HKEY hKey; - DWORD dwcb; - LONG lr; - - if ( joy->error ) - return 0; - - /* Open .. MediaResources\CurrentJoystickSettings */ - _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); - - if ( lr != ERROR_SUCCESS ) return 0; - - /* Get OEM Key name */ - dwcb = sizeof(OEMKey); - - /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */ - _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 ); - - if ( lr != ERROR_SUCCESS ) return 0; - - /* Open OEM Key from ...MediaProperties */ - _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey ); - - lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey ); + int i; - if ( lr != ERROR_SUCCESS ) return 0; + if ( buttons ) + { + *buttons = 0; - /* Get OEM Name */ - dwcb = buf_sz; + for ( i = 0; i < joy->num_buttons; i++ ) + { + UInt32 state; + int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i + ISP_NUM_AXIS ], &state); + ISP_CHECK_ERR(err) - lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf, - &dwcb ); - RegCloseKey ( hKey ); + *buttons |= state << i; + } + } - if ( lr != ERROR_SUCCESS ) return 0; + if ( axes ) + { + for ( i = 0; i < joy->num_axes; i++ ) + { + UInt32 state; + int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i ], &state ); + ISP_CHECK_ERR(err) - return 1; + axes [i] = (float) state; + } + } } -#endif -static void fghJoystickOpen( SFG_Joystick* joy ) +void fgPlatformJoystickOpen( SFG_Joystick* joy ) { - int i = 0; -#if TARGET_HOST_MACINTOSH + int i = 0; OSStatus err; -#endif -#if TARGET_HOST_MAC_OSX - IOReturn rv; - SInt32 score; - IOCFPlugInInterface **plugin; - - HRESULT pluginResult; - - CFDictionaryRef props; - CFTypeRef topLevelElement; -#endif -#if TARGET_HOST_POSIX_X11 -# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) - char *cp; -# endif -# ifdef JS_NEW - unsigned char u; -# else -# 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) - */ - joy->error = TRUE; - joy->num_axes = joy->num_buttons = 0; - joy->name[ 0 ] = '\0'; -#if TARGET_HOST_MACINTOSH /* XXX FIXME: get joystick name in Mac */ err = ISpStartup( ); @@ -1155,7 +606,7 @@ static void fghJoystickOpen( SFG_Joystick* joy ) joy->error = GL_TRUE; /* initialize the needs structure */ - ISpNeed temp_isp_needs[ isp_num_needs ] = + ISpNeed temp_isp_needs[ ISP_NUM_NEEDS ] = { { "\pX-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, { "\pY-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, @@ -1201,7 +652,7 @@ static void fghJoystickOpen( SFG_Joystick* joy ) { "\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, }; - memcpy( joy->isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) ); + memcpy( joy->pJoystick.isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) ); /* next two calls allow keyboard and mouse to emulate other input @@ -1216,17 +667,17 @@ static void fghJoystickOpen( SFG_Joystick* joy ) ISP_CHECK_ERR(err) */ - err = ISpElement_NewVirtualFromNeeds( joy->isp_num_needs, - joy->isp_needs, joy->isp_elem, + err = ISpElement_NewVirtualFromNeeds( ISP_NUM_NEEDS, + joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, 0 ); ISP_CHECK_ERR( err ) - err = ISpInit( joy->isp_num_needs, joy->isp_needs, joy->isp_elem, + err = ISpInit( ISP_NUM_NEEDS, joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, 'freeglut', nil, 0, 128, 0 ); ISP_CHECK_ERR( err ) - joy->num_buttons = joy->isp_num_needs - joy->isp_num_axis; - joy->num_axes = joy->isp_num_axis; + joy->num_buttons = ISP_NUM_NEEDS - ISP_NUM_AXIS; + joy->num_axes = ISP_NUM_AXIS; for( i = 0; i < joy->num_axes; i++ ) { @@ -1241,17 +692,74 @@ static void fghJoystickOpen( SFG_Joystick* joy ) } else joy->num_buttons = joy->num_axes = 0; +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + fgJoystick[ ident ]->id = ident; + snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident ); /* FIXME */ + fgJoystick[ ident ]->error = GL_FALSE; +} + + +void fgPlatformJoystickClose ( int ident ) +{ + ISpSuspend( ); + ISpStop( ); + ISpShutdown( ); +} #endif #if TARGET_HOST_MAC_OSX - if( joy->id >= numDevices ) +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int i; + + if ( buttons != NULL ) { - fgWarning( "device index out of range in fgJoystickOpen()" ); - return; + *buttons = 0; + + for ( i = 0; i < joy->num_buttons; i++ ) + { + IOHIDEventStruct hidEvent; + (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.buttonCookies[i], &hidEvent ); + if ( hidEvent.value ) + *buttons |= 1 << i; + } } - /* create device interface */ - rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ], + if ( axes != NULL ) + { + for ( i = 0; i < joy->num_axes; i++ ) + { + IOHIDEventStruct hidEvent; + (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.axisCookies[i], &hidEvent ); + axes[i] = hidEvent.value; + } + } +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ + IOReturn rv; + SInt32 score; + IOCFPlugInInterface **plugin; + + HRESULT pluginResult; + + CFDictionaryRef props; + CFTypeRef topLevelElement; + + if( joy->id >= numDevices ) + { + fgWarning( "device index out of range in fgJoystickOpen()" ); + return; + } + + /* create device interface */ + rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ], kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin, &score ); @@ -1265,18 +773,18 @@ static void fghJoystickOpen( SFG_Joystick* joy ) pluginResult = ( *plugin )->QueryInterface( plugin, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), - &( LPVOID )joy->hidDev + &( LPVOID )joy->pJoystick.hidDev ); if( pluginResult != S_OK ) fgWarning ( "QI-ing IO plugin to HID Device interface failed" ); ( *plugin )->Release( plugin ); /* don't leak a ref */ - if( joy->hidDev == NULL ) + if( joy->pJoystick.hidDev == NULL ) return; /* store the interface in this instance */ - rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 ); + rv = ( *( joy->pJoystick.hidDev ) )->open( joy->pJoystick.hidDev, 0 ); if( rv != kIOReturnSuccess ) { fgWarning( "error opening device interface"); @@ -1291,92 +799,273 @@ static void fghJoystickOpen( SFG_Joystick* joy ) enumerateElements( topLevelElement ); CFRelease( props ); +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + fgJoystick[ ident ]->num_axes = 0; + fgJoystick[ ident ]->num_buttons = 0; + + if( numDevices < 0 ) + { + /* do first-time init (since we can't over-ride jsInit, hmm */ + numDevices = 0; + + mach_port_t masterPort; + IOReturn rv = IOMasterPort( bootstrap_port, &masterPort ); + if( rv != kIOReturnSuccess ) + { + fgWarning( "error getting master Mach port" ); + return; + } + fghJoystickFindDevices( masterPort ); + } + + if ( ident >= numDevices ) + { + fgJoystick[ ident ]->error = GL_TRUE; + return; + } + + /* get the name now too */ + CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] ); + CFTypeRef ref = CFDictionaryGetValue( properties, + CFSTR( kIOHIDProductKey ) ); + if (!ref) + ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) ); + + if( !ref || + !CFStringGetCString( ( CFStringRef )ref, name, 128, + CFStringGetSystemEncoding( ) ) ) + { + fgWarning( "error getting device name" ); + name[ 0 ] = '\0'; + } +} + + +void fgPlatformJoystickClose ( int ident ) +{ + ( *( fgJoystick[ ident ]->pJoystick.hidDev ) )-> + close( fgJoystick[ ident ]->pJoystick.hidDev ); +} #endif -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - joy->js.dwFlags = JOY_RETURNALL; - joy->js.dwSize = sizeof( joy->js ); +#if TARGET_HOST_POSIX_X11 +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int status; - memset( &joy->jsCaps, 0, sizeof( joy->jsCaps ) ); + int i; - joy->error = - ( joyGetDevCaps( joy->js_id, &joy->jsCaps, sizeof( joy->jsCaps ) ) != - JOYERR_NOERROR ); +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + int len; - if( joy->jsCaps.wNumAxes == 0 ) + if ( joy->pJoystick.os->is_analog ) { - joy->num_axes = 0; - joy->error = GL_TRUE; + int status = read ( joy->pJoystick.os->fd, &joy->pJoystick.os->ajs, sizeof(joy->pJoystick.os->ajs) ); + if ( status != sizeof(joy->pJoystick.os->ajs) ) { + perror ( joy->pJoystick.os->fname ); + joy->error = GL_TRUE; + return; + } + if ( buttons != NULL ) + *buttons = ( joy->pJoystick.os->ajs.b1 ? 1 : 0 ) | ( joy->pJoystick.os->ajs.b2 ? 2 : 0 ); + + if ( axes != NULL ) + { + axes[0] = (float) joy->pJoystick.os->ajs.x; + axes[1] = (float) joy->pJoystick.os->ajs.y; + } + + return; } - else + +# ifdef HAVE_USB_JS + while ( ( len = read ( joy->pJoystick.os->fd, joy->pJoystick.os->hid_data_buf, joy->pJoystick.os->hid_dlen ) ) == joy->pJoystick.os->hid_dlen ) { - /* Device name from jsCaps is often "Microsoft PC-joystick driver", - * at least for USB. Try to get the real name from the registry. - */ - if ( ! fghJoystickGetOEMProductName( joy, joy->name, - sizeof( joy->name ) ) ) + struct hid_item *h; + + for ( h = joy->pJoystick.os->hids; h; h = h->next ) { - fgWarning( "JS: Failed to read joystick name from registry" ); - strncpy( joy->name, joy->jsCaps.szPname, sizeof( joy->name ) ); + int d = hid_get_data ( joy->pJoystick.os->hid_data_buf, h ); + + int page = HID_PAGE ( h->usage ); + int usage = HID_USAGE ( h->usage ); + + if ( page == HUP_GENERIC_DESKTOP ) + { + int i; + for ( i = 0; i < joy->num_axes; i++ ) + if (joy->pJoystick.os->axes_usage[i] == usage) + { + if (usage == HUG_HAT_SWITCH) + { + if (d < 0 || d > 8) + d = 0; /* safety */ + joy->pJoystick.os->cache_axes[i] = (float)hatmap_x[d]; + joy->pJoystick.os->cache_axes[i + 1] = (float)hatmap_y[d]; + } + else + { + joy->pJoystick.os->cache_axes[i] = (float)d; + } + break; + } + } + else if (page == HUP_BUTTON) + { + if (usage > 0 && usage < _JS_MAX_BUTTONS + 1) + { + if (d) + joy->pJoystick.os->cache_buttons |= (1 << ( usage - 1 )); + else + joy->pJoystick.os->cache_buttons &= ~(1 << ( usage - 1 )); + } + } } + } +# ifdef HAVE_ERRNO_H + if ( len < 0 && errno != EAGAIN ) +# else + if ( len < 0 ) +# endif + { + perror( joy->pJoystick.os->fname ); + joy->error = 1; + } + if ( buttons != NULL ) *buttons = joy->pJoystick.os->cache_buttons; + if ( axes != NULL ) + memcpy ( axes, joy->pJoystick.os->cache_axes, sizeof(float) * joy->num_axes ); +# endif +#endif - /* Windows joystick drivers may provide any combination of - * X,Y,Z,R,U,V,POV - not necessarily the first n of these. - */ - if( joy->jsCaps.wCaps & JOYCAPS_HASPOV ) +#ifdef JS_NEW + + while ( 1 ) + { + status = read ( joy->pJoystick.fd, &joy->pJoystick.js, sizeof(struct js_event) ); + + if ( status != sizeof( struct js_event ) ) { - joy->num_axes = _JS_MAX_AXES; - joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0; /* POV Y */ - joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0; /* POV X */ +# ifdef HAVE_ERRNO_H + if ( errno == EAGAIN ) + { + /* Use the old values */ + if ( buttons ) + *buttons = joy->pJoystick.tmp_buttons; + if ( axes ) + memcpy( axes, joy->pJoystick.tmp_axes, + sizeof( float ) * joy->num_axes ); + return; + } +# endif + + fgWarning ( "%s", joy->pJoystick.fname ); + joy->error = GL_TRUE; + return; } - else - joy->num_axes = 6; - - joy->min[ 5 ] = ( float )joy->jsCaps.wVmin; - joy->max[ 5 ] = ( float )joy->jsCaps.wVmax; - joy->min[ 4 ] = ( float )joy->jsCaps.wUmin; - joy->max[ 4 ] = ( float )joy->jsCaps.wUmax; - joy->min[ 3 ] = ( float )joy->jsCaps.wRmin; - joy->max[ 3 ] = ( float )joy->jsCaps.wRmax; - joy->min[ 2 ] = ( float )joy->jsCaps.wZmin; - joy->max[ 2 ] = ( float )joy->jsCaps.wZmax; - joy->min[ 1 ] = ( float )joy->jsCaps.wYmin; - joy->max[ 1 ] = ( float )joy->jsCaps.wYmax; - joy->min[ 0 ] = ( float )joy->jsCaps.wXmin; - joy->max[ 0 ] = ( float )joy->jsCaps.wXmax; + + switch ( joy->pJoystick.js.type & ~JS_EVENT_INIT ) + { + case JS_EVENT_BUTTON: + if( joy->pJoystick.js.value == 0 ) /* clear the flag */ + joy->pJoystick.tmp_buttons &= ~( 1 << joy->pJoystick.js.number ); + else + joy->pJoystick.tmp_buttons |= ( 1 << joy->pJoystick.js.number ); + break; + + case JS_EVENT_AXIS: + if ( joy->pJoystick.js.number < joy->num_axes ) + { + joy->pJoystick.tmp_axes[ joy->pJoystick.js.number ] = ( float )joy->pJoystick.js.value; + + if( axes ) + memcpy( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes ); + } + break; + + default: + fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" ); + + /* use the old values */ + + if ( buttons != NULL ) *buttons = joy->pJoystick.tmp_buttons; + if ( axes != NULL ) + memcpy ( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes ); + + return; + } + + if( buttons ) + *buttons = joy->pJoystick.tmp_buttons; + } +#else + + status = read( joy->pJoystick.fd, &joy->pJoystick.js, JS_RETURN ); + + if ( status != JS_RETURN ) + { + fgWarning( "%s", joy->pJoystick.fname ); + joy->error = GL_TRUE; + return; } - /* Guess all the rest judging on the axes extremals */ - for( i = 0; i < joy->num_axes; i++ ) + if ( buttons ) +# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) + *buttons = ( joy->pJoystick.js.b1 ? 1 : 0 ) | ( joy->pJoystick.js.b2 ? 2 : 0 ); /* XXX Should not be here -- BSD is handled earlier */ +# else + *buttons = joy->pJoystick.js.buttons; +# endif + + if ( axes ) { - joy->center [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f; - joy->dead_band[ i ] = 0.0f; - joy->saturate [ i ] = 1.0f; + axes[ 0 ] = (float) joy->pJoystick.js.x; + axes[ 1 ] = (float) joy->pJoystick.js.y; } #endif +} + + +void fgPlatformJoystickOpen( SFG_Joystick* joy ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) + int i = 0; + char *cp; +#endif +#ifdef JS_NEW + unsigned char u; +#else +# if defined( __linux__ ) || TARGET_HOST_SOLARIS + int i = 0; + int counter = 0; +# endif +#endif -#if TARGET_HOST_POSIX_X11 #if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) for( i = 0; i < _JS_MAX_AXES; i++ ) - joy->os->cache_axes[ i ] = 0.0f; + joy->pJoystick.os->cache_axes[ i ] = 0.0f; - joy->os->cache_buttons = 0; + joy->pJoystick.os->cache_buttons = 0; - joy->os->fd = open( joy->os->fname, O_RDONLY | O_NONBLOCK); + joy->pJoystick.os->fd = open( joy->pJoystick.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 ); + if( joy->pJoystick.os->fd < 0 && errno == EACCES ) + fgWarning ( "%s exists but is not readable by you", joy->pJoystick.os->fname ); #endif - joy->error =( joy->os->fd < 0 ); + joy->error =( joy->pJoystick.os->fd < 0 ); if( joy->error ) return; joy->num_axes = 0; joy->num_buttons = 0; - if( joy->os->is_analog ) + if( joy->pJoystick.os->is_analog ) { FILE *joyfile; char joyfname[ 1024 ]; @@ -1418,15 +1107,15 @@ static void fghJoystickOpen( SFG_Joystick* joy ) } # ifdef HAVE_USB_JS - if( ! fghJoystickInitializeHID( joy->os, &joy->num_axes, + if( ! fghJoystickInitializeHID( joy->pJoystick.os, &joy->num_axes, &joy->num_buttons ) ) { - close( joy->os->fd ); + close( joy->pJoystick.os->fd ); joy->error = GL_TRUE; return; } - cp = strrchr( joy->os->fname, '/' ); + cp = strrchr( joy->pJoystick.os->fname, '/' ); if( cp ) { if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) == @@ -1443,7 +1132,7 @@ static void fghJoystickOpen( SFG_Joystick* joy ) * to be quite unreliable for analog-to-USB converters. Punt for * now. */ - if( joy->os->axes_usage[ i ] == HUG_HAT_SWITCH ) + if( joy->pJoystick.os->axes_usage[ i ] == HUG_HAT_SWITCH ) { joy->max [ i ] = 1.0f; joy->center[ i ] = 0.0f; @@ -1469,14 +1158,14 @@ static void fghJoystickOpen( SFG_Joystick* joy ) # ifdef JS_NEW for( i = 0; i < _JS_MAX_AXES; i++ ) - joy->tmp_axes[ i ] = 0.0f; + joy->pJoystick.tmp_axes[ i ] = 0.0f; - joy->tmp_buttons = 0; + joy->pJoystick.tmp_buttons = 0; # endif - joy->fd = open( joy->fname, O_RDONLY ); + joy->pJoystick.fd = open( joy->pJoystick.fname, O_RDONLY ); - joy->error =( joy->fd < 0 ); + joy->error =( joy->pJoystick.fd < 0 ); if( joy->error ) return; @@ -1487,12 +1176,12 @@ static void fghJoystickOpen( SFG_Joystick* joy ) * to the upper byte of an uninitialized word doesn't work. * 9 April 2003 */ - ioctl( joy->fd, JSIOCGAXES, &u ); + ioctl( joy->pJoystick.fd, JSIOCGAXES, &u ); joy->num_axes = u; - ioctl( joy->fd, JSIOCGBUTTONS, &u ); + ioctl( joy->pJoystick.fd, JSIOCGBUTTONS, &u ); joy->num_buttons = u; - ioctl( joy->fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name ); - fcntl( joy->fd, F_SETFL, O_NONBLOCK ); + ioctl( joy->pJoystick.fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name ); + fcntl( joy->pJoystick.fd, F_SETFL, O_NONBLOCK ); # endif /* @@ -1533,7 +1222,75 @@ static void fghJoystickOpen( SFG_Joystick* joy ) joy->saturate [ i ] = 1.0f; } #endif +} + + +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + + fgJoystick[ ident ]->pJoystick.os = calloc( 1, sizeof( struct os_specific_s ) ); + memset( fgJoystick[ ident ]->pJoystick.os, 0, sizeof( struct os_specific_s ) ); + if( ident < USB_IDENT_OFFSET ) + fgJoystick[ ident ]->pJoystick.os->is_analog = 1; + if( fgJoystick[ ident ]->pJoystick.os->is_analog ) + snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", AJSDEV, ident ); + else + snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", UHIDDEV, + ident - USB_IDENT_OFFSET ); +#elif defined( __linux__ ) + fgJoystick[ ident ]->id = ident; + fgJoystick[ ident ]->error = GL_FALSE; + + snprintf( fgJoystick[ident]->pJoystick.fname, sizeof(fgJoystick[ident]->pJoystick.fname), "/dev/input/js%d", ident ); + + if( access( fgJoystick[ ident ]->pJoystick.fname, F_OK ) != 0 ) + snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident ); +#endif +} + + +void fgPlatformJoystickClose ( int ident ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) + if( fgJoystick[ident]->pJoystick.os ) + { + if( ! fgJoystick[ ident ]->error ) + close( fgJoystick[ ident ]->pJoystick.os->fd ); +#ifdef HAVE_USB_JS + if( fgJoystick[ ident ]->pJoystick.os->hids ) + free (fgJoystick[ ident ]->pJoystick.os->hids); + if( fgJoystick[ ident ]->pJoystick.os->hid_data_buf ) + free( fgJoystick[ ident ]->pJoystick.os->hid_data_buf ); +#endif + free( fgJoystick[ident]->pJoystick.os ); + } +#endif + + if( ! fgJoystick[ident]->error ) + close( fgJoystick[ ident ]->pJoystick.fd ); +} #endif + + + + + + +static void fghJoystickOpen( SFG_Joystick* joy ) +{ + /* + * Default values (for no joystick -- each conditional will reset the + * error flag) + */ + joy->error = TRUE; + joy->num_axes = joy->num_buttons = 0; + joy->name[ 0 ] = '\0'; + + fgPlatformJoystickOpen ( joy ); + } /* @@ -1554,97 +1311,7 @@ static void fghJoystickInit( int ident ) fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0; fgJoystick[ ident ]->error = GL_TRUE; -#if TARGET_HOST_MACINTOSH - fgJoystick[ ident ]->id = ident; - snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); /* FIXME */ - fgJoystick[ ident ]->error = GL_FALSE; -#endif - -#if TARGET_HOST_MAC_OSX - fgJoystick[ ident ]->id = ident; - fgJoystick[ ident ]->error = GL_FALSE; - fgJoystick[ ident ]->num_axes = 0; - fgJoystick[ ident ]->num_buttons = 0; - - if( numDevices < 0 ) - { - /* do first-time init (since we can't over-ride jsInit, hmm */ - numDevices = 0; - - mach_port_t masterPort; - IOReturn rv = IOMasterPort( bootstrap_port, &masterPort ); - if( rv != kIOReturnSuccess ) - { - fgWarning( "error getting master Mach port" ); - return; - } - fghJoystickFindDevices( masterPort ); - } - - if ( ident >= numDevices ) - { - fgJoystick[ ident ]->error = GL_TRUE; - return; - } - - /* get the name now too */ - CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] ); - CFTypeRef ref = CFDictionaryGetValue( properties, - CFSTR( kIOHIDProductKey ) ); - if (!ref) - ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) ); - - if( !ref || - !CFStringGetCString( ( CFStringRef )ref, name, 128, - CFStringGetSystemEncoding( ) ) ) - { - fgWarning( "error getting device name" ); - name[ 0 ] = '\0'; - } -#endif - -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - switch( ident ) - { - case 0: - fgJoystick[ ident ]->js_id = JOYSTICKID1; - fgJoystick[ ident ]->error = GL_FALSE; - break; - case 1: - fgJoystick[ ident ]->js_id = JOYSTICKID2; - fgJoystick[ ident ]->error = GL_FALSE; - break; - default: - fgJoystick[ ident ]->num_axes = 0; - fgJoystick[ ident ]->error = GL_TRUE; - return; - } -#endif - -#if TARGET_HOST_POSIX_X11 -# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) - fgJoystick[ ident ]->id = ident; - fgJoystick[ ident ]->error = GL_FALSE; - - fgJoystick[ ident ]->os = calloc( 1, sizeof( struct os_specific_s ) ); - memset( fgJoystick[ ident ]->os, 0, sizeof( struct os_specific_s ) ); - if( ident < USB_IDENT_OFFSET ) - fgJoystick[ ident ]->os->is_analog = 1; - if( fgJoystick[ ident ]->os->is_analog ) - snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", AJSDEV, ident ); - else - 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; - - snprintf( fgJoystick[ident]->fname, sizeof(fgJoystick[ident]->fname), "/dev/input/js%d", ident ); - - if( access( fgJoystick[ ident ]->fname, F_OK ) != 0 ) - snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); -# endif -#endif + fgPlatformJoystickInit( fgJoystick, ident ); fghJoystickOpen( fgJoystick[ ident ] ); }