Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/freeglut/src/fg_joystick.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * fg_joystick.c | |
| 3 * | |
| 4 * Joystick handling code | |
| 5 * | |
| 6 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. | |
| 7 * Written by Steve Baker, <sjbaker1@airmail.net> | |
| 8 * | |
| 9 * Permission is hereby granted, free of charge, to any person obtaining a | |
| 10 * copy of this software and associated documentation files (the "Software"), | |
| 11 * to deal in the Software without restriction, including without limitation | |
| 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 13 * and/or sell copies of the Software, and to permit persons to whom the | |
| 14 * Software is furnished to do so, subject to the following conditions: | |
| 15 * | |
| 16 * The above copyright notice and this permission notice shall be included | |
| 17 * in all copies or substantial portions of the Software. | |
| 18 * | |
| 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 22 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
| 23 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 25 */ | |
| 26 | |
| 27 /* | |
| 28 * FreeBSD port by Stephen Montgomery-Smith <stephen@math.missouri.edu> | |
| 29 * | |
| 30 * Redone by John Fay 2/4/04 with another look from the PLIB "js" library. | |
| 31 * Many thanks for Steve Baker for permission to pull from that library. | |
| 32 */ | |
| 33 | |
| 34 #include <GL/freeglut.h> | |
| 35 #include "fg_internal.h" | |
| 36 #ifdef HAVE_SYS_PARAM_H | |
| 37 # include <sys/param.h> | |
| 38 #endif | |
| 39 | |
| 40 #define JS_TRUE 1 | |
| 41 #define JS_FALSE 0 | |
| 42 | |
| 43 /* BSD defines from "jsBSD.cxx" around lines 42-270 */ | |
| 44 | |
| 45 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |
| 46 | |
| 47 # ifdef HAVE_USB_JS | |
| 48 # if defined(__NetBSD__) | |
| 49 /* XXX The below hack is done until freeglut's autoconf is updated. */ | |
| 50 # define HAVE_USBHID_H 1 | |
| 51 # ifdef HAVE_USBHID_H | |
| 52 # include <usbhid.h> | |
| 53 # else | |
| 54 # include <usb.h> | |
| 55 # endif | |
| 56 # elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |
| 57 # ifdef HAVE_USBHID_H | |
| 58 # include <usbhid.h> | |
| 59 # else | |
| 60 # include <libusbhid.h> | |
| 61 # endif | |
| 62 # endif | |
| 63 # include <legacy/dev/usb/usb.h> | |
| 64 # include <dev/usb/usbhid.h> | |
| 65 | |
| 66 /* Compatibility with older usb.h revisions */ | |
| 67 # if !defined(USB_MAX_DEVNAMES) && defined(MAXDEVNAMES) | |
| 68 # define USB_MAX_DEVNAMES MAXDEVNAMES | |
| 69 # endif | |
| 70 # endif | |
| 71 | |
| 72 static int hatmap_x[9] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; | |
| 73 static int hatmap_y[9] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 }; | |
| 74 struct os_specific_s { | |
| 75 char fname [128 ]; | |
| 76 int fd; | |
| 77 int is_analog; | |
| 78 /* The following structure members are specific to analog joysticks */ | |
| 79 struct joystick ajs; | |
| 80 # ifdef HAVE_USB_JS | |
| 81 /* The following structure members are specific to USB joysticks */ | |
| 82 struct hid_item *hids; | |
| 83 int hid_dlen; | |
| 84 int hid_offset; | |
| 85 char *hid_data_buf; | |
| 86 int axes_usage [ _JS_MAX_AXES ]; | |
| 87 # endif | |
| 88 /* We keep button and axes state ourselves, as they might not be updated | |
| 89 * on every read of a USB device | |
| 90 */ | |
| 91 int cache_buttons; | |
| 92 float cache_axes [ _JS_MAX_AXES ]; | |
| 93 }; | |
| 94 | |
| 95 /* Idents lower than USB_IDENT_OFFSET are for analog joysticks. */ | |
| 96 # define USB_IDENT_OFFSET 2 | |
| 97 | |
| 98 # define USBDEV "/dev/usb" | |
| 99 # define UHIDDEV "/dev/uhid" | |
| 100 # define AJSDEV "/dev/joy" | |
| 101 | |
| 102 # ifdef HAVE_USB_JS | |
| 103 /* | |
| 104 * fghJoystickFindUSBdev (and its helper, fghJoystickWalkUSBdev) try to locate | |
| 105 * the full name of a USB device. If /dev/usbN isn't readable, we punt and | |
| 106 * return the uhidN device name. We warn the user of this situation once. | |
| 107 */ | |
| 108 static char *fghJoystickWalkUSBdev(int f, char *dev, char *out, int outlen) | |
| 109 { | |
| 110 struct usb_device_info di; | |
| 111 int i, a; | |
| 112 char *cp; | |
| 113 | |
| 114 for (a = 1; a < USB_MAX_DEVICES; a++) { | |
| 115 di.udi_addr = a; | |
| 116 if (ioctl(f, USB_DEVICEINFO, &di) != 0) | |
| 117 return NULL; | |
| 118 for (i = 0; i < USB_MAX_DEVNAMES; i++) | |
| 119 if (di.udi_devnames[i][0] && | |
| 120 strcmp(di.udi_devnames[i], dev) == 0) { | |
| 121 cp = calloc( 1, strlen(di.udi_vendor) + strlen(di.udi_product) + 2); | |
| 122 strcpy(cp, di.udi_vendor); | |
| 123 strcat(cp, " "); | |
| 124 strcat(cp, di.udi_product); | |
| 125 strncpy(out, cp, outlen - 1); | |
| 126 out[outlen - 1] = 0; | |
| 127 free( cp ); | |
| 128 return out; | |
| 129 } | |
| 130 } | |
| 131 return NULL; | |
| 132 } | |
| 133 | |
| 134 static int fghJoystickFindUSBdev(char *name, char *out, int outlen) | |
| 135 { | |
| 136 int i, f; | |
| 137 char buf[50]; | |
| 138 char *cp; | |
| 139 static int protection_warned = 0; | |
| 140 | |
| 141 for (i = 0; i < 16; i++) { | |
| 142 snprintf(buf, sizeof(buf), "%s%d", USBDEV, i); | |
| 143 f = open(buf, O_RDONLY); | |
| 144 if (f >= 0) { | |
| 145 cp = fghJoystickWalkUSBdev(f, name, out, outlen); | |
| 146 close(f); | |
| 147 if (cp) | |
| 148 return 1; | |
| 149 } | |
| 150 else if (errno == EACCES) { | |
| 151 if (!protection_warned) { | |
| 152 fgWarning ( "Can't open %s for read!", buf ); | |
| 153 protection_warned = 1; | |
| 154 } | |
| 155 } | |
| 156 } | |
| 157 return 0; | |
| 158 } | |
| 159 | |
| 160 static int fghJoystickInitializeHID(struct os_specific_s *os, | |
| 161 int *num_axes, int *num_buttons) | |
| 162 { | |
| 163 int size, is_joystick; | |
| 164 # ifdef HAVE_USBHID_H | |
| 165 int report_id = 0; | |
| 166 # endif | |
| 167 struct hid_data *d; | |
| 168 struct hid_item h; | |
| 169 report_desc_t rd; | |
| 170 | |
| 171 if ( ( rd = hid_get_report_desc( os->fd ) ) == 0 ) | |
| 172 { | |
| 173 fgWarning ( "error: %s: %s", os->fname, strerror( errno ) ); | |
| 174 return FALSE; | |
| 175 } | |
| 176 | |
| 177 os->hids = NULL; | |
| 178 | |
| 179 # ifdef HAVE_USBHID_H | |
| 180 if( ioctl( os->fd, USB_GET_REPORT_ID, &report_id ) < 0) | |
| 181 { | |
| 182 /*** XXX {report_id} may not be the right variable? ***/ | |
| 183 fgWarning ( "error: %s%d: %s", UHIDDEV, report_id, strerror( errno ) ); | |
| 184 return FALSE; | |
| 185 } | |
| 186 | |
| 187 size = hid_report_size( rd, hid_input, report_id ); | |
| 188 # else | |
| 189 size = hid_report_size( rd, 0, hid_input ); | |
| 190 # endif | |
| 191 os->hid_data_buf = calloc( 1, size ); | |
| 192 os->hid_dlen = size; | |
| 193 | |
| 194 is_joystick = 0; | |
| 195 # ifdef HAVE_USBHID_H | |
| 196 d = hid_start_parse( rd, 1 << hid_input, report_id ); | |
| 197 # else | |
| 198 d = hid_start_parse( rd, 1 << hid_input ); | |
| 199 # endif | |
| 200 while( hid_get_item( d, &h ) ) | |
| 201 { | |
| 202 int usage, page, interesting_hid; | |
| 203 | |
| 204 page = HID_PAGE( h.usage ); | |
| 205 usage = HID_USAGE( h.usage ); | |
| 206 | |
| 207 /* This test is somewhat too simplistic, but this is how MicroSoft | |
| 208 * does, so I guess it works for all joysticks/game pads. */ | |
| 209 is_joystick = is_joystick || | |
| 210 ( h.kind == hid_collection && | |
| 211 page == HUP_GENERIC_DESKTOP && | |
| 212 ( usage == HUG_JOYSTICK || usage == HUG_GAME_PAD ) ); | |
| 213 | |
| 214 if( h.kind != hid_input ) | |
| 215 continue; | |
| 216 | |
| 217 if( !is_joystick ) | |
| 218 continue; | |
| 219 | |
| 220 interesting_hid = TRUE; | |
| 221 if( page == HUP_GENERIC_DESKTOP ) | |
| 222 { | |
| 223 switch( usage ) | |
| 224 { | |
| 225 case HUG_X: | |
| 226 case HUG_RX: | |
| 227 case HUG_Y: | |
| 228 case HUG_RY: | |
| 229 case HUG_Z: | |
| 230 case HUG_RZ: | |
| 231 case HUG_SLIDER: | |
| 232 if( *num_axes < _JS_MAX_AXES ) | |
| 233 { | |
| 234 os->axes_usage[ *num_axes ] = usage; | |
| 235 ( *num_axes )++; | |
| 236 } | |
| 237 break; | |
| 238 case HUG_HAT_SWITCH: | |
| 239 /* Allocate two axes for a hat */ | |
| 240 if( *num_axes + 1 < _JS_MAX_AXES ) | |
| 241 { | |
| 242 os->axes_usage[ *num_axes ] = usage; | |
| 243 (*num_axes)++; | |
| 244 os->axes_usage[ *num_axes ] = usage; | |
| 245 (*num_axes)++; | |
| 246 } | |
| 247 break; | |
| 248 default: | |
| 249 interesting_hid = FALSE; | |
| 250 break; | |
| 251 } | |
| 252 } | |
| 253 else if( page == HUP_BUTTON ) | |
| 254 { | |
| 255 interesting_hid = ( usage > 0 ) && | |
| 256 ( usage <= _JS_MAX_BUTTONS ); | |
| 257 | |
| 258 if( interesting_hid && usage - 1 > *num_buttons ) | |
| 259 *num_buttons = usage - 1; | |
| 260 } | |
| 261 | |
| 262 if( interesting_hid ) | |
| 263 { | |
| 264 h.next = os->hids; | |
| 265 os->hids = calloc( 1, sizeof ( struct hid_item ) ); | |
| 266 *os->hids = h; | |
| 267 } | |
| 268 } | |
| 269 hid_end_parse( d ); | |
| 270 | |
| 271 return os->hids != NULL; | |
| 272 } | |
| 273 # endif | |
| 274 #endif | |
| 275 | |
| 276 /* | |
| 277 * Functions associated with the "jsJoystick" class in PLIB | |
| 278 */ | |
| 279 #if TARGET_HOST_MAC_OSX | |
| 280 #define K_NUM_DEVICES 32 | |
| 281 int numDevices; | |
| 282 io_object_t ioDevices[K_NUM_DEVICES]; | |
| 283 | |
| 284 static void fghJoystickFindDevices ( SFG_Joystick* joy, mach_port_t ); | |
| 285 static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick* joy, io_object_t ); | |
| 286 | |
| 287 static void fghJoystickEnumerateElements ( SFG_Joystick* joy, CFTypeRef element ); | |
| 288 /* callback for CFArrayApply */ | |
| 289 static void fghJoystickElementEnumerator ( SFG_Joystick* joy, void *element, void* vjs ); | |
| 290 | |
| 291 static void fghJoystickAddAxisElement ( SFG_Joystick* joy, CFDictionaryRef axis ); | |
| 292 static void fghJoystickAddButtonElement ( SFG_Joystick* joy, CFDictionaryRef button ); | |
| 293 static void fghJoystickAddHatElement ( SFG_Joystick* joy, CFDictionaryRef hat ); | |
| 294 #endif | |
| 295 | |
| 296 | |
| 297 /* External function declarations (mostly platform-specific) */ | |
| 298 extern void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ); | |
| 299 extern void fgPlatformJoystickOpen( SFG_Joystick* joy ); | |
| 300 extern void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ); | |
| 301 extern void fgPlatformJoystickClose ( int ident ); | |
| 302 | |
| 303 /* | |
| 304 * The static joystick structure pointer | |
| 305 */ | |
| 306 #define MAX_NUM_JOYSTICKS 2 | |
| 307 SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ]; | |
| 308 | |
| 309 /* | |
| 310 * Read the raw joystick data | |
| 311 */ | |
| 312 static void fghJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) | |
| 313 { | |
| 314 int i; | |
| 315 | |
| 316 /* Defaults */ | |
| 317 if( buttons ) | |
| 318 *buttons = 0; | |
| 319 | |
| 320 if( axes ) | |
| 321 for( i = 0; i < joy->num_axes; i++ ) | |
| 322 axes[ i ] = 1500.0f; | |
| 323 | |
| 324 if( joy->error ) | |
| 325 return; | |
| 326 | |
| 327 fgPlatformJoystickRawRead ( joy, buttons, axes ); | |
| 328 } | |
| 329 | |
| 330 /* | |
| 331 * Correct the joystick axis data | |
| 332 */ | |
| 333 static float fghJoystickFudgeAxis( SFG_Joystick* joy, float value, int axis ) | |
| 334 { | |
| 335 if( value < joy->center[ axis ] ) | |
| 336 { | |
| 337 float xx = ( value - joy->center[ axis ] ) / ( joy->center[ axis ] - | |
| 338 joy->min[ axis ] ); | |
| 339 | |
| 340 if( xx < -joy->saturate[ axis ] ) | |
| 341 return -1.0f; | |
| 342 | |
| 343 if( xx > -joy->dead_band [ axis ] ) | |
| 344 return 0.0f; | |
| 345 | |
| 346 xx = ( xx + joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - | |
| 347 joy->dead_band[ axis ] ); | |
| 348 | |
| 349 return ( xx < -1.0f ) ? -1.0f : xx; | |
| 350 } | |
| 351 else | |
| 352 { | |
| 353 float xx = ( value - joy->center [ axis ] ) / ( joy->max[ axis ] - | |
| 354 joy->center[ axis ] ); | |
| 355 | |
| 356 if( xx > joy->saturate[ axis ] ) | |
| 357 return 1.0f; | |
| 358 | |
| 359 if( xx < joy->dead_band[ axis ] ) | |
| 360 return 0.0f; | |
| 361 | |
| 362 xx = ( xx - joy->dead_band[ axis ] ) / ( joy->saturate[ axis ] - | |
| 363 joy->dead_band[ axis ] ); | |
| 364 | |
| 365 return ( xx > 1.0f ) ? 1.0f : xx; | |
| 366 } | |
| 367 } | |
| 368 | |
| 369 /* | |
| 370 * Read the corrected joystick data | |
| 371 */ | |
| 372 static void fghJoystickRead( SFG_Joystick* joy, int* buttons, float* axes ) | |
| 373 { | |
| 374 float raw_axes[ _JS_MAX_AXES ]; | |
| 375 int i; | |
| 376 | |
| 377 if( joy->error ) | |
| 378 { | |
| 379 if( buttons ) | |
| 380 *buttons = 0; | |
| 381 | |
| 382 if( axes ) | |
| 383 for ( i=0; i<joy->num_axes; i++ ) | |
| 384 axes[ i ] = 0.0f; | |
| 385 } | |
| 386 | |
| 387 fghJoystickRawRead( joy, buttons, raw_axes ); | |
| 388 | |
| 389 if( axes ) | |
| 390 for( i=0; i<joy->num_axes; i++ ) | |
| 391 axes[ i ] = fghJoystickFudgeAxis( joy, raw_axes[ i ], i ); | |
| 392 } | |
| 393 | |
| 394 /* | |
| 395 * Happy happy happy joy joy joy (happy new year toudi :D) | |
| 396 */ | |
| 397 | |
| 398 | |
| 399 #if TARGET_HOST_MAC_OSX | |
| 400 /** open the IOKit connection, enumerate all the HID devices, add their | |
| 401 interface references to the static array. We then use the array index | |
| 402 as the device number when we come to open() the joystick. */ | |
| 403 static int fghJoystickFindDevices ( SFG_Joystick *joy, mach_port_t masterPort ) | |
| 404 { | |
| 405 CFMutableDictionaryRef hidMatch = NULL; | |
| 406 IOReturn rv = kIOReturnSuccess; | |
| 407 | |
| 408 io_iterator_t hidIterator; | |
| 409 io_object_t ioDev; | |
| 410 | |
| 411 /* build a dictionary matching HID devices */ | |
| 412 hidMatch = IOServiceMatching(kIOHIDDeviceKey); | |
| 413 | |
| 414 rv = IOServiceGetMatchingServices(masterPort, hidMatch, &hidIterator); | |
| 415 if (rv != kIOReturnSuccess || !hidIterator) { | |
| 416 fgWarning( "no joystick (HID) devices found" ); | |
| 417 return; | |
| 418 } | |
| 419 | |
| 420 /* iterate */ | |
| 421 while ((ioDev = IOIteratorNext(hidIterator))) { | |
| 422 /* filter out keyboard and mouse devices */ | |
| 423 CFDictionaryRef properties = getCFProperties(ioDev); | |
| 424 long usage, page; | |
| 425 | |
| 426 CFTypeRef refPage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsagePageKey)); | |
| 427 CFTypeRef refUsage = CFDictionaryGetValue (properties, CFSTR(kIOHIDPrimaryUsageKey)); | |
| 428 CFNumberGetValue((CFNumberRef) refUsage, kCFNumberLongType, &usage); | |
| 429 CFNumberGetValue((CFNumberRef) refPage, kCFNumberLongType, &page); | |
| 430 | |
| 431 /* keep only joystick devices */ | |
| 432 if ( ( page == kHIDPage_GenericDesktop ) && ( | |
| 433 (usage == kHIDUsage_GD_Joystick) | |
| 434 || (usage == kHIDUsage_GD_GamePad) | |
| 435 || (usage == kHIDUsage_GD_MultiAxisController) | |
| 436 || (usage == kHIDUsage_GD_Hatswitch) /* last two necessary ? */ | |
| 437 /* add it to the array */ | |
| 438 ioDevices[numDevices++] = ioDev; | |
| 439 } | |
| 440 | |
| 441 IOObjectRelease(hidIterator); | |
| 442 } | |
| 443 | |
| 444 static CFDictionaryRef fghJoystickGetCFProperties ( SFG_Joystick *joy, io_object_t ioDev ) | |
| 445 { | |
| 446 IOReturn rv; | |
| 447 CFMutableDictionaryRef cfProperties; | |
| 448 | |
| 449 #if 0 | |
| 450 /* comment copied from darwin/SDL_sysjoystick.c */ | |
| 451 /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also | |
| 452 * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties | |
| 453 */ | |
| 454 | |
| 455 io_registry_entry_t parent1, parent2; | |
| 456 | |
| 457 rv = IORegistryEntryGetParentEntry (ioDev, kIOServicePlane, &parent1); | |
| 458 if (rv != kIOReturnSuccess) { | |
| 459 fgWarning ( "error getting device entry parent"); | |
| 460 return NULL; | |
| 461 } | |
| 462 | |
| 463 rv = IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2); | |
| 464 if (rv != kIOReturnSuccess) { | |
| 465 fgWarning ( "error getting device entry parent 2"); | |
| 466 return NULL; | |
| 467 } | |
| 468 #endif | |
| 469 | |
| 470 rv = IORegistryEntryCreateCFProperties( ioDev /*parent2*/, | |
| 471 &cfProperties, kCFAllocatorDefault, kNilOptions); | |
| 472 if (rv != kIOReturnSuccess || !cfProperties) { | |
| 473 fgWarning ( "error getting device properties"); | |
| 474 return NULL; | |
| 475 } | |
| 476 | |
| 477 return cfProperties; | |
| 478 } | |
| 479 | |
| 480 static void fghJoystickElementEnumerator ( SFG_Joystick *joy, void *element, void* vjs ) | |
| 481 { | |
| 482 if (CFGetTypeID((CFTypeRef) element) != CFDictionaryGetTypeID()) { | |
| 483 fgError ( "%s", "element enumerator passed non-dictionary value"); | |
| 484 return; | |
| 485 } | |
| 486 | |
| 487 static_cast<jsJoystick*>(vjs)->parseElement ( (CFDictionaryRef) element ); | |
| 488 } | |
| 489 | |
| 490 /** element enumerator function : pass NULL for top-level*/ | |
| 491 static void fghJoystickEnumerateElements ( SFG_Joystick *joy, CFTypeRef element ) | |
| 492 { | |
| 493 FREEGLUT_INTERNAL_ERROR_EXIT( (CFGetTypeID(element) == CFArrayGetTypeID(), | |
| 494 "Joystick element type mismatch", | |
| 495 "fghJoystickEnumerateElements" ); | |
| 496 | |
| 497 CFRange range = {0, CFArrayGetCount ((CFArrayRef)element)}; | |
| 498 CFArrayApplyFunction((CFArrayRef) element, range, | |
| 499 &fghJoystickElementEnumerator, joy ); | |
| 500 } | |
| 501 | |
| 502 static void fghJoystickAddAxisElement ( SFG_Joystick *joy, CFDictionaryRef axis ) | |
| 503 { | |
| 504 long cookie, lmin, lmax; | |
| 505 int index = joy->num_axes++; | |
| 506 | |
| 507 CFNumberGetValue ((CFNumberRef) | |
| 508 CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementCookieKey) ), | |
| 509 kCFNumberLongType, &cookie); | |
| 510 | |
| 511 joy->pJoystick.axisCookies[index] = (IOHIDElementCookie) cookie; | |
| 512 | |
| 513 CFNumberGetValue ((CFNumberRef) | |
| 514 CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMinKey) ), | |
| 515 kCFNumberLongType, &lmin); | |
| 516 | |
| 517 CFNumberGetValue ((CFNumberRef) | |
| 518 CFDictionaryGetValue ( axis, CFSTR(kIOHIDElementMaxKey) ), | |
| 519 kCFNumberLongType, &lmax); | |
| 520 | |
| 521 joy->min[index] = lmin; | |
| 522 joy->max[index] = lmax; | |
| 523 joy->dead_band[index] = 0.0; | |
| 524 joy->saturate[index] = 1.0; | |
| 525 joy->center[index] = (lmax + lmin) * 0.5; | |
| 526 } | |
| 527 | |
| 528 static void fghJoystickAddButtonElement ( SFG_Joystick *joy, CFDictionaryRef button ) | |
| 529 { | |
| 530 long cookie; | |
| 531 CFNumberGetValue ((CFNumberRef) | |
| 532 CFDictionaryGetValue ( button, CFSTR(kIOHIDElementCookieKey) ), | |
| 533 kCFNumberLongType, &cookie); | |
| 534 | |
| 535 joy->pJoystick.buttonCookies[num_buttons++] = (IOHIDElementCookie) cookie; | |
| 536 /* anything else for buttons? */ | |
| 537 } | |
| 538 | |
| 539 static void fghJoystickAddHatElement ( SFG_Joystick *joy, CFDictionaryRef button ) | |
| 540 { | |
| 541 /* hatCookies[num_hats++] = (IOHIDElementCookie) cookie; */ | |
| 542 /* do we map hats to axes or buttons? */ | |
| 543 } | |
| 544 #endif | |
| 545 | |
| 546 /* | |
| 547 * Platform-Specific Code | |
| 548 */ | |
| 549 | |
| 550 #if TARGET_HOST_MACINTOSH | |
| 551 void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) | |
| 552 { | |
| 553 int i; | |
| 554 | |
| 555 if ( buttons ) | |
| 556 { | |
| 557 *buttons = 0; | |
| 558 | |
| 559 for ( i = 0; i < joy->num_buttons; i++ ) | |
| 560 { | |
| 561 UInt32 state; | |
| 562 int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i + ISP_NUM_AXIS ], &state); | |
| 563 ISP_CHECK_ERR(err) | |
| 564 | |
| 565 *buttons |= state << i; | |
| 566 } | |
| 567 } | |
| 568 | |
| 569 if ( axes ) | |
| 570 { | |
| 571 for ( i = 0; i < joy->num_axes; i++ ) | |
| 572 { | |
| 573 UInt32 state; | |
| 574 int err = ISpElement_GetSimpleState ( joy->pJoystick.isp_elem [ i ], &state ); | |
| 575 ISP_CHECK_ERR(err) | |
| 576 | |
| 577 axes [i] = (float) state; | |
| 578 } | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 | |
| 583 void fgPlatformJoystickOpen( SFG_Joystick* joy ) | |
| 584 { | |
| 585 int i = 0; | |
| 586 OSStatus err; | |
| 587 | |
| 588 /* XXX FIXME: get joystick name in Mac */ | |
| 589 | |
| 590 err = ISpStartup( ); | |
| 591 | |
| 592 if( err == noErr ) | |
| 593 { | |
| 594 #define ISP_CHECK_ERR(x) if( x != noErr ) { joy->error = GL_TRUE; return; } | |
| 595 | |
| 596 joy->error = GL_TRUE; | |
| 597 | |
| 598 /* initialize the needs structure */ | |
| 599 ISpNeed temp_isp_needs[ ISP_NUM_NEEDS ] = | |
| 600 { | |
| 601 { "\pX-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 602 { "\pY-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 603 { "\pZ-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 604 { "\pR-Axis", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 605 { "\pAxis 4", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 606 { "\pAxis 5", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 607 { "\pAxis 6", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 608 { "\pAxis 7", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 609 { "\pAxis 8", 128, 0, 0, kISpElementKind_Axis, kISpElementLabel_None, 0, 0, 0, 0 }, | |
| 610 | |
| 611 { "\pButton 0", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 612 { "\pButton 1", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 613 { "\pButton 2", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 614 { "\pButton 3", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 615 { "\pButton 4", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 616 { "\pButton 5", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 617 { "\pButton 6", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 618 { "\pButton 7", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 619 { "\pButton 8", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 620 { "\pButton 9", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 621 { "\pButton 10", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 622 { "\pButton 11", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 623 { "\pButton 12", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 624 { "\pButton 13", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 625 { "\pButton 14", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 626 { "\pButton 15", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 627 { "\pButton 16", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 628 { "\pButton 17", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 629 { "\pButton 18", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 630 { "\pButton 19", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 631 { "\pButton 20", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 632 { "\pButton 21", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 633 { "\pButton 22", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 634 { "\pButton 23", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 635 { "\pButton 24", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 636 { "\pButton 25", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 637 { "\pButton 26", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 638 { "\pButton 27", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 639 { "\pButton 28", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 640 { "\pButton 29", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 641 { "\pButton 30", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 642 { "\pButton 31", 128, 0, 0, kISpElementKind_Button, kISpElementLabel_Btn_Select, 0, 0, 0, 0 }, | |
| 643 }; | |
| 644 | |
| 645 memcpy( joy->pJoystick.isp_needs, temp_isp_needs, sizeof (temp_isp_needs ) ); | |
| 646 | |
| 647 | |
| 648 /* next two calls allow keyboard and mouse to emulate other input | |
| 649 * devices (gamepads, joysticks, etc) | |
| 650 */ | |
| 651 /* | |
| 652 err = ISpDevices_ActivateClass ( kISpDeviceClass_Keyboard ); | |
| 653 ISP_CHECK_ERR(err) | |
| 654 | |
| 655 | |
| 656 err = ISpDevices_ActivateClass ( kISpDeviceClass_Mouse ); | |
| 657 ISP_CHECK_ERR(err) | |
| 658 */ | |
| 659 | |
| 660 err = ISpElement_NewVirtualFromNeeds( ISP_NUM_NEEDS, | |
| 661 joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, | |
| 662 0 ); | |
| 663 ISP_CHECK_ERR( err ) | |
| 664 | |
| 665 err = ISpInit( ISP_NUM_NEEDS, joy->pJoystick.isp_needs, joy->pJoystick.isp_elem, | |
| 666 'freeglut', nil, 0, 128, 0 ); | |
| 667 ISP_CHECK_ERR( err ) | |
| 668 | |
| 669 joy->num_buttons = ISP_NUM_NEEDS - ISP_NUM_AXIS; | |
| 670 joy->num_axes = ISP_NUM_AXIS; | |
| 671 | |
| 672 for( i = 0; i < joy->num_axes; i++ ) | |
| 673 { | |
| 674 joy->dead_band[ i ] = 0; | |
| 675 joy->saturate [ i ] = 1; | |
| 676 joy->center [ i ] = kISpAxisMiddle; | |
| 677 joy->max [ i ] = kISpAxisMaximum; | |
| 678 joy->min [ i ] = kISpAxisMinimum; | |
| 679 } | |
| 680 | |
| 681 joy->error = GL_FALSE; | |
| 682 } | |
| 683 else | |
| 684 joy->num_buttons = joy->num_axes = 0; | |
| 685 } | |
| 686 | |
| 687 | |
| 688 void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) | |
| 689 { | |
| 690 fgJoystick[ ident ]->id = ident; | |
| 691 snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident ); /* FIXME */ | |
| 692 fgJoystick[ ident ]->error = GL_FALSE; | |
| 693 } | |
| 694 | |
| 695 | |
| 696 void fgPlatformJoystickClose ( int ident ) | |
| 697 { | |
| 698 ISpSuspend( ); | |
| 699 ISpStop( ); | |
| 700 ISpShutdown( ); | |
| 701 } | |
| 702 #endif | |
| 703 | |
| 704 #if TARGET_HOST_MAC_OSX | |
| 705 void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes ) | |
| 706 { | |
| 707 int i; | |
| 708 | |
| 709 if ( buttons != NULL ) | |
| 710 { | |
| 711 *buttons = 0; | |
| 712 | |
| 713 for ( i = 0; i < joy->num_buttons; i++ ) | |
| 714 { | |
| 715 IOHIDEventStruct hidEvent; | |
| 716 (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.buttonCookies[i], &hidEvent ); | |
| 717 if ( hidEvent.value ) | |
| 718 *buttons |= 1 << i; | |
| 719 } | |
| 720 } | |
| 721 | |
| 722 if ( axes != NULL ) | |
| 723 { | |
| 724 for ( i = 0; i < joy->num_axes; i++ ) | |
| 725 { | |
| 726 IOHIDEventStruct hidEvent; | |
| 727 (*(joy->pJoystick.hidDev))->getElementValue ( joy->pJoystick.hidDev, joy->pJoystick.axisCookies[i], &hidEvent ); | |
| 728 axes[i] = hidEvent.value; | |
| 729 } | |
| 730 } | |
| 731 } | |
| 732 | |
| 733 | |
| 734 void fgPlatformJoystickOpen( SFG_Joystick* joy ) | |
| 735 { | |
| 736 IOReturn rv; | |
| 737 SInt32 score; | |
| 738 IOCFPlugInInterface **plugin; | |
| 739 | |
| 740 HRESULT pluginResult; | |
| 741 | |
| 742 CFDictionaryRef props; | |
| 743 CFTypeRef topLevelElement; | |
| 744 | |
| 745 if( joy->id >= numDevices ) | |
| 746 { | |
| 747 fgWarning( "device index out of range in fgJoystickOpen()" ); | |
| 748 return; | |
| 749 } | |
| 750 | |
| 751 /* create device interface */ | |
| 752 rv = IOCreatePlugInInterfaceForService( ioDevices[ joy->id ], | |
| 753 kIOHIDDeviceUserClientTypeID, | |
| 754 kIOCFPlugInInterfaceID, | |
| 755 &plugin, &score ); | |
| 756 | |
| 757 if( rv != kIOReturnSuccess ) | |
| 758 { | |
| 759 fgWarning( "error creating plugin for io device" ); | |
| 760 return; | |
| 761 } | |
| 762 | |
| 763 pluginResult = ( *plugin )->QueryInterface( | |
| 764 plugin, | |
| 765 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), | |
| 766 &( LPVOID )joy->pJoystick.hidDev | |
| 767 ); | |
| 768 | |
| 769 if( pluginResult != S_OK ) | |
| 770 fgWarning ( "QI-ing IO plugin to HID Device interface failed" ); | |
| 771 | |
| 772 ( *plugin )->Release( plugin ); /* don't leak a ref */ | |
| 773 if( joy->pJoystick.hidDev == NULL ) | |
| 774 return; | |
| 775 | |
| 776 /* store the interface in this instance */ | |
| 777 rv = ( *( joy->pJoystick.hidDev ) )->open( joy->pJoystick.hidDev, 0 ); | |
| 778 if( rv != kIOReturnSuccess ) | |
| 779 { | |
| 780 fgWarning( "error opening device interface"); | |
| 781 return; | |
| 782 } | |
| 783 | |
| 784 props = getCFProperties( ioDevices[ joy->id ] ); | |
| 785 | |
| 786 /* recursively enumerate all the bits */ | |
| 787 CFTypeRef topLevelElement = | |
| 788 CFDictionaryGetValue( props, CFSTR( kIOHIDElementKey ) ); | |
| 789 enumerateElements( topLevelElement ); | |
| 790 | |
| 791 CFRelease( props ); | |
| 792 } | |
| 793 | |
| 794 | |
| 795 void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident ) | |
| 796 { | |
| 797 fgJoystick[ ident ]->id = ident; | |
| 798 fgJoystick[ ident ]->error = GL_FALSE; | |
| 799 fgJoystick[ ident ]->num_axes = 0; | |
| 800 fgJoystick[ ident ]->num_buttons = 0; | |
| 801 | |
| 802 if( numDevices < 0 ) | |
| 803 { | |
| 804 /* do first-time init (since we can't over-ride jsInit, hmm */ | |
| 805 numDevices = 0; | |
| 806 | |
| 807 mach_port_t masterPort; | |
| 808 IOReturn rv = IOMasterPort( bootstrap_port, &masterPort ); | |
| 809 if( rv != kIOReturnSuccess ) | |
| 810 { | |
| 811 fgWarning( "error getting master Mach port" ); | |
| 812 return; | |
| 813 } | |
| 814 fghJoystickFindDevices( masterPort ); | |
| 815 } | |
| 816 | |
| 817 if ( ident >= numDevices ) | |
| 818 { | |
| 819 fgJoystick[ ident ]->error = GL_TRUE; | |
| 820 return; | |
| 821 } | |
| 822 | |
| 823 /* get the name now too */ | |
| 824 CFDictionaryRef properties = getCFProperties( ioDevices[ ident ] ); | |
| 825 CFTypeRef ref = CFDictionaryGetValue( properties, | |
| 826 CFSTR( kIOHIDProductKey ) ); | |
| 827 if (!ref) | |
| 828 ref = CFDictionaryGetValue(properties, CFSTR( "USB Product Name" ) ); | |
| 829 | |
| 830 if( !ref || | |
| 831 !CFStringGetCString( ( CFStringRef )ref, name, 128, | |
| 832 CFStringGetSystemEncoding( ) ) ) | |
| 833 { | |
| 834 fgWarning( "error getting device name" ); | |
| 835 name[ 0 ] = '\0'; | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 | |
| 840 void fgPlatformJoystickClose ( int ident ) | |
| 841 { | |
| 842 ( *( fgJoystick[ ident ]->pJoystick.hidDev ) )-> | |
| 843 close( fgJoystick[ ident ]->pJoystick.hidDev ); | |
| 844 } | |
| 845 #endif | |
| 846 | |
| 847 | |
| 848 | |
| 849 | |
| 850 static void fghJoystickOpen( SFG_Joystick* joy ) | |
| 851 { | |
| 852 /* | |
| 853 * Default values (for no joystick -- each conditional will reset the | |
| 854 * error flag) | |
| 855 */ | |
| 856 joy->error = TRUE; | |
| 857 joy->num_axes = joy->num_buttons = 0; | |
| 858 joy->name[ 0 ] = '\0'; | |
| 859 | |
| 860 fgPlatformJoystickOpen ( joy ); | |
| 861 | |
| 862 } | |
| 863 | |
| 864 /* | |
| 865 * This function replaces the constructor method in the JS library. | |
| 866 */ | |
| 867 static void fghJoystickInit( int ident ) | |
| 868 { | |
| 869 if( ident >= MAX_NUM_JOYSTICKS ) | |
| 870 fgError( "Too large a joystick number: %d", ident ); | |
| 871 | |
| 872 if( fgJoystick[ ident ] ) | |
| 873 fgError( "illegal attempt to initialize joystick device again" ); | |
| 874 | |
| 875 fgJoystick[ ident ] = | |
| 876 ( SFG_Joystick * )calloc( sizeof( SFG_Joystick ), 1 ); | |
| 877 | |
| 878 /* Set defaults */ | |
| 879 fgJoystick[ ident ]->num_axes = fgJoystick[ ident ]->num_buttons = 0; | |
| 880 fgJoystick[ ident ]->error = GL_TRUE; | |
| 881 | |
| 882 fgPlatformJoystickInit( fgJoystick, ident ); | |
| 883 | |
| 884 fghJoystickOpen( fgJoystick[ ident ] ); | |
| 885 } | |
| 886 | |
| 887 /* | |
| 888 * Try initializing all the joysticks (well, both of them) | |
| 889 */ | |
| 890 void fgInitialiseJoysticks ( void ) | |
| 891 { | |
| 892 if( !fgState.JoysticksInitialised ) | |
| 893 { | |
| 894 int ident ; | |
| 895 for ( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) | |
| 896 fghJoystickInit( ident ); | |
| 897 | |
| 898 fgState.JoysticksInitialised = GL_TRUE; | |
| 899 } | |
| 900 } | |
| 901 | |
| 902 | |
| 903 void fgJoystickClose( void ) | |
| 904 { | |
| 905 int ident ; | |
| 906 for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) | |
| 907 { | |
| 908 if( fgJoystick[ ident ] ) | |
| 909 { | |
| 910 fgPlatformJoystickClose ( ident ); | |
| 911 | |
| 912 free( fgJoystick[ ident ] ); | |
| 913 fgJoystick[ ident ] = NULL; | |
| 914 /* show joystick has been deinitialized */ | |
| 915 } | |
| 916 } | |
| 917 } | |
| 918 | |
| 919 /* | |
| 920 * Polls the joystick and executes the joystick callback hooked to the | |
| 921 * window specified in the function's parameter: | |
| 922 */ | |
| 923 void fgJoystickPollWindow( SFG_Window* window ) | |
| 924 { | |
| 925 float axes[ _JS_MAX_AXES ]; | |
| 926 int buttons; | |
| 927 int ident; | |
| 928 | |
| 929 freeglut_return_if_fail( window ); | |
| 930 freeglut_return_if_fail( FETCH_WCB( *window, Joystick ) ); | |
| 931 | |
| 932 for( ident = 0; ident < MAX_NUM_JOYSTICKS; ident++ ) | |
| 933 { | |
| 934 if( fgJoystick[ident] ) | |
| 935 { | |
| 936 fghJoystickRead( fgJoystick[ident], &buttons, axes ); | |
| 937 | |
| 938 if( !fgJoystick[ident]->error ) | |
| 939 INVOKE_WCB( *window, Joystick, | |
| 940 ( buttons, | |
| 941 (int) ( axes[ 0 ] * 1000.0f ), | |
| 942 (int) ( axes[ 1 ] * 1000.0f ), | |
| 943 (int) ( axes[ 2 ] * 1000.0f ) ) | |
| 944 ); | |
| 945 } | |
| 946 } | |
| 947 } | |
| 948 | |
| 949 /* | |
| 950 * Implementation for glutDeviceGet(GLUT_HAS_JOYSTICK) | |
| 951 */ | |
| 952 int fgJoystickDetect( void ) | |
| 953 { | |
| 954 int ident; | |
| 955 | |
| 956 fgInitialiseJoysticks (); | |
| 957 | |
| 958 if ( !fgState.JoysticksInitialised ) | |
| 959 return 0; | |
| 960 | |
| 961 for( ident=0; ident<MAX_NUM_JOYSTICKS; ident++ ) | |
| 962 if( fgJoystick[ident] && !fgJoystick[ident]->error ) | |
| 963 return 1; | |
| 964 | |
| 965 return 0; | |
| 966 } | |
| 967 | |
| 968 /* | |
| 969 * Joystick information, setup and execution functions | |
| 970 */ | |
| 971 | |
| 972 /* | |
| 973 * Forces the joystick callback to be executed | |
| 974 */ | |
| 975 void FGAPIENTRY glutForceJoystickFunc( void ) | |
| 976 { | |
| 977 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutForceJoystickFunc" ); | |
| 978 #if !defined(_WIN32_WCE) | |
| 979 freeglut_return_if_fail( fgStructure.CurrentWindow != NULL ); | |
| 980 freeglut_return_if_fail( FETCH_WCB( *( fgStructure.CurrentWindow ), Joystick ) ); | |
| 981 fgJoystickPollWindow( fgStructure.CurrentWindow ); | |
| 982 #endif /* !defined(_WIN32_WCE) */ | |
| 983 } | |
| 984 int glutJoystickGetNumAxes( int ident ) | |
| 985 { | |
| 986 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumAxes" ); | |
| 987 return fgJoystick[ ident ]->num_axes; | |
| 988 } | |
| 989 int glutJoystickGetNumButtons( int ident ) | |
| 990 { | |
| 991 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetNumButtons" ); | |
| 992 return fgJoystick[ ident ]->num_buttons; | |
| 993 } | |
| 994 int glutJoystickNotWorking( int ident ) | |
| 995 { | |
| 996 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickNotWorking" ); | |
| 997 return fgJoystick[ ident ]->error; | |
| 998 } | |
| 999 | |
| 1000 float glutJoystickGetDeadBand( int ident, int axis ) | |
| 1001 { | |
| 1002 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetDeadBand" ); | |
| 1003 return fgJoystick[ ident ]->dead_band [ axis ]; | |
| 1004 } | |
| 1005 void glutJoystickSetDeadBand( int ident, int axis, float db ) | |
| 1006 { | |
| 1007 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetDeadBand" ); | |
| 1008 fgJoystick[ ident ]->dead_band[ axis ] = db; | |
| 1009 } | |
| 1010 | |
| 1011 float glutJoystickGetSaturation( int ident, int axis ) | |
| 1012 { | |
| 1013 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetSaturation" ); | |
| 1014 return fgJoystick[ ident ]->saturate[ axis ]; | |
| 1015 } | |
| 1016 void glutJoystickSetSaturation( int ident, int axis, float st ) | |
| 1017 { | |
| 1018 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetSaturation" ); | |
| 1019 fgJoystick[ ident ]->saturate [ axis ] = st; | |
| 1020 } | |
| 1021 | |
| 1022 void glutJoystickSetMinRange( int ident, float *axes ) | |
| 1023 { | |
| 1024 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMinRange" ); | |
| 1025 memcpy( fgJoystick[ ident ]->min, axes, | |
| 1026 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1027 } | |
| 1028 void glutJoystickSetMaxRange( int ident, float *axes ) | |
| 1029 { | |
| 1030 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetMaxRange" ); | |
| 1031 memcpy( fgJoystick[ ident ]->max, axes, | |
| 1032 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1033 } | |
| 1034 void glutJoystickSetCenter( int ident, float *axes ) | |
| 1035 { | |
| 1036 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickSetCenter" ); | |
| 1037 memcpy( fgJoystick[ ident ]->center, axes, | |
| 1038 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1039 } | |
| 1040 | |
| 1041 void glutJoystickGetMinRange( int ident, float *axes ) | |
| 1042 { | |
| 1043 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMinRange" ); | |
| 1044 memcpy( axes, fgJoystick[ ident ]->min, | |
| 1045 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1046 } | |
| 1047 void glutJoystickGetMaxRange( int ident, float *axes ) | |
| 1048 { | |
| 1049 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetMaxRange" ); | |
| 1050 memcpy( axes, fgJoystick[ ident ]->max, | |
| 1051 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1052 } | |
| 1053 void glutJoystickGetCenter( int ident, float *axes ) | |
| 1054 { | |
| 1055 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickGetCenter" ); | |
| 1056 memcpy( axes, fgJoystick[ ident ]->center, | |
| 1057 fgJoystick[ ident ]->num_axes * sizeof( float ) ); | |
| 1058 } | |
| 1059 | |
| 1060 /*** END OF FILE ***/ |
