+ if( pluginResult != S_OK )\r
+ fgWarning ( "QI-ing IO plugin to HID Device interface failed" );\r
+\r
+ ( *plugin )->Release( plugin ); /* don't leak a ref */\r
+ if( joy->hidDev == NULL )\r
+ return;\r
+\r
+ /* store the interface in this instance */\r
+ rv = ( *( joy->hidDev ) )->open( joy->hidDev, 0 );\r
+ if( rv != kIOReturnSuccess )\r
+ {\r
+ fgWarning( "error opening device interface");\r
+ return;\r
+ }\r
+\r
+ props = getCFProperties( ioDevices[ joy->id ] );\r
+\r
+ /* recursively enumerate all the bits */\r
+ CFTypeRef topLevelElement =\r
+ CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) );\r
+ enumerateElements( topLevelElement );\r
+\r
+ CFRelease( props );\r
+}\r
+\r
+\r
+void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )\r
+{\r
+ fgJoystick[ ident ]->id = ident;\r
+ fgJoystick[ ident ]->error = GL_FALSE;\r
+ fgJoystick[ ident ]->num_axes = 0;\r
+ fgJoystick[ ident ]->num_buttons = 0;\r
+\r
+ if( numDevices < 0 )\r
+ {\r
+ /* do first-time init (since we can't over-ride jsInit, hmm */\r
+ numDevices = 0;\r
+\r
+ mach_port_t masterPort;\r
+ IOReturn rv = IOMasterPort( bootstrap_port, &masterPort );\r
+ if( rv != kIOReturnSuccess )\r
+ {\r
+ fgWarning( "error getting master Mach port" );\r
+ return;\r
+ }\r
+ fghJoystickFindDevices( masterPort );\r
+ }\r
+\r
+ if ( ident >= numDevices )\r
+ {\r
+ fgJoystick[ ident ]->error = GL_TRUE;\r
+ return;\r
+ }\r
+\r
+ /* get the name now too */\r
+ CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] );\r
+ CFTypeRef ref = CFDictionaryGetValue( properties,\r
+ CFSTR( kIOHIDProductKey ) );\r
+ if (!ref)\r
+ ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) );\r
+\r
+ if( !ref ||\r
+ !CFStringGetCString( ( CFStringRef )ref, name, 128,\r
+ CFStringGetSystemEncoding( ) ) )\r
+ {\r
+ fgWarning( "error getting device name" );\r
+ name[ 0 ] = '\0';\r
+ }\r
+}\r
+\r
+\r
+void fgPlatformJoystickClose ( int ident )\r
+{\r
+ ( *( fgJoystick[ ident ]->hidDev ) )->\r
+ close( fgJoystick[ ident ]->hidDev );\r
+}\r
+#endif\r
+\r
+#if TARGET_HOST_POSIX_X11\r
+void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )\r
+{\r
+ int status;\r
+\r
+ int i;\r
+\r
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)\r
+ int len;\r
+\r
+ if ( joy->os->is_analog )\r
+ {\r
+ int status = read ( joy->os->fd, &joy->os->ajs, sizeof(joy->os->ajs) );\r
+ if ( status != sizeof(joy->os->ajs) ) {\r
+ perror ( joy->os->fname );\r
+ joy->error = GL_TRUE;\r
+ return;\r
+ }\r
+ if ( buttons != NULL )\r
+ *buttons = ( joy->os->ajs.b1 ? 1 : 0 ) | ( joy->os->ajs.b2 ? 2 : 0 );\r
+\r
+ if ( axes != NULL )\r
+ {\r
+ axes[0] = (float) joy->os->ajs.x;\r
+ axes[1] = (float) joy->os->ajs.y;\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+# ifdef HAVE_USB_JS\r
+ while ( ( len = read ( joy->os->fd, joy->os->hid_data_buf, joy->os->hid_dlen ) ) == joy->os->hid_dlen )\r
+ {\r
+ struct hid_item *h;\r
+\r
+ for ( h = joy->os->hids; h; h = h->next )\r
+ {\r
+ int d = hid_get_data ( joy->os->hid_data_buf, h );\r
+\r
+ int page = HID_PAGE ( h->usage );\r
+ int usage = HID_USAGE ( h->usage );\r
+\r
+ if ( page == HUP_GENERIC_DESKTOP )\r
+ {\r
+ int i;\r
+ for ( i = 0; i < joy->num_axes; i++ )\r
+ if (joy->os->axes_usage[i] == usage)\r
+ {\r
+ if (usage == HUG_HAT_SWITCH)\r
+ {\r
+ if (d < 0 || d > 8)\r
+ d = 0; /* safety */\r
+ joy->os->cache_axes[i] = (float)hatmap_x[d];\r
+ joy->os->cache_axes[i + 1] = (float)hatmap_y[d];\r
+ }\r
+ else\r
+ {\r
+ joy->os->cache_axes[i] = (float)d;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ else if (page == HUP_BUTTON)\r
+ {\r
+ if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)\r
+ {\r
+ if (d)\r
+ joy->os->cache_buttons |= (1 << ( usage - 1 ));\r
+ else\r
+ joy->os->cache_buttons &= ~(1 << ( usage - 1 ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+# ifdef HAVE_ERRNO_H\r
+ if ( len < 0 && errno != EAGAIN )\r
+# else\r
+ if ( len < 0 )\r
+# endif\r
+ {\r
+ perror( joy->os->fname );\r
+ joy->error = 1;\r
+ }\r
+ if ( buttons != NULL ) *buttons = joy->os->cache_buttons;\r
+ if ( axes != NULL )\r
+ memcpy ( axes, joy->os->cache_axes, sizeof(float) * joy->num_axes );\r
+# endif\r
+#endif\r
+\r
+#ifdef JS_NEW\r
+\r
+ while ( 1 )\r
+ {\r
+ status = read ( joy->fd, &joy->js, sizeof(struct js_event) );\r
+\r
+ if ( status != sizeof( struct js_event ) )\r
+ {\r
+# ifdef HAVE_ERRNO_H\r
+ if ( errno == EAGAIN )\r
+ {\r
+ /* Use the old values */\r
+ if ( buttons )\r
+ *buttons = joy->tmp_buttons;\r
+ if ( axes )\r
+ memcpy( axes, joy->tmp_axes,\r
+ sizeof( float ) * joy->num_axes );\r
+ return;\r
+ }\r
+# endif\r
+\r
+ fgWarning ( "%s", joy->fname );\r
+ joy->error = GL_TRUE;\r
+ return;\r
+ }\r
+\r
+ switch ( joy->js.type & ~JS_EVENT_INIT )\r
+ {\r
+ case JS_EVENT_BUTTON:\r
+ if( joy->js.value == 0 ) /* clear the flag */\r
+ joy->tmp_buttons &= ~( 1 << joy->js.number );\r
+ else\r
+ joy->tmp_buttons |= ( 1 << joy->js.number );\r
+ break;\r