X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2FCommon%2Ffreeglut_joystick.c;h=3937a1b1a8878a5498ff6d168c0a63d81e84ca34;hb=2eb11979566278c10d5e3e62d0cb0be255e567c0;hp=416091ffa5a7d3c7f694841307f89c65c490d215;hpb=38011fb92295a6a40a003b3d1fabcd565694cfb1;p=freeglut diff --git a/src/Common/freeglut_joystick.c b/src/Common/freeglut_joystick.c index 416091f..3937a1b 100644 --- a/src/Common/freeglut_joystick.c +++ b/src/Common/freeglut_joystick.c @@ -42,25 +42,17 @@ * 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 @@ -68,7 +60,6 @@ #endif #if TARGET_HOST_POSIX_X11 -# define _JS_MAX_AXES 16 # ifdef HAVE_SYS_IOCTL_H # include # endif @@ -376,65 +367,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 +388,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 ); /* @@ -464,22 +399,11 @@ extern void fgPlatformJoystickClose ( int ident ); #define MAX_NUM_JOYSTICKS 2 static SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ]; - /* * 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 */ @@ -493,393 +417,109 @@ 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 ); + io_iterator_t hidIterator; + io_object_t ioDev; - 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; + /* build a dictionary matching HID devices */ + hidMatch = IOServiceMatching(kIOHIDDeviceKey); + + rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator); + if (rv != kIOReturnSuccess || !hidIterator) { + fgWarning( "no joystick (HID) devices found" ); + return; } - 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 + /* iterate */ + while ((ioDev = IOIteratorNext(hidIterator))) { + /* filter out keyboard and mouse devices */ + CFDictionaryRef properties = getCFProperties(ioDev); + long usage, page; - 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; - - /* build a dictionary matching HID devices */ - hidMatch = IOServiceMatching(kIOHIDDeviceKey); - - rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator); - if (rv != kIOReturnSuccess || !hidIterator) { - fgWarning( "no joystick (HID) devices found" ); - return; - } - - /* iterate */ - 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); + 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 ) && ( @@ -996,109 +636,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 ( 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 ( 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( ); @@ -1196,9 +775,66 @@ 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 ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); /* FIXME */ + fgJoystick[ ident ]->error = GL_FALSE; +} + + +void fgPlatformJoystickClose ( int ident ) +{ + ISpSuspend( ); + ISpStop( ); + ISpShutdown( ); +} #endif #if TARGET_HOST_MAC_OSX +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int i; + + if ( buttons != NULL ) + { + *buttons = 0; + + 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 ( axes != NULL ) + { + for ( i = 0; i < joy->num_axes; i++ ) + { + IOHIDEventStruct hidEvent; + (*(joy->hidDev))->getElementValue ( joy->hidDev, 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()" ); @@ -1223,94 +859,275 @@ static void fghJoystickOpen( SFG_Joystick* joy ) &( LPVOID )joy->hidDev ); - if( pluginResult != S_OK ) - fgWarning ( "QI-ing IO plugin to HID Device interface failed" ); + 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 ) + return; + + /* store the interface in this instance */ + rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 ); + if( rv != kIOReturnSuccess ) + { + fgWarning( "error opening device interface"); + return; + } + + props = getCFProperties( ioDevices[ joy->id ] ); + + /* recursively enumerate all the bits */ + CFTypeRef topLevelElement = + CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) ); + 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 ]->hidDev ) )-> + close( fgJoystick[ ident ]->hidDev ); +} +#endif + +#if TARGET_HOST_POSIX_X11 +void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) +{ + int status; + + int i; + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) + int len; + + 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 ); + + if ( axes != NULL ) + { + axes[0] = (float) joy->os->ajs.x; + axes[1] = (float) joy->os->ajs.y; + } + + return; + } + +# 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 ); + + 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; - ( *plugin )->Release( plugin ); /* don't leak a ref */ - if( joy->hidDev == NULL ) - return; + case JS_EVENT_AXIS: + if ( joy->js.number < joy->num_axes ) + { + joy->tmp_axes[ joy->js.number ] = ( float )joy->js.value; - /* store the interface in this instance */ - rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 ); - if( rv != kIOReturnSuccess ) - { - fgWarning( "error opening device interface"); - return; - } + if( axes ) + memcpy( axes, joy->tmp_axes, sizeof(float) * joy->num_axes ); + } + break; - props = getCFProperties( ioDevices[ joy->id ] ); + default: + fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" ); - /* recursively enumerate all the bits */ - CFTypeRef topLevelElement = - CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) ); - enumerateElements( topLevelElement ); + /* use the old values */ - CFRelease( props ); -#endif + if ( buttons != NULL ) *buttons = joy->tmp_buttons; + if ( axes != NULL ) + memcpy ( axes, joy->tmp_axes, sizeof(float) * joy->num_axes ); -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) - joy->js.dwFlags = JOY_RETURNALL; - joy->js.dwSize = sizeof( joy->js ); + return; + } - memset( &joy->jsCaps, 0, sizeof( joy->jsCaps ) ); + if( buttons ) + *buttons = joy->tmp_buttons; + } +#else - joy->error = - ( joyGetDevCaps( joy->js_id, &joy->jsCaps, sizeof( joy->jsCaps ) ) != - JOYERR_NOERROR ); + status = read( joy->fd, &joy->js, JS_RETURN ); - if( joy->jsCaps.wNumAxes == 0 ) + if ( status != JS_RETURN ) { - joy->num_axes = 0; + fgWarning( "%s", joy->fname ); joy->error = GL_TRUE; + return; } - else - { - /* Device name from jsCaps is often "Microsoft PC-joystick driver", - * at least for USB. Try to get the real name from the registry. - */ - if ( ! fghJoystickGetOEMProductName( joy, joy->name, - sizeof( joy->name ) ) ) - { - fgWarning( "JS: Failed to read joystick name from registry" ); - strncpy( joy->name, joy->jsCaps.szPname, sizeof( joy->name ) ); - } - /* 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 ) - { - 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 */ - } - 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; - } + 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 - /* Guess all the rest judging on the axes extremals */ - for( i = 0; i < joy->num_axes; i++ ) + 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->js.x; + axes[ 1 ] = (float) joy->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; @@ -1488,96 +1305,12 @@ static void fghJoystickOpen( SFG_Joystick* joy ) joy->saturate [ i ] = 1.0f; } #endif -#endif } -/* - * This function replaces the constructor method in the JS library. - */ -static void fghJoystickInit( int ident ) -{ - if( ident >= MAX_NUM_JOYSTICKS ) - fgError( "Too large a joystick number: %d", ident ); - - if( fgJoystick[ ident ] ) - fgError( "illegal attempt to initialize joystick device again" ); - - fgJoystick[ ident ] = - ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 ); - - /* Set defaults */ - 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__ ) +void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) +{ +#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ ) fgJoystick[ ident ]->id = ident; fgJoystick[ ident ]->error = GL_FALSE; @@ -1590,7 +1323,7 @@ static void fghJoystickInit( int ident ) else snprintf( fgJoystick[ ident ]->os->fname, sizeof(fgJoystick[ ident ]->os->fname), "%s%d", UHIDDEV, ident - USB_IDENT_OFFSET ); -# elif defined( __linux__ ) +#elif defined( __linux__ ) fgJoystick[ ident ]->id = ident; fgJoystick[ ident ]->error = GL_FALSE; @@ -1598,49 +1331,10 @@ static void fghJoystickInit( int ident ) if( access( fgJoystick[ ident ]->fname, F_OK ) != 0 ) snprintf( fgJoystick[ ident ]->fname, sizeof(fgJoystick[ ident ]->fname), "/dev/js%d", ident ); -# endif #endif - - fghJoystickOpen( fgJoystick[ ident ] ); -} - -/* - * Try initializing all the joysticks (well, both of them) - */ -void fgInitialiseJoysticks ( void ) -{ - if( !fgState.JoysticksInitialised ) - { - int ident ; - for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) - fghJoystickInit( ident ); - - fgState.JoysticksInitialised = GL_TRUE; - } -} - -/* - * - */ - -#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__ ) @@ -1664,6 +1358,63 @@ void fgPlatformJoystickClose ( int ident ) #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 ); + +} + +/* + * This function replaces the constructor method in the JS library. + */ +static void fghJoystickInit( int ident ) +{ + if( ident >= MAX_NUM_JOYSTICKS ) + fgError( "Too large a joystick number: %d", ident ); + + if( fgJoystick[ ident ] ) + fgError( "illegal attempt to initialize joystick device again" ); + + fgJoystick[ ident ] = + ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 ); + + /* Set defaults */ + fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0; + fgJoystick[ ident ]->error = GL_TRUE; + + fgPlatformJoystickInit( fgJoystick, ident ); + + fghJoystickOpen( fgJoystick[ ident ] ); +} + +/* + * Try initializing all the joysticks (well, both of them) + */ +void fgInitialiseJoysticks ( void ) +{ + if( !fgState.JoysticksInitialised ) + { + int ident ; + for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) + fghJoystickInit( ident ); + + fgState.JoysticksInitialised = GL_TRUE; + } +} + + void fgJoystickClose( void ) { int ident ;