+ CFDictionaryRef props;
+ CFTypeRef topLevelElement;
+#endif
+#if TARGET_HOST_UNIX_X11
+# if defined(__FreeBSD__) || defined(__NetBSD__)
+ char *cp;
+# endif
+# ifdef JS_NEW
+ unsigned char u;
+# else
+ int counter;
+# endif
+#endif
+
+ /* 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 ();
+
+ if ( err == noErr )
+ {
+#define ISP_CHECK_ERR(x) if ( x != noErr ) { joy->error = GL_TRUE; return; }
+
+ joy->error = GL_TRUE;
+
+ /* initialize the needs structure */
+ 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 },
+ { "\pZ-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pR-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 4", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 5", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 6", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 7", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+ { "\pAxis 8", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 },
+
+ { "\pButton 0", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 1", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 2", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 3", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 4", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 5", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 6", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 7", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 8", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 9", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 10", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 11", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 12", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 13", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 14", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 15", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 16", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 17", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 18", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 19", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 20", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 21", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 22", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 23", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 24", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 25", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 26", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 27", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 28", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 29", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\pButton 30", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 },
+ { "\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) );
+
+
+ /* next two calls allow keyboard and mouse to emulate other input
+ * devices (gamepads, joysticks, etc)
+ */
+ /*
+ err = ISpDevices_ActivateClass ( kISpDeviceClass_Keyboard );
+ ISP_CHECK_ERR(err)
+
+
+ err = ISpDevices_ActivateClass ( kISpDeviceClass_Mouse );
+ ISP_CHECK_ERR(err)
+ */
+
+ err = ISpElement_NewVirtualFromNeeds ( joy->isp_num_needs, joy->isp_needs, joy->isp_elem, 0 );
+ ISP_CHECK_ERR(err)
+
+ err = ISpInit ( joy->isp_num_needs, joy->isp_needs, joy->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;
+
+ for ( i = 0; i < joy->num_axes; i++ )
+ {
+ joy->dead_band [ i ] = 0;
+ joy->saturate [ i ] = 1;
+ joy->center [ i ] = kISpAxisMiddle;
+ joy->max [ i ] = kISpAxisMaximum;
+ joy->min [ i ] = kISpAxisMinimum;
+ }
+
+ joy->error = GL_FALSE;
+ }
+ else
+ joy->num_buttons = joy->num_axes = 0;
+#endif
+
+#if TARGET_HOST_MAC_OSX
+ if (joy->id >= numDevices) {
+ fgWarning ( "%s", "device index out of range in fgJoystickOpen()");
+ return;
+ }
+
+ /* create device interface */
+ rv = IOCreatePlugInInterfaceForService ( ioDevices[joy->id],
+ kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugin, &score);
+
+ if (rv != kIOReturnSuccess) {
+ fgWarning ( "%s", "error creating plugin for io device");
+ return;
+ }
+
+ pluginResult = (*plugin)->QueryInterface ( plugin,
+ CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), &(LPVOID) joy->hidDev );
+
+ if ( pluginResult != S_OK )
+ fgWarning ( "%s", "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 ( "%s", "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 );
+#endif
+
+#if TARGET_HOST_WIN32