diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-07-31 12:31:11 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-07-31 12:31:11 +0000 |
| commit | 8bca7a2d9797c2b0546895f5e62fc05b38183468 (patch) | |
| tree | 19e6bad8d1c3eabaaa7e34fe425a702ef7eb1e2b /macosx/plugins/DFInput/SDL/src | |
| parent | dd4c0b039bcd38459cd5545d087c2b047198067b (diff) | |
| download | pcsxr-8bca7a2d9797c2b0546895f5e62fc05b38183468.tar.gz | |
dfinput (macosx): upgraded to SDL 1.3 Beta.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@55318 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'macosx/plugins/DFInput/SDL/src')
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/SDL.c | 106 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/SDL_error.c | 351 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/SDL_error_c.h | 48 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic.c | 708 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic_c.h | 26 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/haptic/SDL_syshaptic.h | 201 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/haptic/darwin/SDL_syshaptic.c | 1321 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick.c | 660 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick_c.h | 24 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/joystick/SDL_sysjoystick.h | 58 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick.c | 1290 | ||||
| -rw-r--r-- | macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick_c.h | 88 |
12 files changed, 3642 insertions, 1239 deletions
diff --git a/macosx/plugins/DFInput/SDL/src/SDL.c b/macosx/plugins/DFInput/SDL/src/SDL.c index 4d6a98c0..8f8e676f 100644 --- a/macosx/plugins/DFInput/SDL/src/SDL.c +++ b/macosx/plugins/DFInput/SDL/src/SDL.c @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,79 +19,83 @@ Sam Lantinga slouken@libsdl.org */ - -// 7-25-2010 Wei Mingzhi -// Removed everything unrelated to Mac OS X Joystick support. +// 7/31/2010 Wei Mingzhi +// Removed everything unrated to Mac OS X Joystick support #include "SDL_config.h" /* Initialization code for SDL */ #include "SDL.h" - -/* Initialization/Cleanup routines */ -extern int SDL_JoystickInit(void); -extern void SDL_JoystickQuit(void); - -/* The current SDL version */ -static SDL_version version = - { SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL }; +#include "haptic/SDL_haptic_c.h" +#include "joystick/SDL_joystick_c.h" /* The initialized subsystems */ static Uint32 SDL_initialized = 0; -int SDL_InitSubSystem(Uint32 flags) +int +SDL_InitSubSystem(Uint32 flags) { - /* Initialize the joystick subsystem */ - if ( (flags & SDL_INIT_JOYSTICK) && - !(SDL_initialized & SDL_INIT_JOYSTICK) ) { - if ( SDL_JoystickInit() < 0 ) { - return(-1); - } - SDL_initialized |= SDL_INIT_JOYSTICK; - } - - return(0); + /* Initialize the joystick subsystem */ + if ((flags & SDL_INIT_JOYSTICK) && !(SDL_initialized & SDL_INIT_JOYSTICK)) { + if (SDL_JoystickInit() < 0) { + return (-1); + } + SDL_initialized |= SDL_INIT_JOYSTICK; + } + + /* Initialize the haptic subsystem */ + if ((flags & SDL_INIT_HAPTIC) && !(SDL_initialized & SDL_INIT_HAPTIC)) { + if (SDL_HapticInit() < 0) { + return (-1); + } + SDL_initialized |= SDL_INIT_HAPTIC; + } + + return (0); } -int SDL_Init(Uint32 flags) +int +SDL_Init(Uint32 flags) { - /* Clear the error message */ - SDL_ClearError(); + /* Clear the error message */ + SDL_ClearError(); - /* Initialize the desired subsystems */ - if ( SDL_InitSubSystem(flags) < 0 ) { - return(-1); - } + /* Initialize the desired subsystems */ + if (SDL_InitSubSystem(flags) < 0) { + return (-1); + } - return(0); -} - -void SDL_QuitSubSystem(Uint32 flags) -{ - /* Shut down requested initialized subsystems */ - if ( (flags & SDL_initialized & SDL_INIT_JOYSTICK) ) { - SDL_JoystickQuit(); - SDL_initialized &= ~SDL_INIT_JOYSTICK; - } + return (0); } -Uint32 SDL_WasInit(Uint32 flags) +void +SDL_QuitSubSystem(Uint32 flags) { - if ( ! flags ) { - flags = SDL_INIT_EVERYTHING; - } - return (SDL_initialized&flags); + /* Shut down requested initialized subsystems */ + if ((flags & SDL_initialized & SDL_INIT_JOYSTICK)) { + SDL_JoystickQuit(); + SDL_initialized &= ~SDL_INIT_JOYSTICK; + } + + if ((flags & SDL_initialized & SDL_INIT_HAPTIC)) { + SDL_HapticQuit(); + SDL_initialized &= ~SDL_INIT_HAPTIC; + } } -void SDL_Quit(void) +Uint32 +SDL_WasInit(Uint32 flags) { - /* Quit all subsystems */ - SDL_QuitSubSystem(SDL_INIT_EVERYTHING); + if (!flags) { + flags = SDL_INIT_EVERYTHING; + } + return (SDL_initialized & flags); } -/* Return the library version number */ -const SDL_version * SDL_Linked_Version(void) +void +SDL_Quit(void) { - return(&version); + /* Quit all subsystems */ + SDL_QuitSubSystem(SDL_INIT_EVERYTHING); } diff --git a/macosx/plugins/DFInput/SDL/src/SDL_error.c b/macosx/plugins/DFInput/SDL/src/SDL_error.c index 11632f28..55d183a5 100644 --- a/macosx/plugins/DFInput/SDL/src/SDL_error.c +++ b/macosx/plugins/DFInput/SDL/src/SDL_error.c @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ /* Routine to get the thread-specific error variable */ #if SDL_THREADS_DISABLED +/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */ /* The SDL_arraysize(The ),default (non-thread-safe) global error variable */ static SDL_error SDL_global_error; #define SDL_GetErrBuf() (&SDL_global_error) @@ -39,200 +40,220 @@ extern SDL_error *SDL_GetErrBuf(void); /* Private functions */ -static const char *SDL_LookupString(const char *key) +static const char * +SDL_LookupString(const char *key) { - /* FIXME: Add code to lookup key in language string hash-table */ - return key; + /* FIXME: Add code to lookup key in language string hash-table */ + return key; } /* Public functions */ -void SDL_SetError (const char *fmt, ...) +void +SDL_SetError(const char *fmt, ...) { - va_list ap; - SDL_error *error; - - /* Copy in the key, mark error as valid */ - error = SDL_GetErrBuf(); - error->error = 1; - SDL_strlcpy((char *)error->key, fmt, sizeof(error->key)); - - va_start(ap, fmt); - error->argc = 0; - while ( *fmt ) { - if ( *fmt++ == '%' ) { - while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') ) { - ++fmt; - } - switch (*fmt++) { - case 0: /* Malformed format string.. */ - --fmt; - break; - case 'c': - case 'i': - case 'd': - case 'u': - case 'o': - case 'x': - case 'X': - error->args[error->argc++].value_i = - va_arg(ap, int); - break; - case 'f': - error->args[error->argc++].value_f = - va_arg(ap, double); - break; - case 'p': - error->args[error->argc++].value_ptr = - va_arg(ap, void *); - break; - case 's': - { - int i = error->argc; - const char *str = va_arg(ap, const char *); - if (str == NULL) - str = "(null)"; - SDL_strlcpy((char *)error->args[i].buf, str, ERR_MAX_STRLEN); - error->argc++; - } - break; - default: - break; - } - if ( error->argc >= ERR_MAX_ARGS ) { - break; - } - } - } - va_end(ap); - - /* If we are in debug mode, print out an error message */ + va_list ap; + SDL_error *error; + + /* Copy in the key, mark error as valid */ + error = SDL_GetErrBuf(); + error->error = 1; + SDL_strlcpy((char *) error->key, fmt, sizeof(error->key)); + + va_start(ap, fmt); + error->argc = 0; + while (*fmt) { + if (*fmt++ == '%') { + while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) { + ++fmt; + } + switch (*fmt++) { + case 0: /* Malformed format string.. */ + --fmt; + break; + case 'c': + case 'i': + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': + error->args[error->argc++].value_i = va_arg(ap, int); + break; + case 'f': + error->args[error->argc++].value_f = va_arg(ap, double); + break; + case 'p': + error->args[error->argc++].value_ptr = va_arg(ap, void *); + break; + case 's': + { + int i = error->argc; + const char *str = va_arg(ap, const char *); + if (str == NULL) + str = "(null)"; + SDL_strlcpy((char *) error->args[i].buf, str, + ERR_MAX_STRLEN); + error->argc++; + } + break; + default: + break; + } + if (error->argc >= ERR_MAX_ARGS) { + break; + } + } + } + va_end(ap); + + /* If we are in debug mode, print out an error message */ #ifdef DEBUG_ERROR - fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); + fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); #endif } /* This function has a bit more overhead than most error functions so that it supports internationalization and thread-safe errors. */ -char *SDL_GetErrorMsg(char *errstr, unsigned int maxlen) +static char * +SDL_GetErrorMsg(char *errstr, unsigned int maxlen) { - SDL_error *error; - - /* Clear the error string */ - *errstr = '\0'; --maxlen; - - /* Get the thread-safe error, and print it out */ - error = SDL_GetErrBuf(); - if ( error->error ) { - const char *fmt; - char *msg = errstr; - int len; - int argi; - - fmt = SDL_LookupString(error->key); - argi = 0; - while ( *fmt && (maxlen > 0) ) { - if ( *fmt == '%' ) { - char tmp[32], *spot = tmp; - *spot++ = *fmt++; - while ( (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) && spot < (tmp+SDL_arraysize(tmp)-2) ) { - *spot++ = *fmt++; - } - *spot++ = *fmt++; - *spot++ = '\0'; - switch (spot[-2]) { - case '%': - *msg++ = '%'; - maxlen -= 1; - break; - case 'c': - case 'i': - case 'd': - case 'u': - case 'o': - case 'x': - case 'X': - len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_i); - msg += len; - maxlen -= len; - break; - case 'f': - len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_f); - msg += len; - maxlen -= len; - break; - case 'p': - len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_ptr); - msg += len; - maxlen -= len; - break; - case 's': - len = SDL_snprintf(msg, maxlen, tmp, SDL_LookupString(error->args[argi++].buf)); - msg += len; - maxlen -= len; - break; - } - } else { - *msg++ = *fmt++; - maxlen -= 1; - } - } - *msg = 0; /* NULL terminate the string */ - } - return(errstr); + SDL_error *error; + + /* Clear the error string */ + *errstr = '\0'; + --maxlen; + + /* Get the thread-safe error, and print it out */ + error = SDL_GetErrBuf(); + if (error->error) { + const char *fmt; + char *msg = errstr; + int len; + int argi; + + fmt = SDL_LookupString(error->key); + argi = 0; + while (*fmt && (maxlen > 0)) { + if (*fmt == '%') { + char tmp[32], *spot = tmp; + *spot++ = *fmt++; + while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) + && spot < (tmp + SDL_arraysize(tmp) - 2)) { + *spot++ = *fmt++; + } + *spot++ = *fmt++; + *spot++ = '\0'; + switch (spot[-2]) { + case '%': + *msg++ = '%'; + maxlen -= 1; + break; + case 'c': + case 'i': + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': + len = + SDL_snprintf(msg, maxlen, tmp, + error->args[argi++].value_i); + msg += len; + maxlen -= len; + break; + case 'f': + len = + SDL_snprintf(msg, maxlen, tmp, + error->args[argi++].value_f); + msg += len; + maxlen -= len; + break; + case 'p': + len = + SDL_snprintf(msg, maxlen, tmp, + error->args[argi++].value_ptr); + msg += len; + maxlen -= len; + break; + case 's': + len = + SDL_snprintf(msg, maxlen, tmp, + SDL_LookupString(error->args[argi++]. + buf)); + msg += len; + maxlen -= len; + break; + } + } else { + *msg++ = *fmt++; + maxlen -= 1; + } + } + *msg = 0; /* NULL terminate the string */ + } + return (errstr); } /* Available for backwards compatibility */ -char *SDL_GetError (void) +char * +SDL_GetError(void) { - static char errmsg[SDL_ERRBUFIZE]; + static char errmsg[SDL_ERRBUFIZE]; - return((char *)SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE)); + return ((char *) SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE)); } -void SDL_ClearError(void) +void +SDL_ClearError(void) { - SDL_error *error; + SDL_error *error; - error = SDL_GetErrBuf(); - error->error = 0; + error = SDL_GetErrBuf(); + error->error = 0; } /* Very common errors go here */ -void SDL_Error(SDL_errorcode code) +void +SDL_Error(SDL_errorcode code) { - switch (code) { - case SDL_ENOMEM: - SDL_SetError("Out of memory"); - break; - case SDL_EFREAD: - SDL_SetError("Error reading from datastream"); - break; - case SDL_EFWRITE: - SDL_SetError("Error writing to datastream"); - break; - case SDL_EFSEEK: - SDL_SetError("Error seeking in datastream"); - break; - default: - SDL_SetError("Unknown SDL error"); - break; - } + switch (code) { + case SDL_ENOMEM: + SDL_SetError("Out of memory"); + break; + case SDL_EFREAD: + SDL_SetError("Error reading from datastream"); + break; + case SDL_EFWRITE: + SDL_SetError("Error writing to datastream"); + break; + case SDL_EFSEEK: + SDL_SetError("Error seeking in datastream"); + break; + case SDL_UNSUPPORTED: + SDL_SetError("That operation is not supported"); + break; + default: + SDL_SetError("Unknown SDL error"); + break; + } } #ifdef TEST_ERROR -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - char buffer[BUFSIZ+1]; - - SDL_SetError("Hi there!"); - printf("Error 1: %s\n", SDL_GetError()); - SDL_ClearError(); - SDL_memset(buffer, '1', BUFSIZ); - buffer[BUFSIZ] = 0; - SDL_SetError("This is the error: %s (%f)", buffer, 1.0); - printf("Error 2: %s\n", SDL_GetError()); - exit(0); + char buffer[BUFSIZ + 1]; + + SDL_SetError("Hi there!"); + printf("Error 1: %s\n", SDL_GetError()); + SDL_ClearError(); + SDL_memset(buffer, '1', BUFSIZ); + buffer[BUFSIZ] = 0; + SDL_SetError("This is the error: %s (%f)", buffer, 1.0); + printf("Error 2: %s\n", SDL_GetError()); + exit(0); } #endif +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/SDL_error_c.h b/macosx/plugins/DFInput/SDL/src/SDL_error_c.h index 990acb56..54501f5f 100644 --- a/macosx/plugins/DFInput/SDL/src/SDL_error_c.h +++ b/macosx/plugins/DFInput/SDL/src/SDL_error_c.h @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -31,28 +31,32 @@ #define ERR_MAX_STRLEN 128 #define ERR_MAX_ARGS 5 -typedef struct SDL_error { - /* This is a numeric value corresponding to the current error */ - int error; - - /* This is a key used to index into a language hashtable containing - internationalized versions of the SDL error messages. If the key - is not in the hashtable, or no hashtable is available, the key is - used directly as an error message format string. - */ - char key[ERR_MAX_STRLEN]; - - /* These are the arguments for the error functions */ - int argc; - union { - void *value_ptr; -#if 0 /* What is a character anyway? (UNICODE issues) */ - unsigned char value_c; +typedef struct SDL_error +{ + /* This is a numeric value corresponding to the current error */ + int error; + + /* This is a key used to index into a language hashtable containing + internationalized versions of the SDL error messages. If the key + is not in the hashtable, or no hashtable is available, the key is + used directly as an error message format string. + */ + char key[ERR_MAX_STRLEN]; + + /* These are the arguments for the error functions */ + int argc; + union + { + void *value_ptr; +#if 0 /* What is a character anyway? (UNICODE issues) */ + unsigned char value_c; #endif - int value_i; - double value_f; - char buf[ERR_MAX_STRLEN]; - } args[ERR_MAX_ARGS]; + int value_i; + double value_f; + char buf[ERR_MAX_STRLEN]; + } args[ERR_MAX_ARGS]; } SDL_error; #endif /* _SDL_error_c_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic.c b/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic.c new file mode 100644 index 00000000..af8c39a7 --- /dev/null +++ b/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic.c @@ -0,0 +1,708 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2008 Edgar Simo + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_syshaptic.h" +#include "SDL_haptic_c.h" +#include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */ + + +Uint8 SDL_numhaptics = 0; +SDL_Haptic **SDL_haptics = NULL; + + +/* + * Initializes the Haptic devices. + */ +int +SDL_HapticInit(void) +{ + int arraylen; + int status; + + SDL_numhaptics = 0; + status = SDL_SYS_HapticInit(); + if (status >= 0) { + arraylen = (status + 1) * sizeof(*SDL_haptics); + SDL_haptics = (SDL_Haptic **) SDL_malloc(arraylen); + if (SDL_haptics == NULL) { /* Out of memory. */ + SDL_numhaptics = 0; + } else { + SDL_memset(SDL_haptics, 0, arraylen); + SDL_numhaptics = status; + } + status = 0; + } + + return status; +} + + +/* + * Checks to see if the haptic device is valid + */ +static int +ValidHaptic(SDL_Haptic * haptic) +{ + int i; + int valid; + + valid = 0; + if (haptic != NULL) { + for (i = 0; i < SDL_numhaptics; i++) { + if (SDL_haptics[i] == haptic) { + valid = 1; + break; + } + } + } + + /* Create the error here. */ + if (valid == 0) { + SDL_SetError("Haptic: Invalid haptic device identifier"); + } + + return valid; +} + + +/* + * Returns the number of available devices. + */ +int +SDL_NumHaptics(void) +{ + return SDL_numhaptics; +} + + +/* + * Gets the name of a Haptic device by index. + */ +const char * +SDL_HapticName(int device_index) +{ + if ((device_index < 0) || (device_index >= SDL_numhaptics)) { + SDL_SetError("Haptic: There are %d haptic devices available", + SDL_numhaptics); + return NULL; + } + return SDL_SYS_HapticName(device_index); +} + + +/* + * Opens a Haptic device. + */ +SDL_Haptic * +SDL_HapticOpen(int device_index) +{ + int i; + SDL_Haptic *haptic; + + if ((device_index < 0) || (device_index >= SDL_numhaptics)) { + SDL_SetError("Haptic: There are %d haptic devices available", + SDL_numhaptics); + return NULL; + } + + /* If the haptic is already open, return it */ + for (i = 0; SDL_haptics[i]; i++) { + if (device_index == SDL_haptics[i]->index) { + haptic = SDL_haptics[i]; + ++haptic->ref_count; + return haptic; + } + } + + /* Create the haptic device */ + haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic)); + if (haptic == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + /* Initialize the haptic device */ + SDL_memset(haptic, 0, (sizeof *haptic)); + haptic->index = device_index; + if (SDL_SYS_HapticOpen(haptic) < 0) { + SDL_free(haptic); + return NULL; + } + + /* Disable autocenter and set gain to max. */ + if (haptic->supported & SDL_HAPTIC_GAIN) + SDL_HapticSetGain(haptic, 100); + if (haptic->supported & SDL_HAPTIC_AUTOCENTER) + SDL_HapticSetAutocenter(haptic, 0); + + /* Add haptic to list */ + ++haptic->ref_count; + for (i = 0; SDL_haptics[i]; i++) + /* Skip to next haptic */ ; + SDL_haptics[i] = haptic; + + return haptic; +} + + +/* + * Returns 1 if the device has been opened. + */ +int +SDL_HapticOpened(int device_index) +{ + int i, opened; + + opened = 0; + for (i = 0; SDL_haptics[i]; i++) { + if (SDL_haptics[i]->index == (Uint8) device_index) { + opened = 1; + break; + } + } + return opened; +} + + +/* + * Returns the index to a haptic device. + */ +int +SDL_HapticIndex(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return haptic->index; +} + + +/* + * Returns SDL_TRUE if mouse is haptic, SDL_FALSE if it isn't. + */ +int +SDL_MouseIsHaptic(void) +{ + if (SDL_SYS_HapticMouse() < 0) + return SDL_FALSE; + return SDL_TRUE; +} + + +/* + * Returns the haptic device if mouse is haptic or NULL elsewise. + */ +SDL_Haptic * +SDL_HapticOpenFromMouse(void) +{ + int device_index; + + device_index = SDL_SYS_HapticMouse(); + + if (device_index < 0) { + SDL_SetError("Haptic: Mouse isn't a haptic device."); + return NULL; + } + + return SDL_HapticOpen(device_index); +} + + +/* + * Returns SDL_TRUE if joystick has haptic features. + */ +int +SDL_JoystickIsHaptic(SDL_Joystick * joystick) +{ + int ret; + + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(&joystick)) { + return -1; + } + + ret = SDL_SYS_JoystickIsHaptic(joystick); + + if (ret > 0) + return SDL_TRUE; + else if (ret == 0) + return SDL_FALSE; + else + return -1; +} + + +/* + * Opens a haptic device from a joystick. + */ +SDL_Haptic * +SDL_HapticOpenFromJoystick(SDL_Joystick * joystick) +{ + int i; + SDL_Haptic *haptic; + + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(&joystick)) { + SDL_SetError("Haptic: Joystick isn't valid."); + return NULL; + } + + /* Joystick must be haptic */ + if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { + SDL_SetError("Haptic: Joystick isn't a haptic device."); + return NULL; + } + + /* Check to see if joystick's haptic is already open */ + for (i = 0; SDL_haptics[i]; i++) { + if (SDL_SYS_JoystickSameHaptic(SDL_haptics[i], joystick)) { + haptic = SDL_haptics[i]; + ++haptic->ref_count; + return haptic; + } + } + + /* Create the haptic device */ + haptic = (SDL_Haptic *) SDL_malloc((sizeof *haptic)); + if (haptic == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + /* Initialize the haptic device */ + SDL_memset(haptic, 0, sizeof(SDL_Haptic)); + if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { + SDL_free(haptic); + return NULL; + } + + /* Add haptic to list */ + ++haptic->ref_count; + for (i = 0; SDL_haptics[i]; i++) + /* Skip to next haptic */ ; + SDL_haptics[i] = haptic; + + return haptic; +} + + +/* + * Closes a SDL_Haptic device. + */ +void +SDL_HapticClose(SDL_Haptic * haptic) +{ + int i; + + /* Must be valid */ + if (!ValidHaptic(haptic)) { + return; + } + + /* Check if it's still in use */ + if (--haptic->ref_count < 0) { + return; + } + + /* Close it, properly removing effects if needed */ + for (i = 0; i < haptic->neffects; i++) { + if (haptic->effects[i].hweffect != NULL) { + SDL_HapticDestroyEffect(haptic, i); + } + } + SDL_SYS_HapticClose(haptic); + + /* Remove from the list */ + for (i = 0; SDL_haptics[i]; ++i) { + if (haptic == SDL_haptics[i]) { + SDL_haptics[i] = NULL; + SDL_memcpy(&SDL_haptics[i], &SDL_haptics[i + 1], + (SDL_numhaptics - i) * sizeof(haptic)); + break; + } + } + + /* Free */ + SDL_free(haptic); +} + +/* + * Cleans up after the subsystem. + */ +void +SDL_HapticQuit(void) +{ + SDL_SYS_HapticQuit(); + if (SDL_haptics != NULL) { + SDL_free(SDL_haptics); + SDL_haptics = NULL; + } + SDL_numhaptics = 0; +} + +/* + * Returns the number of effects a haptic device has. + */ +int +SDL_HapticNumEffects(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return haptic->neffects; +} + + +/* + * Returns the number of effects a haptic device can play. + */ +int +SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return haptic->nplaying; +} + + +/* + * Returns supported effects by the device. + */ +unsigned int +SDL_HapticQuery(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return haptic->supported; +} + + +/* + * Returns the number of axis on the device. + */ +int +SDL_HapticNumAxes(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return haptic->naxes; +} + +/* + * Checks to see if the device can support the effect. + */ +int +SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + if ((haptic->supported & effect->type) != 0) + return SDL_TRUE; + return SDL_FALSE; +} + +/* + * Creates a new haptic effect. + */ +int +SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect) +{ + int i; + + /* Check for device validity. */ + if (!ValidHaptic(haptic)) { + return -1; + } + + /* Check to see if effect is supported */ + if (SDL_HapticEffectSupported(haptic, effect) == SDL_FALSE) { + SDL_SetError("Haptic: Effect not supported by haptic device."); + return -1; + } + + /* See if there's a free slot */ + for (i = 0; i < haptic->neffects; i++) { + if (haptic->effects[i].hweffect == NULL) { + + /* Now let the backend create the real effect */ + if (SDL_SYS_HapticNewEffect(haptic, &haptic->effects[i], effect) + != 0) { + return -1; /* Backend failed to create effect */ + } + + SDL_memcpy(&haptic->effects[i].effect, effect, + sizeof(SDL_HapticEffect)); + return i; + } + } + + SDL_SetError("Haptic: Device has no free space left."); + return -1; +} + +/* + * Checks to see if an effect is valid. + */ +static int +ValidEffect(SDL_Haptic * haptic, int effect) +{ + if ((effect < 0) || (effect >= haptic->neffects)) { + SDL_SetError("Haptic: Invalid effect identifier."); + return 0; + } + return 1; +} + +/* + * Updates an effect. + */ +int +SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, + SDL_HapticEffect * data) +{ + if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + return -1; + } + + /* Can't change type dynamically. */ + if (data->type != haptic->effects[effect].effect.type) { + SDL_SetError("Haptic: Updating effect type is illegal."); + return -1; + } + + /* Updates the effect */ + if (SDL_SYS_HapticUpdateEffect(haptic, &haptic->effects[effect], data) < + 0) { + return -1; + } + + SDL_memcpy(&haptic->effects[effect].effect, data, + sizeof(SDL_HapticEffect)); + return 0; +} + + +/* + * Runs the haptic effect on the device. + */ +int +SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 iterations) +{ + if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + return -1; + } + + /* Run the effect */ + if (SDL_SYS_HapticRunEffect(haptic, &haptic->effects[effect], iterations) + < 0) { + return -1; + } + + return 0; +} + +/* + * Stops the haptic effect on the device. + */ +int +SDL_HapticStopEffect(SDL_Haptic * haptic, int effect) +{ + if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + return -1; + } + + /* Stop the effect */ + if (SDL_SYS_HapticStopEffect(haptic, &haptic->effects[effect]) < 0) { + return -1; + } + + return 0; +} + +/* + * Gets rid of a haptic effect. + */ +void +SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect) +{ + if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + return; + } + + /* Not allocated */ + if (haptic->effects[effect].hweffect == NULL) { + return; + } + + SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]); +} + +/* + * Gets the status of a haptic effect. + */ +int +SDL_HapticGetEffectStatus(SDL_Haptic * haptic, int effect) +{ + if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + return -1; + } + + if ((haptic->supported & SDL_HAPTIC_STATUS) == 0) { + SDL_SetError("Haptic: Device does not support status queries."); + return -1; + } + + return SDL_SYS_HapticGetEffectStatus(haptic, &haptic->effects[effect]); +} + +/* + * Sets the global gain of the device. + */ +int +SDL_HapticSetGain(SDL_Haptic * haptic, int gain) +{ + const char *env; + int real_gain, max_gain; + + if (!ValidHaptic(haptic)) { + return -1; + } + + if ((haptic->supported & SDL_HAPTIC_GAIN) == 0) { + SDL_SetError("Haptic: Device does not support setting gain."); + return -1; + } + + if ((gain < 0) || (gain > 100)) { + SDL_SetError("Haptic: Gain must be between 0 and 100."); + return -1; + } + + /* We use the envvar to get the maximum gain. */ + env = SDL_getenv("SDL_HAPTIC_GAIN_MAX"); + if (env != NULL) { + max_gain = SDL_atoi(env); + + /* Check for sanity. */ + if (max_gain < 0) + max_gain = 0; + else if (max_gain > 100) + max_gain = 100; + + /* We'll scale it linearly with SDL_HAPTIC_GAIN_MAX */ + real_gain = (gain * max_gain) / 100; + } else { + real_gain = gain; + } + + if (SDL_SYS_HapticSetGain(haptic, real_gain) < 0) { + return -1; + } + + return 0; +} + +/* + * Makes the device autocenter, 0 disables. + */ +int +SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + if ((haptic->supported & SDL_HAPTIC_AUTOCENTER) == 0) { + SDL_SetError("Haptic: Device does not support setting autocenter."); + return -1; + } + + if ((autocenter < 0) || (autocenter > 100)) { + SDL_SetError("Haptic: Autocenter must be between 0 and 100."); + return -1; + } + + if (SDL_SYS_HapticSetAutocenter(haptic, autocenter) < 0) { + return -1; + } + + return 0; +} + +/* + * Pauses the haptic device. + */ +int +SDL_HapticPause(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + if ((haptic->supported & SDL_HAPTIC_PAUSE) == 0) { + SDL_SetError("Haptic: Device does not support setting pausing."); + return -1; + } + + return SDL_SYS_HapticPause(haptic); +} + +/* + * Unpauses the haptic device. + */ +int +SDL_HapticUnpause(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + if ((haptic->supported & SDL_HAPTIC_PAUSE) == 0) { + return 0; /* Not going to be paused, so we pretend it's unpaused. */ + } + + return SDL_SYS_HapticUnpause(haptic); +} + +/* + * Stops all the currently playing effects. + */ +int +SDL_HapticStopAll(SDL_Haptic * haptic) +{ + if (!ValidHaptic(haptic)) { + return -1; + } + + return SDL_SYS_HapticStopAll(haptic); +} diff --git a/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic_c.h b/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic_c.h new file mode 100644 index 00000000..4144a0fb --- /dev/null +++ b/macosx/plugins/DFInput/SDL/src/haptic/SDL_haptic_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +extern int SDL_HapticInit(void); +extern void SDL_HapticQuit(void); + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/haptic/SDL_syshaptic.h b/macosx/plugins/DFInput/SDL/src/haptic/SDL_syshaptic.h new file mode 100644 index 00000000..9542a0d7 --- /dev/null +++ b/macosx/plugins/DFInput/SDL/src/haptic/SDL_syshaptic.h @@ -0,0 +1,201 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2008 Edgar Simo + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include "SDL_config.h" + +#include "SDL_haptic.h" + + +/* + * Number of haptic devices on the system. + */ +extern Uint8 SDL_numhaptics; + + +struct haptic_effect +{ + SDL_HapticEffect effect; /* The current event */ + struct haptic_hweffect *hweffect; /* The hardware behind the event */ +}; + +/* + * The real SDL_Haptic struct. + */ +struct _SDL_Haptic +{ + Uint8 index; /* Stores index it is attached to */ + + struct haptic_effect *effects; /* Allocated effects */ + int neffects; /* Maximum amount of effects */ + int nplaying; /* Maximum amount of effects to play at the same time */ + unsigned int supported; /* Supported effects */ + int naxes; /* Number of axes on the device. */ + + struct haptic_hwdata *hwdata; /* Driver dependent */ + int ref_count; /* Count for multiple opens */ +}; + +/* + * Scans the system for haptic devices. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticInit(void); + +/* + * Gets the device dependent name of the haptic device + */ +extern const char *SDL_SYS_HapticName(int index); + +/* + * Opens the haptic device for usage. The haptic device should have + * the index value set previously. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticOpen(SDL_Haptic * haptic); + +/* + * Returns the index of the haptic core pointer or -1 if none is found. + */ +int SDL_SYS_HapticMouse(void); + +/* + * Checks to see if the joystick has haptic capabilities. + * + * Returns >0 if haptic capabilities are detected, 0 if haptic + * capabilities aren't detected and -1 on error. + */ +extern int SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick); + +/* + * Opens the haptic device for usage using the same device as + * the joystick. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, + SDL_Joystick * joystick); +/* + * Checks to see if haptic device and joystick device are the same. + * + * Returns 1 if they are the same, 0 if they aren't. + */ +extern int SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, + SDL_Joystick * joystick); + +/* + * Closes a haptic device after usage. + */ +extern void SDL_SYS_HapticClose(SDL_Haptic * haptic); + +/* + * Performs a cleanup on the haptic subsystem. + */ +extern void SDL_SYS_HapticQuit(void); + +/* + * Creates a new haptic effect on the haptic device using base + * as a template for the effect. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, + struct haptic_effect *effect, + SDL_HapticEffect * base); + +/* + * Updates the haptic effect on the haptic device using data + * as a template. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic, + struct haptic_effect *effect, + SDL_HapticEffect * data); + +/* + * Runs the effect on the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, + struct haptic_effect *effect, + Uint32 iterations); + +/* + * Stops the effect on the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, + struct haptic_effect *effect); + +/* + * Cleanups up the effect on the haptic device. + */ +extern void SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, + struct haptic_effect *effect); + +/* + * Queries the device for the status of effect. + * + * Returns 0 if device is stopped, >0 if device is playing and + * -1 on error. + */ +extern int SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic, + struct haptic_effect *effect); + +/* + * Sets the global gain of the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain); + +/* + * Sets the autocenter feature of the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter); + +/* + * Pauses the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticPause(SDL_Haptic * haptic); + +/* + * Unpauses the haptic device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticUnpause(SDL_Haptic * haptic); + +/* + * Stops all the currently playing haptic effects on the device. + * + * Returns 0 on success, -1 on error. + */ +extern int SDL_SYS_HapticStopAll(SDL_Haptic * haptic); diff --git a/macosx/plugins/DFInput/SDL/src/haptic/darwin/SDL_syshaptic.c b/macosx/plugins/DFInput/SDL/src/haptic/darwin/SDL_syshaptic.c new file mode 100644 index 00000000..c5b1e54b --- /dev/null +++ b/macosx/plugins/DFInput/SDL/src/haptic/darwin/SDL_syshaptic.c @@ -0,0 +1,1321 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2008 Edgar Simo + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_HAPTIC_IOKIT + +#include "SDL_haptic.h" +#include "../SDL_syshaptic.h" +#include "SDL_joystick.h" +#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */ +#include "../../joystick/darwin/SDL_sysjoystick_c.h" /* For joystick hwdata */ + +#include <IOKit/IOKitLib.h> +#include <IOKit/hid/IOHIDKeys.h> +#include <IOKit/hid/IOHIDUsageTables.h> +#include <ForceFeedback/ForceFeedback.h> +#include <ForceFeedback/ForceFeedbackConstants.h> + +#ifndef IO_OBJECT_NULL +#define IO_OBJECT_NULL ((io_service_t)0) +#endif + +#define MAX_HAPTICS 32 + + +/* + * List of available haptic devices. + */ +static struct +{ + char name[256]; /* Name of the device. */ + + io_service_t dev; /* Node we use to create the device. */ + SDL_Haptic *haptic; /* Haptic currently assosciated with it. */ + + /* Usage pages for determining if it's a mouse or not. */ + long usage; + long usagePage; +} SDL_hapticlist[MAX_HAPTICS]; + + +/* + * Haptic system hardware data. + */ +struct haptic_hwdata +{ + FFDeviceObjectReference device; /* Hardware device. */ + UInt8 axes[3]; +}; + + +/* + * Haptic system effect data. + */ +struct haptic_hweffect +{ + FFEffectObjectReference ref; /* Reference. */ + struct FFEFFECT effect; /* Hardware effect. */ +}; + +/* + * Prototypes. + */ +static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect, int type); +static int HIDGetDeviceProduct(io_service_t dev, char *name); + + +/* + * Like strerror but for force feedback errors. + */ +static const char * +FFStrError(HRESULT err) +{ + switch (err) { + case FFERR_DEVICEFULL: + return "device full"; + /* This should be valid, but for some reason isn't defined... */ + /*case FFERR_DEVICENOTREG: + return "device not registered"; */ + case FFERR_DEVICEPAUSED: + return "device paused"; + case FFERR_DEVICERELEASED: + return "device released"; + case FFERR_EFFECTPLAYING: + return "effect playing"; + case FFERR_EFFECTTYPEMISMATCH: + return "effect type mismatch"; + case FFERR_EFFECTTYPENOTSUPPORTED: + return "effect type not supported"; + case FFERR_GENERIC: + return "undetermined error"; + case FFERR_HASEFFECTS: + return "device has effects"; + case FFERR_INCOMPLETEEFFECT: + return "incomplete effect"; + case FFERR_INTERNAL: + return "internal fault"; + case FFERR_INVALIDDOWNLOADID: + return "invalid download id"; + case FFERR_INVALIDPARAM: + return "invalid parameter"; + case FFERR_MOREDATA: + return "more data"; + case FFERR_NOINTERFACE: + return "interface not supported"; + case FFERR_NOTDOWNLOADED: + return "effect is not downloaded"; + case FFERR_NOTINITIALIZED: + return "object has not been initialized"; + case FFERR_OUTOFMEMORY: + return "out of memory"; + case FFERR_UNPLUGGED: + return "device is unplugged"; + case FFERR_UNSUPPORTED: + return "function call unsupported"; + case FFERR_UNSUPPORTEDAXIS: + return "axis unsupported"; + + default: + return "unknown error"; + } +} + + +/* + * Initializes the haptic subsystem. + */ +int +SDL_SYS_HapticInit(void) +{ + int numhaptics; + IOReturn result; + io_iterator_t iter; + CFDictionaryRef match; + io_service_t device; + CFMutableDictionaryRef hidProperties; + CFTypeRef refCF; + + /* Clear all the memory. */ + SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist)); + + /* Get HID devices. */ + match = IOServiceMatching(kIOHIDDeviceKey); + if (match == NULL) { + SDL_SetError("Haptic: Failed to get IOServiceMatching."); + return -1; + } + + /* Now search I/O Registry for matching devices. */ + result = IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iter); + if (result != kIOReturnSuccess) { + SDL_SetError("Haptic: Couldn't create a HID object iterator."); + return -1; + } + /* IOServiceGetMatchingServices consumes dictionary. */ + + if (!IOIteratorIsValid(iter)) { /* No iterator. */ + numhaptics = 0; + return 0; + } + + numhaptics = 0; + while ((device = IOIteratorNext(iter)) != IO_OBJECT_NULL) { + + /* Check for force feedback. */ + if (FFIsForceFeedback(device) == FF_OK) { + + /* Set basic device data. */ + HIDGetDeviceProduct(device, SDL_hapticlist[numhaptics].name); + SDL_hapticlist[numhaptics].dev = device; + SDL_hapticlist[numhaptics].haptic = NULL; + + /* Set usage pages. */ + hidProperties = 0; + refCF = 0; + result = IORegistryEntryCreateCFProperties(device, + &hidProperties, + kCFAllocatorDefault, + kNilOptions); + if ((result == KERN_SUCCESS) && hidProperties) { + refCF = + CFDictionaryGetValue(hidProperties, + CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) { + if (!CFNumberGetValue(refCF, kCFNumberLongType, + &SDL_hapticlist[numhaptics]. + usagePage)) + SDL_SetError + ("Haptic: Recieving device's usage page."); + refCF = + CFDictionaryGetValue(hidProperties, + CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) { + if (!CFNumberGetValue(refCF, kCFNumberLongType, + &SDL_hapticlist[numhaptics]. + usage)) + SDL_SetError("Haptic: Recieving device's usage."); + } + } + CFRelease(hidProperties); + } + + /* Device has been added. */ + numhaptics++; + } else { /* Free the unused device. */ + IOObjectRelease(device); + } + + /* Reached haptic limit. */ + if (numhaptics >= MAX_HAPTICS) + break; + } + IOObjectRelease(iter); + + return numhaptics; +} + + +/* + * Return the name of a haptic device, does not need to be opened. + */ +const char * +SDL_SYS_HapticName(int index) +{ + return SDL_hapticlist[index].name; +} + +/* + * Gets the device's product name. + */ +static int +HIDGetDeviceProduct(io_service_t dev, char *name) +{ + CFMutableDictionaryRef hidProperties, usbProperties; + io_registry_entry_t parent1, parent2; + kern_return_t ret; + + hidProperties = usbProperties = 0; + + ret = IORegistryEntryCreateCFProperties(dev, &hidProperties, + kCFAllocatorDefault, kNilOptions); + if ((ret != KERN_SUCCESS) || !hidProperties) { + SDL_SetError("Haptic: Unable to create CFProperties."); + return -1; + } + + /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + */ + if ((KERN_SUCCESS == + IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1)) + && (KERN_SUCCESS == + IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2)) + && (KERN_SUCCESS == + IORegistryEntryCreateCFProperties(parent2, &usbProperties, + kCFAllocatorDefault, + kNilOptions))) { + if (usbProperties) { + CFTypeRef refCF = 0; + /* get device info + * try hid dictionary first, if fail then go to usb dictionary + */ + + + /* Get product name */ + refCF = + CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey)); + if (!refCF) + refCF = + CFDictionaryGetValue(usbProperties, + CFSTR("USB Product Name")); + if (refCF) { + if (!CFStringGetCString(refCF, name, 256, + CFStringGetSystemEncoding())) { + SDL_SetError + ("Haptic: CFStringGetCString error retrieving pDevice->product."); + return -1; + } + } + + CFRelease(usbProperties); + } else { + SDL_SetError + ("Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties."); + return -1; + } + + /* Release stuff. */ + if (kIOReturnSuccess != IOObjectRelease(parent2)) { + SDL_SetError("Haptic: IOObjectRelease error with parent2."); + } + if (kIOReturnSuccess != IOObjectRelease(parent1)) { + SDL_SetError("Haptic: IOObjectRelease error with parent1."); + } + } else { + SDL_SetError("Haptic: Error getting registry entries."); + return -1; + } + + return 0; +} + + +#define FF_TEST(ff, s) \ +if (features.supportedEffects & (ff)) supported |= (s) +/* + * Gets supported features. + */ +static unsigned int +GetSupportedFeatures(SDL_Haptic * haptic) +{ + HRESULT ret; + FFDeviceObjectReference device; + FFCAPABILITIES features; + unsigned int supported; + Uint32 val; + + device = haptic->hwdata->device; + + ret = FFDeviceGetForceFeedbackCapabilities(device, &features); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to get device's supported features."); + return -1; + } + + supported = 0; + + /* Get maximum effects. */ + haptic->neffects = features.storageCapacity; + haptic->nplaying = features.playbackCapacity; + + /* Test for effects. */ + FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT); + FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP); + FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE); + FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE); + FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE); + FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP); + FF_TEST(FFCAP_ET_SAWTOOTHDOWN, SDL_HAPTIC_SAWTOOTHDOWN); + FF_TEST(FFCAP_ET_SPRING, SDL_HAPTIC_SPRING); + FF_TEST(FFCAP_ET_DAMPER, SDL_HAPTIC_DAMPER); + FF_TEST(FFCAP_ET_INERTIA, SDL_HAPTIC_INERTIA); + FF_TEST(FFCAP_ET_FRICTION, SDL_HAPTIC_FRICTION); + FF_TEST(FFCAP_ET_CUSTOMFORCE, SDL_HAPTIC_CUSTOM); + + /* Check if supports gain. */ + ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_FFGAIN, + &val, sizeof(val)); + if (ret == FF_OK) + supported |= SDL_HAPTIC_GAIN; + else if (ret != FFERR_UNSUPPORTED) { + SDL_SetError("Haptic: Unable to get if device supports gain: %s.", + FFStrError(ret)); + return -1; + } + + /* Checks if supports autocenter. */ + ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_AUTOCENTER, + &val, sizeof(val)); + if (ret == FF_OK) + supported |= SDL_HAPTIC_AUTOCENTER; + else if (ret != FFERR_UNSUPPORTED) { + SDL_SetError + ("Haptic: Unable to get if device supports autocenter: %s.", + FFStrError(ret)); + return -1; + } + + /* Check for axes, we have an artificial limit on axes */ + haptic->naxes = ((features.numFfAxes) > 3) ? 3 : features.numFfAxes; + /* Actually store the axes we want to use */ + SDL_memcpy(haptic->hwdata->axes, features.ffAxes, + haptic->naxes * sizeof(Uint8)); + + /* Always supported features. */ + supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE; + + haptic->supported = supported; + return 0;; +} + + +/* + * Opens the haptic device from the file descriptor. + */ +static int +SDL_SYS_HapticOpenFromService(SDL_Haptic * haptic, io_service_t service) +{ + HRESULT ret; + int ret2; + + /* Allocate the hwdata */ + haptic->hwdata = (struct haptic_hwdata *) + SDL_malloc(sizeof(*haptic->hwdata)); + if (haptic->hwdata == NULL) { + SDL_OutOfMemory(); + goto creat_err; + } + SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); + + /* Open the device */ + ret = FFCreateDevice(service, &haptic->hwdata->device); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to create device from service: %s.", + FFStrError(ret)); + goto creat_err; + } + + /* Get supported features. */ + ret2 = GetSupportedFeatures(haptic); + if (haptic->supported < 0) { + goto open_err; + } + + + /* Reset and then enable actuators. */ + ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device, + FFSFFC_RESET); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to reset device: %s.", FFStrError(ret)); + goto open_err; + } + ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device, + FFSFFC_SETACTUATORSON); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to enable actuators: %s.", + FFStrError(ret)); + goto open_err; + } + + + /* Allocate effects memory. */ + haptic->effects = (struct haptic_effect *) + SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); + if (haptic->effects == NULL) { + SDL_OutOfMemory(); + goto open_err; + } + /* Clear the memory */ + SDL_memset(haptic->effects, 0, + sizeof(struct haptic_effect) * haptic->neffects); + + return 0; + + /* Error handling */ + open_err: + FFReleaseDevice(haptic->hwdata->device); + creat_err: + if (haptic->hwdata != NULL) { + free(haptic->hwdata); + haptic->hwdata = NULL; + } + return -1; + +} + + +/* + * Opens a haptic device for usage. + */ +int +SDL_SYS_HapticOpen(SDL_Haptic * haptic) +{ + return SDL_SYS_HapticOpenFromService(haptic, + SDL_hapticlist[haptic->index].dev); +} + + +/* + * Opens a haptic device from first mouse it finds for usage. + */ +int +SDL_SYS_HapticMouse(void) +{ + int i; + + for (i = 0; i < SDL_numhaptics; i++) { + if ((SDL_hapticlist[i].usagePage == kHIDPage_GenericDesktop) && + (SDL_hapticlist[i].usage == kHIDUsage_GD_Mouse)) + return i; + } + + return -1; +} + + +/* + * Checks to see if a joystick has haptic features. + */ +int +SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick) +{ + if (joystick->hwdata->ffservice != 0) + return SDL_TRUE; + return SDL_FALSE; +} + + +/* + * Checks to see if the haptic device and joystick and in reality the same. + */ +int +SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick) +{ + if (IOObjectIsEqualTo((io_object_t) haptic->hwdata->device, + joystick->hwdata->ffservice)) + return 1; + return 0; +} + + +/* + * Opens a SDL_Haptic from a SDL_Joystick. + */ +int +SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick) +{ + return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice); +} + + +/* + * Closes the haptic device. + */ +void +SDL_SYS_HapticClose(SDL_Haptic * haptic) +{ + if (haptic->hwdata) { + + /* Free Effects. */ + SDL_free(haptic->effects); + haptic->effects = NULL; + haptic->neffects = 0; + + /* Clean up */ + FFReleaseDevice(haptic->hwdata->device); + + /* Free */ + SDL_free(haptic->hwdata); + haptic->hwdata = NULL; + } +} + + +/* + * Clean up after system specific haptic stuff + */ +void +SDL_SYS_HapticQuit(void) +{ + int i; + + for (i = 0; i < SDL_numhaptics; i++) { + /* Opened and not closed haptics are leaked, this is on purpose. + * Close your haptic devices after usage. */ + + /* Free the io_service_t */ + IOObjectRelease(SDL_hapticlist[i].dev); + } +} + + +/* + * Converts an SDL trigger button to an FFEFFECT trigger button. + */ +static DWORD +FFGetTriggerButton(Uint16 button) +{ + DWORD dwTriggerButton; + + dwTriggerButton = FFEB_NOTRIGGER; + + if (button != 0) { + dwTriggerButton = FFJOFS_BUTTON(button - 1); + } + + return dwTriggerButton; +} + + +/* + * Sets the direction. + */ +static int +SDL_SYS_SetDirection(FFEFFECT * effect, SDL_HapticDirection * dir, int naxes) +{ + LONG *rglDir; + + /* Handle no axes a part. */ + if (naxes == 0) { + effect->dwFlags |= FFEFF_SPHERICAL; /* Set as default. */ + effect->rglDirection = NULL; + return 0; + } + + /* Has axes. */ + rglDir = SDL_malloc(sizeof(LONG) * naxes); + if (rglDir == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(rglDir, 0, sizeof(LONG) * naxes); + effect->rglDirection = rglDir; + + switch (dir->type) { + case SDL_HAPTIC_POLAR: + effect->dwFlags |= FFEFF_POLAR; + rglDir[0] = dir->dir[0]; + return 0; + case SDL_HAPTIC_CARTESIAN: + effect->dwFlags |= FFEFF_CARTESIAN; + rglDir[0] = dir->dir[0]; + if (naxes > 1) + rglDir[1] = dir->dir[1]; + if (naxes > 2) + rglDir[2] = dir->dir[2]; + return 0; + case SDL_HAPTIC_SPHERICAL: + effect->dwFlags |= FFEFF_SPHERICAL; + rglDir[0] = dir->dir[0]; + if (naxes > 1) + rglDir[1] = dir->dir[1]; + if (naxes > 2) + rglDir[2] = dir->dir[2]; + return 0; + + default: + SDL_SetError("Haptic: Unknown direction type."); + return -1; + } +} + + +/* Clamps and converts. */ +#define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF) +/* Just converts. */ +#define CONVERT(x) (((x)*10000) / 0x7FFF) +/* + * Creates the FFEFFECT from a SDL_HapticEffect. + */ +static int +SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest, + SDL_HapticEffect * src) +{ + int i; + FFCONSTANTFORCE *constant; + FFPERIODIC *periodic; + FFCONDITION *condition; /* Actually an array of conditions - one per axis. */ + FFRAMPFORCE *ramp; + FFCUSTOMFORCE *custom; + FFENVELOPE *envelope; + SDL_HapticConstant *hap_constant; + SDL_HapticPeriodic *hap_periodic; + SDL_HapticCondition *hap_condition; + SDL_HapticRamp *hap_ramp; + SDL_HapticCustom *hap_custom; + DWORD *axes; + + /* Set global stuff. */ + SDL_memset(dest, 0, sizeof(FFEFFECT)); + dest->dwSize = sizeof(FFEFFECT); /* Set the structure size. */ + dest->dwSamplePeriod = 0; /* Not used by us. */ + dest->dwGain = 10000; /* Gain is set globally, not locally. */ + dest->dwFlags = FFEFF_OBJECTOFFSETS; /* Seems obligatory. */ + + /* Envelope. */ + envelope = SDL_malloc(sizeof(FFENVELOPE)); + if (envelope == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(envelope, 0, sizeof(FFENVELOPE)); + dest->lpEnvelope = envelope; + envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */ + + /* Axes. */ + dest->cAxes = haptic->naxes; + if (dest->cAxes > 0) { + axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); + if (axes == NULL) { + SDL_OutOfMemory(); + return -1; + } + axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */ + if (dest->cAxes > 1) { + axes[1] = haptic->hwdata->axes[1]; + } + if (dest->cAxes > 2) { + axes[2] = haptic->hwdata->axes[2]; + } + dest->rgdwAxes = axes; + } + + + /* The big type handling switch, even bigger then linux's version. */ + switch (src->type) { + case SDL_HAPTIC_CONSTANT: + hap_constant = &src->constant; + constant = SDL_malloc(sizeof(FFCONSTANTFORCE)); + if (constant == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(constant, 0, sizeof(FFCONSTANTFORCE)); + + /* Specifics */ + constant->lMagnitude = CONVERT(hap_constant->level); + dest->cbTypeSpecificParams = sizeof(FFCONSTANTFORCE); + dest->lpvTypeSpecificParams = constant; + + /* Generics */ + dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFGetTriggerButton(hap_constant->button); + dest->dwTriggerRepeatInterval = hap_constant->interval; + dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) + < 0) { + return -1; + } + + /* Envelope */ + if ((hap_constant->attack_length == 0) + && (hap_constant->fade_length == 0)) { + SDL_free(envelope); + dest->lpEnvelope = NULL; + } else { + envelope->dwAttackLevel = CCONVERT(hap_constant->attack_level); + envelope->dwAttackTime = hap_constant->attack_length * 1000; + envelope->dwFadeLevel = CCONVERT(hap_constant->fade_level); + envelope->dwFadeTime = hap_constant->fade_length * 1000; + } + + break; + + case SDL_HAPTIC_SINE: + case SDL_HAPTIC_SQUARE: + case SDL_HAPTIC_TRIANGLE: + case SDL_HAPTIC_SAWTOOTHUP: + case SDL_HAPTIC_SAWTOOTHDOWN: + hap_periodic = &src->periodic; + periodic = SDL_malloc(sizeof(FFPERIODIC)); + if (periodic == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(periodic, 0, sizeof(FFPERIODIC)); + + /* Specifics */ + periodic->dwMagnitude = CONVERT(hap_periodic->magnitude); + periodic->lOffset = CONVERT(hap_periodic->offset); + periodic->dwPhase = hap_periodic->phase; + periodic->dwPeriod = hap_periodic->period * 1000; + dest->cbTypeSpecificParams = sizeof(FFPERIODIC); + dest->lpvTypeSpecificParams = periodic; + + /* Generics */ + dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFGetTriggerButton(hap_periodic->button); + dest->dwTriggerRepeatInterval = hap_periodic->interval; + dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes) + < 0) { + return -1; + } + + /* Envelope */ + if ((hap_periodic->attack_length == 0) + && (hap_periodic->fade_length == 0)) { + SDL_free(envelope); + dest->lpEnvelope = NULL; + } else { + envelope->dwAttackLevel = CCONVERT(hap_periodic->attack_level); + envelope->dwAttackTime = hap_periodic->attack_length * 1000; + envelope->dwFadeLevel = CCONVERT(hap_periodic->fade_level); + envelope->dwFadeTime = hap_periodic->fade_length * 1000; + } + + break; + + case SDL_HAPTIC_SPRING: + case SDL_HAPTIC_DAMPER: + case SDL_HAPTIC_INERTIA: + case SDL_HAPTIC_FRICTION: + hap_condition = &src->condition; + condition = SDL_malloc(sizeof(FFCONDITION) * dest->cAxes); + if (condition == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(condition, 0, sizeof(FFCONDITION)); + + /* Specifics */ + for (i = 0; i < dest->cAxes; i++) { + condition[i].lOffset = CONVERT(hap_condition->center[i]); + condition[i].lPositiveCoefficient = + CONVERT(hap_condition->right_coeff[i]); + condition[i].lNegativeCoefficient = + CONVERT(hap_condition->left_coeff[i]); + condition[i].dwPositiveSaturation = + CCONVERT(hap_condition->right_sat[i]); + condition[i].dwNegativeSaturation = + CCONVERT(hap_condition->left_sat[i]); + condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i]); + } + dest->cbTypeSpecificParams = sizeof(FFCONDITION) * dest->cAxes; + dest->lpvTypeSpecificParams = condition; + + /* Generics */ + dest->dwDuration = hap_condition->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFGetTriggerButton(hap_condition->button); + dest->dwTriggerRepeatInterval = hap_condition->interval; + dest->dwStartDelay = hap_condition->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes) + < 0) { + return -1; + } + + /* Envelope - Not actually supported by most CONDITION implementations. */ + SDL_free(dest->lpEnvelope); + dest->lpEnvelope = NULL; + + break; + + case SDL_HAPTIC_RAMP: + hap_ramp = &src->ramp; + ramp = SDL_malloc(sizeof(FFRAMPFORCE)); + if (ramp == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(ramp, 0, sizeof(FFRAMPFORCE)); + + /* Specifics */ + ramp->lStart = CONVERT(hap_ramp->start); + ramp->lEnd = CONVERT(hap_ramp->end); + dest->cbTypeSpecificParams = sizeof(FFRAMPFORCE); + dest->lpvTypeSpecificParams = ramp; + + /* Generics */ + dest->dwDuration = hap_ramp->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFGetTriggerButton(hap_ramp->button); + dest->dwTriggerRepeatInterval = hap_ramp->interval; + dest->dwStartDelay = hap_ramp->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) { + return -1; + } + + /* Envelope */ + if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) { + SDL_free(envelope); + dest->lpEnvelope = NULL; + } else { + envelope->dwAttackLevel = CCONVERT(hap_ramp->attack_level); + envelope->dwAttackTime = hap_ramp->attack_length * 1000; + envelope->dwFadeLevel = CCONVERT(hap_ramp->fade_level); + envelope->dwFadeTime = hap_ramp->fade_length * 1000; + } + + break; + + case SDL_HAPTIC_CUSTOM: + hap_custom = &src->custom; + custom = SDL_malloc(sizeof(FFCUSTOMFORCE)); + if (custom == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(custom, 0, sizeof(FFCUSTOMFORCE)); + + /* Specifics */ + custom->cChannels = hap_custom->channels; + custom->dwSamplePeriod = hap_custom->period * 1000; + custom->cSamples = hap_custom->samples; + custom->rglForceData = + SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels); + for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */ + custom->rglForceData[i] = CCONVERT(hap_custom->data[i]); + } + dest->cbTypeSpecificParams = sizeof(FFCUSTOMFORCE); + dest->lpvTypeSpecificParams = custom; + + /* Generics */ + dest->dwDuration = hap_custom->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFGetTriggerButton(hap_custom->button); + dest->dwTriggerRepeatInterval = hap_custom->interval; + dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < + 0) { + return -1; + } + + /* Envelope */ + if ((hap_custom->attack_length == 0) + && (hap_custom->fade_length == 0)) { + SDL_free(envelope); + dest->lpEnvelope = NULL; + } else { + envelope->dwAttackLevel = CCONVERT(hap_custom->attack_level); + envelope->dwAttackTime = hap_custom->attack_length * 1000; + envelope->dwFadeLevel = CCONVERT(hap_custom->fade_level); + envelope->dwFadeTime = hap_custom->fade_length * 1000; + } + + break; + + + default: + SDL_SetError("Haptic: Unknown effect type."); + return -1; + } + + return 0; +} + + +/* + * Frees an FFEFFECT allocated by SDL_SYS_ToFFEFFECT. + */ +static void +SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect, int type) +{ + FFCUSTOMFORCE *custom; + + if (effect->lpEnvelope != NULL) { + SDL_free(effect->lpEnvelope); + effect->lpEnvelope = NULL; + } + if (effect->rgdwAxes != NULL) { + SDL_free(effect->rgdwAxes); + effect->rgdwAxes = NULL; + } + if (effect->lpvTypeSpecificParams != NULL) { + if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */ + custom = (FFCUSTOMFORCE *) effect->lpvTypeSpecificParams; + SDL_free(custom->rglForceData); + custom->rglForceData = NULL; + } + SDL_free(effect->lpvTypeSpecificParams); + effect->lpvTypeSpecificParams = NULL; + } + if (effect->rglDirection != NULL) { + SDL_free(effect->rglDirection); + effect->rglDirection = NULL; + } +} + + +/* + * Gets the effect type from the generic SDL haptic effect wrapper. + */ +CFUUIDRef +SDL_SYS_HapticEffectType(Uint16 type) +{ + switch (type) { + case SDL_HAPTIC_CONSTANT: + return kFFEffectType_ConstantForce_ID; + + case SDL_HAPTIC_RAMP: + return kFFEffectType_RampForce_ID; + + case SDL_HAPTIC_SQUARE: + return kFFEffectType_Square_ID; + + case SDL_HAPTIC_SINE: + return kFFEffectType_Sine_ID; + + case SDL_HAPTIC_TRIANGLE: + return kFFEffectType_Triangle_ID; + + case SDL_HAPTIC_SAWTOOTHUP: + return kFFEffectType_SawtoothUp_ID; + + case SDL_HAPTIC_SAWTOOTHDOWN: + return kFFEffectType_SawtoothDown_ID; + + case SDL_HAPTIC_SPRING: + return kFFEffectType_Spring_ID; + + case SDL_HAPTIC_DAMPER: + return kFFEffectType_Damper_ID; + + case SDL_HAPTIC_INERTIA: + return kFFEffectType_Inertia_ID; + + case SDL_HAPTIC_FRICTION: + return kFFEffectType_Friction_ID; + + case SDL_HAPTIC_CUSTOM: + return kFFEffectType_CustomForce_ID; + + default: + SDL_SetError("Haptic: Unknown effect type."); + return NULL; + } +} + + +/* + * Creates a new haptic effect. + */ +int +SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, + SDL_HapticEffect * base) +{ + HRESULT ret; + CFUUIDRef type; + + /* Alloc the effect. */ + effect->hweffect = (struct haptic_hweffect *) + SDL_malloc(sizeof(struct haptic_hweffect)); + if (effect->hweffect == NULL) { + SDL_OutOfMemory(); + goto err_hweffect; + } + + /* Get the type. */ + type = SDL_SYS_HapticEffectType(base->type); + if (type == NULL) { + goto err_hweffect; + } + + /* Get the effect. */ + if (SDL_SYS_ToFFEFFECT(haptic, &effect->hweffect->effect, base) < 0) { + goto err_effectdone; + } + + /* Create the actual effect. */ + ret = FFDeviceCreateEffect(haptic->hwdata->device, type, + &effect->hweffect->effect, + &effect->hweffect->ref); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to create effect: %s.", FFStrError(ret)); + goto err_effectdone; + } + + return 0; + + err_effectdone: + SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect, base->type); + err_hweffect: + if (effect->hweffect != NULL) { + SDL_free(effect->hweffect); + effect->hweffect = NULL; + } + return -1; +} + + +/* + * Updates an effect. + */ +int +SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic, + struct haptic_effect *effect, + SDL_HapticEffect * data) +{ + HRESULT ret; + FFEffectParameterFlag flags; + FFEFFECT temp; + + /* Get the effect. */ + SDL_memset(&temp, 0, sizeof(FFEFFECT)); + if (SDL_SYS_ToFFEFFECT(haptic, &temp, data) < 0) { + goto err_update; + } + + /* Set the flags. Might be worthwhile to diff temp with loaded effect and + * only change those parameters. */ + flags = FFEP_DIRECTION | + FFEP_DURATION | + FFEP_ENVELOPE | + FFEP_STARTDELAY | + FFEP_TRIGGERBUTTON | + FFEP_TRIGGERREPEATINTERVAL | FFEP_TYPESPECIFICPARAMS; + + /* Create the actual effect. */ + ret = FFEffectSetParameters(effect->hweffect->ref, &temp, flags); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to update effect: %s.", FFStrError(ret)); + goto err_update; + } + + /* Copy it over. */ + SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect, data->type); + SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(FFEFFECT)); + + return 0; + + err_update: + SDL_SYS_HapticFreeFFEFFECT(&temp, data->type); + return -1; +} + + +/* + * Runs an effect. + */ +int +SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, + Uint32 iterations) +{ + HRESULT ret; + Uint32 iter; + + /* Check if it's infinite. */ + if (iterations == SDL_HAPTIC_INFINITY) { + iter = FF_INFINITE; + } else + iter = iterations; + + /* Run the effect. */ + ret = FFEffectStart(effect->hweffect->ref, iter, 0); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to run the effect: %s.", + FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Stops an effect. + */ +int +SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect) +{ + HRESULT ret; + + ret = FFEffectStop(effect->hweffect->ref); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to stop the effect: %s.", + FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Frees the effect. + */ +void +SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect) +{ + HRESULT ret; + + ret = + FFDeviceReleaseEffect(haptic->hwdata->device, effect->hweffect->ref); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error removing the effect from the device: %s.", + FFStrError(ret)); + } + SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect, + effect->effect.type); + SDL_free(effect->hweffect); + effect->hweffect = NULL; +} + + +/* + * Gets the status of a haptic effect. + */ +int +SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic, + struct haptic_effect *effect) +{ + HRESULT ret; + FFEffectStatusFlag status; + + ret = FFEffectGetEffectStatus(effect->hweffect->ref, &status); + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to get effect status: %s.", + FFStrError(ret)); + return -1; + } + + if (status == 0) + return SDL_FALSE; + return SDL_TRUE; /* Assume it's playing or emulated. */ +} + + +/* + * Sets the gain. + */ +int +SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain) +{ + HRESULT ret; + Uint32 val; + + val = gain * 100; /* Mac OS X uses 0 to 10,000 */ + ret = + FFDeviceSetForceFeedbackProperty(haptic->hwdata->device, + FFPROP_FFGAIN, &val); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error setting gain: %s.", FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Sets the autocentering. + */ +int +SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter) +{ + HRESULT ret; + Uint32 val; + + /* Mac OS X only has 0 (off) and 1 (on) */ + if (autocenter == 0) + val = 0; + else + val = 1; + + ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device, + FFPROP_AUTOCENTER, &val); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error setting autocenter: %s.", + FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Pauses the device. + */ +int +SDL_SYS_HapticPause(SDL_Haptic * haptic) +{ + HRESULT ret; + + ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device, + FFSFFC_PAUSE); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error pausing device: %s.", FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Unpauses the device. + */ +int +SDL_SYS_HapticUnpause(SDL_Haptic * haptic) +{ + HRESULT ret; + + ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device, + FFSFFC_CONTINUE); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error pausing device: %s.", FFStrError(ret)); + return -1; + } + + return 0; +} + + +/* + * Stops all currently playing effects. + */ +int +SDL_SYS_HapticStopAll(SDL_Haptic * haptic) +{ + HRESULT ret; + + ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device, + FFSFFC_STOPALL); + if (ret != FF_OK) { + SDL_SetError("Haptic: Error stopping device: %s.", FFStrError(ret)); + return -1; + } + + return 0; +} + + +#endif /* SDL_HAPTIC_IOKIT */ diff --git a/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick.c b/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick.c index add306a5..189b8117 100644 --- a/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick.c +++ b/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick.c @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,16 +19,14 @@ Sam Lantinga slouken@libsdl.org */ -// 7-25-2010 Wei Mingzhi -// Removed everything unrelated to Mac OS X Joystick support. - -#include "SDL.h" +#include "SDL_config.h" /* This is the joystick API for Simple DirectMedia Layer */ - +#include "SDL.h" #include "SDL_sysjoystick.h" #include "SDL_joystick_c.h" +/* This is used for Quake III Arena */ #define SDL_Lock_EventThread() #define SDL_Unlock_EventThread() @@ -36,47 +34,49 @@ Uint8 SDL_numjoysticks = 0; SDL_Joystick **SDL_joysticks = NULL; static SDL_Joystick *default_joystick = NULL; -int SDL_JoystickInit(void) +int +SDL_JoystickInit(void) { - int arraylen; - int status; - - SDL_numjoysticks = 0; - status = SDL_SYS_JoystickInit(); - if ( status >= 0 ) { - arraylen = (status+1)*sizeof(*SDL_joysticks); - SDL_joysticks = (SDL_Joystick **)SDL_malloc(arraylen); - if ( SDL_joysticks == NULL ) { - SDL_numjoysticks = 0; - } else { - SDL_memset(SDL_joysticks, 0, arraylen); - SDL_numjoysticks = status; - } - status = 0; - } - default_joystick = NULL; - return(status); + int arraylen; + int status; + + SDL_numjoysticks = 0; + status = SDL_SYS_JoystickInit(); + if (status >= 0) { + arraylen = (status + 1) * sizeof(*SDL_joysticks); + SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen); + if (SDL_joysticks == NULL) { + SDL_numjoysticks = 0; + } else { + SDL_memset(SDL_joysticks, 0, arraylen); + SDL_numjoysticks = status; + } + status = 0; + } + default_joystick = NULL; + return (status); } /* * Count the number of joysticks attached to the system */ -int SDL_NumJoysticks(void) +int +SDL_NumJoysticks(void) { - return SDL_numjoysticks; + return SDL_numjoysticks; } /* * Get the implementation dependent name of a joystick */ -const char *SDL_JoystickName(int device_index) +const char * +SDL_JoystickName(int device_index) { - if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { - SDL_SetError("There are %d joysticks available", - SDL_numjoysticks); - return(NULL); - } - return(SDL_SYS_JoystickName(device_index)); + if ((device_index < 0) || (device_index >= SDL_numjoysticks)) { + SDL_SetError("There are %d joysticks available", SDL_numjoysticks); + return (NULL); + } + return (SDL_SYS_JoystickName(device_index)); } /* @@ -86,396 +86,418 @@ const char *SDL_JoystickName(int device_index) * * This function returns a joystick identifier, or NULL if an error occurred. */ -SDL_Joystick *SDL_JoystickOpen(int device_index) +SDL_Joystick * +SDL_JoystickOpen(int device_index) { - int i; - SDL_Joystick *joystick; - - if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { - SDL_SetError("There are %d joysticks available", - SDL_numjoysticks); - return(NULL); - } - - /* If the joystick is already open, return it */ - for ( i=0; SDL_joysticks[i]; ++i ) { - if ( device_index == SDL_joysticks[i]->index ) { - joystick = SDL_joysticks[i]; - ++joystick->ref_count; - return(joystick); - } - } - - /* Create and initialize the joystick */ - joystick = (SDL_Joystick *)SDL_malloc((sizeof *joystick)); - if ( joystick != NULL ) { - SDL_memset(joystick, 0, (sizeof *joystick)); - joystick->index = device_index; - if ( SDL_SYS_JoystickOpen(joystick) < 0 ) { - SDL_free(joystick); - joystick = NULL; - } else { - if ( joystick->naxes > 0 ) { - joystick->axes = (Sint16 *)SDL_malloc - (joystick->naxes*sizeof(Sint16)); - } - if ( joystick->nhats > 0 ) { - joystick->hats = (Uint8 *)SDL_malloc - (joystick->nhats*sizeof(Uint8)); - } - if ( joystick->nballs > 0 ) { - joystick->balls = (struct balldelta *)SDL_malloc - (joystick->nballs*sizeof(*joystick->balls)); - } - if ( joystick->nbuttons > 0 ) { - joystick->buttons = (Uint8 *)SDL_malloc - (joystick->nbuttons*sizeof(Uint8)); - } - if ( ((joystick->naxes > 0) && !joystick->axes) - || ((joystick->nhats > 0) && !joystick->hats) - || ((joystick->nballs > 0) && !joystick->balls) - || ((joystick->nbuttons > 0) && !joystick->buttons)) { - SDL_OutOfMemory(); - SDL_JoystickClose(joystick); - joystick = NULL; - } - if ( joystick->axes ) { - SDL_memset(joystick->axes, 0, - joystick->naxes*sizeof(Sint16)); - } - if ( joystick->hats ) { - SDL_memset(joystick->hats, 0, - joystick->nhats*sizeof(Uint8)); - } - if ( joystick->balls ) { - SDL_memset(joystick->balls, 0, - joystick->nballs*sizeof(*joystick->balls)); - } - if ( joystick->buttons ) { - SDL_memset(joystick->buttons, 0, - joystick->nbuttons*sizeof(Uint8)); - } - } - } - if ( joystick ) { - /* Add joystick to list */ - ++joystick->ref_count; - SDL_Lock_EventThread(); - for ( i=0; SDL_joysticks[i]; ++i ) - /* Skip to next joystick */; - SDL_joysticks[i] = joystick; - SDL_Unlock_EventThread(); - } - return(joystick); + int i; + SDL_Joystick *joystick; + + if ((device_index < 0) || (device_index >= SDL_numjoysticks)) { + SDL_SetError("There are %d joysticks available", SDL_numjoysticks); + return (NULL); + } + + /* If the joystick is already open, return it */ + for (i = 0; SDL_joysticks[i]; ++i) { + if (device_index == SDL_joysticks[i]->index) { + joystick = SDL_joysticks[i]; + ++joystick->ref_count; + return (joystick); + } + } + + /* Create and initialize the joystick */ + joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick)); + if (joystick == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + SDL_memset(joystick, 0, (sizeof *joystick)); + joystick->index = device_index; + if (SDL_SYS_JoystickOpen(joystick) < 0) { + SDL_free(joystick); + return NULL; + } + if (joystick->naxes > 0) { + joystick->axes = (Sint16 *) SDL_malloc + (joystick->naxes * sizeof(Sint16)); + } + if (joystick->nhats > 0) { + joystick->hats = (Uint8 *) SDL_malloc + (joystick->nhats * sizeof(Uint8)); + } + if (joystick->nballs > 0) { + joystick->balls = (struct balldelta *) SDL_malloc + (joystick->nballs * sizeof(*joystick->balls)); + } + if (joystick->nbuttons > 0) { + joystick->buttons = (Uint8 *) SDL_malloc + (joystick->nbuttons * sizeof(Uint8)); + } + if (((joystick->naxes > 0) && !joystick->axes) + || ((joystick->nhats > 0) && !joystick->hats) + || ((joystick->nballs > 0) && !joystick->balls) + || ((joystick->nbuttons > 0) && !joystick->buttons)) { + SDL_OutOfMemory(); + SDL_JoystickClose(joystick); + return NULL; + } + if (joystick->axes) { + SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16)); + } + if (joystick->hats) { + SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8)); + } + if (joystick->balls) { + SDL_memset(joystick->balls, 0, + joystick->nballs * sizeof(*joystick->balls)); + } + if (joystick->buttons) { + SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8)); + } + + /* Add joystick to list */ + ++joystick->ref_count; + SDL_Lock_EventThread(); + for (i = 0; SDL_joysticks[i]; ++i) + /* Skip to next joystick */ ; + SDL_joysticks[i] = joystick; + SDL_Unlock_EventThread(); + + return (joystick); } /* * Returns 1 if the joystick has been opened, or 0 if it has not. */ -int SDL_JoystickOpened(int device_index) +int +SDL_JoystickOpened(int device_index) { - int i, opened; - - opened = 0; - for ( i=0; SDL_joysticks[i]; ++i ) { - if ( SDL_joysticks[i]->index == (Uint8)device_index ) { - opened = 1; - break; - } - } - return(opened); + int i, opened; + + opened = 0; + for (i = 0; SDL_joysticks[i]; ++i) { + if (SDL_joysticks[i]->index == (Uint8) device_index) { + opened = 1; + break; + } + } + return (opened); } -static int ValidJoystick(SDL_Joystick **joystick) + +/* + * Checks to make sure the joystick is valid. + */ +int +SDL_PrivateJoystickValid(SDL_Joystick ** joystick) { - int valid; - - if ( *joystick == NULL ) { - *joystick = default_joystick; - } - if ( *joystick == NULL ) { - SDL_SetError("Joystick hasn't been opened yet"); - valid = 0; - } else { - valid = 1; - } - return valid; + int valid; + + if (*joystick == NULL) { + *joystick = default_joystick; + } + if (*joystick == NULL) { + SDL_SetError("Joystick hasn't been opened yet"); + valid = 0; + } else { + valid = 1; + } + return valid; } /* * Get the device index of an opened joystick. */ -int SDL_JoystickIndex(SDL_Joystick *joystick) +int +SDL_JoystickIndex(SDL_Joystick * joystick) { - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - return(joystick->index); + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + return (joystick->index); } /* * Get the number of multi-dimensional axis controls on a joystick */ -int SDL_JoystickNumAxes(SDL_Joystick *joystick) +int +SDL_JoystickNumAxes(SDL_Joystick * joystick) { - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - return(joystick->naxes); + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + return (joystick->naxes); } /* * Get the number of hats on a joystick */ -int SDL_JoystickNumHats(SDL_Joystick *joystick) +int +SDL_JoystickNumHats(SDL_Joystick * joystick) { - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - return(joystick->nhats); + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + return (joystick->nhats); } /* * Get the number of trackballs on a joystick */ -int SDL_JoystickNumBalls(SDL_Joystick *joystick) +int +SDL_JoystickNumBalls(SDL_Joystick * joystick) { - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - return(joystick->nballs); + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + return (joystick->nballs); } /* * Get the number of buttons on a joystick */ -int SDL_JoystickNumButtons(SDL_Joystick *joystick) +int +SDL_JoystickNumButtons(SDL_Joystick * joystick) { - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - return(joystick->nbuttons); + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + return (joystick->nbuttons); } /* * Get the current state of an axis control on a joystick */ -Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) +Sint16 +SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis) { - Sint16 state; - - if ( ! ValidJoystick(&joystick) ) { - return(0); - } - if ( axis < joystick->naxes ) { - state = joystick->axes[axis]; - } else { - SDL_SetError("Joystick only has %d axes", joystick->naxes); - state = 0; - } - return(state); + Sint16 state; + + if (!SDL_PrivateJoystickValid(&joystick)) { + return (0); + } + if (axis < joystick->naxes) { + state = joystick->axes[axis]; + } else { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + state = 0; + } + return (state); } /* * Get the current state of a hat on a joystick */ -Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) +Uint8 +SDL_JoystickGetHat(SDL_Joystick * joystick, int hat) { - Uint8 state; - - if ( ! ValidJoystick(&joystick) ) { - return(0); - } - if ( hat < joystick->nhats ) { - state = joystick->hats[hat]; - } else { - SDL_SetError("Joystick only has %d hats", joystick->nhats); - state = 0; - } - return(state); + Uint8 state; + + if (!SDL_PrivateJoystickValid(&joystick)) { + return (0); + } + if (hat < joystick->nhats) { + state = joystick->hats[hat]; + } else { + SDL_SetError("Joystick only has %d hats", joystick->nhats); + state = 0; + } + return (state); } /* * Get the ball axis change since the last poll */ -int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) +int +SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy) { - int retval; - - if ( ! ValidJoystick(&joystick) ) { - return(-1); - } - - retval = 0; - if ( ball < joystick->nballs ) { - if ( dx ) { - *dx = joystick->balls[ball].dx; - } - if ( dy ) { - *dy = joystick->balls[ball].dy; - } - joystick->balls[ball].dx = 0; - joystick->balls[ball].dy = 0; - } else { - SDL_SetError("Joystick only has %d balls", joystick->nballs); - retval = -1; - } - return(retval); + int retval; + + if (!SDL_PrivateJoystickValid(&joystick)) { + return (-1); + } + + retval = 0; + if (ball < joystick->nballs) { + if (dx) { + *dx = joystick->balls[ball].dx; + } + if (dy) { + *dy = joystick->balls[ball].dy; + } + joystick->balls[ball].dx = 0; + joystick->balls[ball].dy = 0; + } else { + SDL_SetError("Joystick only has %d balls", joystick->nballs); + retval = -1; + } + return (retval); } /* * Get the current state of a button on a joystick */ -Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) +Uint8 +SDL_JoystickGetButton(SDL_Joystick * joystick, int button) { - Uint8 state; - - if ( ! ValidJoystick(&joystick) ) { - return(0); - } - if ( button < joystick->nbuttons ) { - state = joystick->buttons[button]; - } else { - SDL_SetError("Joystick only has %d buttons",joystick->nbuttons); - state = 0; - } - return(state); + Uint8 state; + + if (!SDL_PrivateJoystickValid(&joystick)) { + return (0); + } + if (button < joystick->nbuttons) { + state = joystick->buttons[button]; + } else { + SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); + state = 0; + } + return (state); } /* * Close a joystick previously opened with SDL_JoystickOpen() */ -void SDL_JoystickClose(SDL_Joystick *joystick) +void +SDL_JoystickClose(SDL_Joystick * joystick) { - int i; - - if ( ! ValidJoystick(&joystick) ) { - return; - } - - /* First decrement ref count */ - if ( --joystick->ref_count > 0 ) { - return; - } - - /* Lock the event queue - prevent joystick polling */ - SDL_Lock_EventThread(); - - if ( joystick == default_joystick ) { - default_joystick = NULL; - } - SDL_SYS_JoystickClose(joystick); - - /* Remove joystick from list */ - for ( i=0; SDL_joysticks[i]; ++i ) { - if ( joystick == SDL_joysticks[i] ) { - SDL_memcpy(&SDL_joysticks[i], &SDL_joysticks[i+1], - (SDL_numjoysticks-i)*sizeof(joystick)); - break; - } - } - - /* Let the event thread keep running */ - SDL_Unlock_EventThread(); - - /* Free the data associated with this joystick */ - if ( joystick->axes ) { - SDL_free(joystick->axes); - } - if ( joystick->hats ) { - SDL_free(joystick->hats); - } - if ( joystick->balls ) { - SDL_free(joystick->balls); - } - if ( joystick->buttons ) { - SDL_free(joystick->buttons); - } - SDL_free(joystick); + int i; + + if (!SDL_PrivateJoystickValid(&joystick)) { + return; + } + + /* First decrement ref count */ + if (--joystick->ref_count > 0) { + return; + } + + /* Lock the event queue - prevent joystick polling */ + SDL_Lock_EventThread(); + + if (joystick == default_joystick) { + default_joystick = NULL; + } + SDL_SYS_JoystickClose(joystick); + + /* Remove joystick from list */ + for (i = 0; SDL_joysticks[i]; ++i) { + if (joystick == SDL_joysticks[i]) { + SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1], + (SDL_numjoysticks - i) * sizeof(joystick)); + break; + } + } + + /* Let the event thread keep running */ + SDL_Unlock_EventThread(); + + /* Free the data associated with this joystick */ + if (joystick->axes) { + SDL_free(joystick->axes); + } + if (joystick->hats) { + SDL_free(joystick->hats); + } + if (joystick->balls) { + SDL_free(joystick->balls); + } + if (joystick->buttons) { + SDL_free(joystick->buttons); + } + SDL_free(joystick); } -void SDL_JoystickQuit(void) +void +SDL_JoystickQuit(void) { - /* Stop the event polling */ - SDL_Lock_EventThread(); - SDL_numjoysticks = 0; - SDL_Unlock_EventThread(); - - /* Quit the joystick setup */ - SDL_SYS_JoystickQuit(); - if ( SDL_joysticks ) { - SDL_free(SDL_joysticks); - SDL_joysticks = NULL; - } + /* Stop the event polling */ + SDL_Lock_EventThread(); + SDL_numjoysticks = 0; + SDL_Unlock_EventThread(); + + /* Quit the joystick setup */ + SDL_SYS_JoystickQuit(); + if (SDL_joysticks) { + SDL_free(SDL_joysticks); + SDL_joysticks = NULL; + } } /* These are global for SDL_sysjoystick.c and SDL_events.c */ -int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value) +int +SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value) { - int posted; + int posted; - /* Update internal joystick state */ - joystick->axes[axis] = value; + /* Update internal joystick state */ + joystick->axes[axis] = value; - /* Post the event, if desired */ - posted = 0; + /* Post the event, if desired */ + posted = 0; - return(posted); + return (posted); } -int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) +int +SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value) { - int posted; + int posted; - /* Update internal joystick state */ - joystick->hats[hat] = value; + /* Update internal joystick state */ + joystick->hats[hat] = value; - /* Post the event, if desired */ - posted = 0; + /* Post the event, if desired */ + posted = 0; - return(posted); + return (posted); } -int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, - Sint16 xrel, Sint16 yrel) +int +SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, + Sint16 xrel, Sint16 yrel) { - int posted; + int posted; - /* Update internal mouse state */ - joystick->balls[ball].dx += xrel; - joystick->balls[ball].dy += yrel; + /* Update internal mouse state */ + joystick->balls[ball].dx += xrel; + joystick->balls[ball].dy += yrel; - /* Post the event, if desired */ - posted = 0; + /* Post the event, if desired */ + posted = 0; - return(posted); + return (posted); } -int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) +int +SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state) { - int posted; + int posted; - /* Update internal joystick state */ - joystick->buttons[button] = state; + /* Update internal joystick state */ + joystick->buttons[button] = state; - /* Post the event, if desired */ - posted = 0; + /* Post the event, if desired */ + posted = 0; - return(posted); + return (posted); } -void SDL_JoystickUpdate(void) +void +SDL_JoystickUpdate(void) { - int i; + int i; - for ( i=0; SDL_joysticks[i]; ++i ) { - SDL_SYS_JoystickUpdate(SDL_joysticks[i]); - } + for (i = 0; SDL_joysticks[i]; ++i) { + SDL_SYS_JoystickUpdate(SDL_joysticks[i]); + } } -int SDL_JoystickEventState(int state) +int +SDL_JoystickEventState(int state) { - return SDL_IGNORE; + return SDL_IGNORE; } diff --git a/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick_c.h b/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick_c.h index 032751cc..e0f8529e 100644 --- a/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick_c.h +++ b/macosx/plugins/DFInput/SDL/src/joystick/SDL_joystick_c.h @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,6 @@ Sam Lantinga slouken@libsdl.org */ -// 7-25-2010 Wei Mingzhi -// Removed everything unrelated to Mac OS X Joystick support. - #include "SDL_config.h" /* Useful functions and variables from SDL_joystick.c */ @@ -30,12 +27,21 @@ /* The number of available joysticks on the system */ extern Uint8 SDL_numjoysticks; +/* Initialization and shutdown functions */ +extern int SDL_JoystickInit(void); +extern void SDL_JoystickQuit(void); + /* Internal event queueing functions */ -extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, +extern int SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value); -extern int SDL_PrivateJoystickBall(SDL_Joystick *joystick, +extern int SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, Sint16 xrel, Sint16 yrel); -extern int SDL_PrivateJoystickHat(SDL_Joystick *joystick, - Uint8 hat, Uint8 value); -extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick, +extern int SDL_PrivateJoystickHat(SDL_Joystick * joystick, + Uint8 hat, Uint8 value); +extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state); + +/* Internal sanity checking functions */ +extern int SDL_PrivateJoystickValid(SDL_Joystick ** joystick); + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/joystick/SDL_sysjoystick.h b/macosx/plugins/DFInput/SDL/src/joystick/SDL_sysjoystick.h index 48fbb3cf..ddb3b84f 100644 --- a/macosx/plugins/DFInput/SDL/src/joystick/SDL_sysjoystick.h +++ b/macosx/plugins/DFInput/SDL/src/joystick/SDL_sysjoystick.h @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga + Copyright (C) 1997-2010 Sam Lantinga This library is SDL_free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,6 @@ Sam Lantinga slouken@libsdl.org */ -// 7-25-2010 Wei Mingzhi -// Removed everything unrelated to Mac OS X Joystick support. - #include "SDL_config.h" /* This is the system specific header for the SDL joystick API */ @@ -29,28 +26,30 @@ #include "SDL_joystick.h" /* The SDL joystick structure */ -struct _SDL_Joystick { - Uint8 index; /* Device index */ - const char *name; /* Joystick name - system dependent */ - - int naxes; /* Number of axis controls on the joystick */ - Sint16 *axes; /* Current axis states */ - - int nhats; /* Number of hats on the joystick */ - Uint8 *hats; /* Current hat states */ - - int nballs; /* Number of trackballs on the joystick */ - struct balldelta { - int dx; - int dy; - } *balls; /* Current ball motion deltas */ - - int nbuttons; /* Number of buttons on the joystick */ - Uint8 *buttons; /* Current button states */ - - struct joystick_hwdata *hwdata; /* Driver dependent information */ - - int ref_count; /* Reference count for multiple opens */ +struct _SDL_Joystick +{ + Uint8 index; /* Device index */ + const char *name; /* Joystick name - system dependent */ + + int naxes; /* Number of axis controls on the joystick */ + Sint16 *axes; /* Current axis states */ + + int nhats; /* Number of hats on the joystick */ + Uint8 *hats; /* Current hat states */ + + int nballs; /* Number of trackballs on the joystick */ + struct balldelta + { + int dx; + int dy; + } *balls; /* Current ball motion deltas */ + + int nbuttons; /* Number of buttons on the joystick */ + Uint8 *buttons; /* Current button states */ + + struct joystick_hwdata *hwdata; /* Driver dependent information */ + + int ref_count; /* Reference count for multiple opens */ }; /* Function to scan the system for joysticks. @@ -68,18 +67,19 @@ extern const char *SDL_SYS_JoystickName(int index); This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ -extern int SDL_SYS_JoystickOpen(SDL_Joystick *joystick); +extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick); /* Function to update the state of a joystick - called as a device poll. * This function shouldn't update the joystick structure directly, * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ -extern void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick); +extern void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick); /* Function to close a joystick after use */ -extern void SDL_SYS_JoystickClose(SDL_Joystick *joystick); +extern void SDL_SYS_JoystickClose(SDL_Joystick * joystick); /* Function to perform any system-specific joystick related cleanup */ extern void SDL_SYS_JoystickQuit(void); +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick.c b/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick.c index b89e8332..824917f2 100644 --- a/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick.c +++ b/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick.c @@ -1,27 +1,24 @@ /* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2004 Sam Lantinga + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Sam Lantinga - slouken@libsdl.org + Sam Lantinga + slouken@libsdl.org */ -// 7-25-2010 Wei Mingzhi -// Removed everything unrelated to Mac OS X Joystick support. - #include "SDL_config.h" #ifdef SDL_JOYSTICK_IOKIT @@ -45,121 +42,81 @@ #include <IOKit/hid/IOHIDLib.h> #include <IOKit/hid/IOHIDKeys.h> #include <CoreFoundation/CoreFoundation.h> -#include <Carbon/Carbon.h> /* for NewPtrClear, DisposePtr */ +#include <Carbon/Carbon.h> /* for NewPtrClear, DisposePtr */ + +/* For force feedback testing. */ +#include <ForceFeedback/ForceFeedback.h> +#include <ForceFeedback/ForceFeedbackConstants.h> #include "SDL_joystick.h" #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" - -struct recElement -{ - IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */ - long min; /* reported min value possible */ - long max; /* reported max value possible */ -#if 0 - /* TODO: maybe should handle the following stuff somehow? */ - - long scaledMin; /* reported scaled min value possible */ - long scaledMax; /* reported scaled max value possible */ - long size; /* size in bits of data return from element */ - Boolean relative; /* are reports relative to last report (deltas) */ - Boolean wrapping; /* does element wrap around (one value higher than max is min) */ - Boolean nonLinear; /* are the values reported non-linear relative to element movement */ - Boolean preferredState; /* does element have a preferred state (such as a button) */ - Boolean nullState; /* does element have null state */ -#endif /* 0 */ - - /* runtime variables used for auto-calibration */ - long minReport; /* min returned value */ - long maxReport; /* max returned value */ - - struct recElement * pNext; /* next element in list */ -}; -typedef struct recElement recElement; - -struct joystick_hwdata -{ - IOHIDDeviceInterface ** interface; /* interface to device, NULL = no interface */ - - char product[256]; /* name of product */ - long usage; /* usage page from IOUSBHID Parser.h which defines general usage */ - long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ - - long axes; /* number of axis (calculated, not reported by device) */ - long buttons; /* number of buttons (calculated, not reported by device) */ - long hats; /* number of hat switches (calculated, not reported by device) */ - long elements; /* number of total elements (shouldbe total of above) (calculated, not reported by device) */ - - recElement* firstAxis; - recElement* firstButton; - recElement* firstHat; - - int removed; - int uncentered; - - struct joystick_hwdata* pNext; /* next device */ -}; -typedef struct joystick_hwdata recDevice; +#include "SDL_sysjoystick_c.h" /* Linked list of all available devices */ static recDevice *gpDeviceList = NULL; -static void HIDReportErrorNum (char * strError, long numError) +static void +HIDReportErrorNum(char *strError, long numError) { - SDL_SetError(strError); + SDL_SetError(strError); } -static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice); +static void HIDGetCollectionElements(CFMutableDictionaryRef deviceProperties, + recDevice * pDevice); /* returns current value for element, polling element * will return 0 on error conditions which should be accounted for by application */ -static SInt32 HIDGetElementValue (recDevice *pDevice, recElement *pElement) +static SInt32 +HIDGetElementValue(recDevice * pDevice, recElement * pElement) { - IOReturn result = kIOReturnSuccess; - IOHIDEventStruct hidEvent; - hidEvent.value = 0; - - if (NULL != pDevice && NULL != pElement && NULL != pDevice->interface) - { - result = (*(pDevice->interface))->getElementValue(pDevice->interface, pElement->cookie, &hidEvent); - if (kIOReturnSuccess == result) - { - /* record min and max for auto calibration */ - if (hidEvent.value < pElement->minReport) - pElement->minReport = hidEvent.value; - if (hidEvent.value > pElement->maxReport) - pElement->maxReport = hidEvent.value; - } - } - - /* auto user scale */ - return hidEvent.value; + IOReturn result = kIOReturnSuccess; + IOHIDEventStruct hidEvent; + hidEvent.value = 0; + + if (NULL != pDevice && NULL != pElement && NULL != pDevice->interface) { + result = + (*(pDevice->interface))->getElementValue(pDevice->interface, + pElement->cookie, + &hidEvent); + if (kIOReturnSuccess == result) { + /* record min and max for auto calibration */ + if (hidEvent.value < pElement->minReport) + pElement->minReport = hidEvent.value; + if (hidEvent.value > pElement->maxReport) + pElement->maxReport = hidEvent.value; + } + } + + /* auto user scale */ + return hidEvent.value; } -static SInt32 HIDScaledCalibratedValue (recDevice *pDevice, recElement *pElement, long min, long max) +static SInt32 +HIDScaledCalibratedValue(recDevice * pDevice, recElement * pElement, + long min, long max) { - float deviceScale = max - min; - float readScale = pElement->maxReport - pElement->minReport; - SInt32 value = HIDGetElementValue(pDevice, pElement); - if (readScale == 0) - return value; /* no scaling at all */ - else - return ((value - pElement->minReport) * deviceScale / readScale) + min; + float deviceScale = max - min; + float readScale = pElement->maxReport - pElement->minReport; + SInt32 value = HIDGetElementValue(pDevice, pElement); + if (readScale == 0) + return value; /* no scaling at all */ + else + return ((value - pElement->minReport) * deviceScale / readScale) + + min; } -static void HIDRemovalCallback(void * target, - IOReturn result, - void * refcon, - void * sender) +static void +HIDRemovalCallback(void *target, IOReturn result, void *refcon, void *sender) { - recDevice *device = (recDevice *) refcon; - device->removed = 1; - device->uncentered = 1; + recDevice *device = (recDevice *) refcon; + device->removed = 1; + device->uncentered = 1; } @@ -168,39 +125,50 @@ static void HIDRemovalCallback(void * target, * Note: appliction now owns the device and must close and release it prior to exiting */ -static IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, recDevice *pDevice) +static IOReturn +HIDCreateOpenDeviceInterface(io_object_t hidDevice, recDevice * pDevice) { - IOReturn result = kIOReturnSuccess; - HRESULT plugInResult = S_OK; - SInt32 score = 0; - IOCFPlugInInterface ** ppPlugInInterface = NULL; - - if (NULL == pDevice->interface) - { - result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); - if (kIOReturnSuccess == result) - { - /* Call a method of the intermediate plug-in to create the device interface */ - plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, - CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); - if (S_OK != plugInResult) - HIDReportErrorNum ("CouldnÕô query HID class device interface from plugInInterface", plugInResult); - (*ppPlugInInterface)->Release (ppPlugInInterface); - } - else - HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); - } - if (NULL != pDevice->interface) - { - result = (*(pDevice->interface))->open (pDevice->interface, 0); - if (kIOReturnSuccess != result) - HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); - else - (*(pDevice->interface))->setRemovalCallback (pDevice->interface, HIDRemovalCallback, pDevice, pDevice); - - } - return result; + IOReturn result = kIOReturnSuccess; + HRESULT plugInResult = S_OK; + SInt32 score = 0; + IOCFPlugInInterface **ppPlugInInterface = NULL; + + if (NULL == pDevice->interface) { + result = + IOCreatePlugInInterfaceForService(hidDevice, + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &ppPlugInInterface, &score); + if (kIOReturnSuccess == result) { + /* Call a method of the intermediate plug-in to create the device interface */ + plugInResult = + (*ppPlugInInterface)->QueryInterface(ppPlugInInterface, + CFUUIDGetUUIDBytes + (kIOHIDDeviceInterfaceID), + (void *) + &(pDevice->interface)); + if (S_OK != plugInResult) + HIDReportErrorNum + ("CouldnÕt query HID class device interface from plugInInterface", + plugInResult); + (*ppPlugInInterface)->Release(ppPlugInInterface); + } else + HIDReportErrorNum + ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", + result); + } + if (NULL != pDevice->interface) { + result = (*(pDevice->interface))->open(pDevice->interface, 0); + if (kIOReturnSuccess != result) + HIDReportErrorNum + ("Failed to open pDevice->interface via open.", result); + else + (*(pDevice->interface))->setRemovalCallback(pDevice->interface, + HIDRemovalCallback, + pDevice, pDevice); + + } + return result; } /* Closes and releases interface to device, should be done prior to exting application @@ -209,45 +177,47 @@ static IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, recDevice * * (device may have to be plug and re-plugged in different location to get it working again without a restart) */ -static IOReturn HIDCloseReleaseInterface (recDevice *pDevice) +static IOReturn +HIDCloseReleaseInterface(recDevice * pDevice) { - IOReturn result = kIOReturnSuccess; - - if ((NULL != pDevice) && (NULL != pDevice->interface)) - { - /* close the interface */ - result = (*(pDevice->interface))->close (pDevice->interface); - if (kIOReturnNotOpen == result) - { - /* do nothing as device was not opened, thus can't be closed */ - } - else if (kIOReturnSuccess != result) - HIDReportErrorNum ("Failed to close IOHIDDeviceInterface.", result); - /* release the interface */ - result = (*(pDevice->interface))->Release (pDevice->interface); - if (kIOReturnSuccess != result) - HIDReportErrorNum ("Failed to release IOHIDDeviceInterface.", result); - pDevice->interface = NULL; - } - return result; + IOReturn result = kIOReturnSuccess; + + if ((NULL != pDevice) && (NULL != pDevice->interface)) { + /* close the interface */ + result = (*(pDevice->interface))->close(pDevice->interface); + if (kIOReturnNotOpen == result) { + /* do nothing as device was not opened, thus can't be closed */ + } else if (kIOReturnSuccess != result) + HIDReportErrorNum("Failed to close IOHIDDeviceInterface.", + result); + /* release the interface */ + result = (*(pDevice->interface))->Release(pDevice->interface); + if (kIOReturnSuccess != result) + HIDReportErrorNum("Failed to release IOHIDDeviceInterface.", + result); + pDevice->interface = NULL; + } + return result; } /* extracts actual specific element information from each element CF dictionary entry */ -static void HIDGetElementInfo (CFTypeRef refElement, recElement *pElement) +static void +HIDGetElementInfo(CFTypeRef refElement, recElement * pElement) { - long number; - CFTypeRef refType; - - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->cookie = (IOHIDElementCookie) number; - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->minReport = pElement->min = number; - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->maxReport = pElement->max = number; + long number; + CFTypeRef refType; + + refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementCookieKey)); + if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) + pElement->cookie = (IOHIDElementCookie) number; + refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMinKey)); + if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) + pElement->minReport = pElement->min = number; + pElement->maxReport = pElement->min; + refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMaxKey)); + if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) + pElement->maxReport = pElement->max = number; /* TODO: maybe should handle the following stuff somehow? @@ -276,292 +246,327 @@ static void HIDGetElementInfo (CFTypeRef refElement, recElement *pElement) if (refType) pElement->nullState = CFBooleanGetValue (refType); */ -} +} /* examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements * if element of interest allocate storage, add to list and retrieve element specific info * if collection then pass on to deconstruction collection into additional individual elements */ -static void HIDAddElement (CFTypeRef refElement, recDevice* pDevice) +static void +HIDAddElement(CFTypeRef refElement, recDevice * pDevice) { - recElement* element = NULL; - recElement** headElement = NULL; - long elementType, usagePage, usage; - CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); - CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); - CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); - - - if ((refElementType) && (CFNumberGetValue (refElementType, kCFNumberLongType, &elementType))) - { - /* look at types of interest */ - if ((elementType == kIOHIDElementTypeInput_Misc) || (elementType == kIOHIDElementTypeInput_Button) || - (elementType == kIOHIDElementTypeInput_Axis)) - { - if (refUsagePage && CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage) && - refUsage && CFNumberGetValue (refUsage, kCFNumberLongType, &usage)) - { - switch (usagePage) /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ - { - case kHIDPage_GenericDesktop: - { - switch (usage) /* look at usage to determine function */ - { - case kHIDUsage_GD_X: - case kHIDUsage_GD_Y: - case kHIDUsage_GD_Z: - case kHIDUsage_GD_Rx: - case kHIDUsage_GD_Ry: - case kHIDUsage_GD_Rz: - case kHIDUsage_GD_Slider: - case kHIDUsage_GD_Dial: - case kHIDUsage_GD_Wheel: - element = (recElement *) NewPtrClear (sizeof (recElement)); - if (element) - { - pDevice->axes++; - headElement = &(pDevice->firstAxis); - } - break; - case kHIDUsage_GD_Hatswitch: - element = (recElement *) NewPtrClear (sizeof (recElement)); - if (element) - { - pDevice->hats++; - headElement = &(pDevice->firstHat); - } - break; - } - } - break; - case kHIDPage_Button: - element = (recElement *) NewPtrClear (sizeof (recElement)); - if (element) - { - pDevice->buttons++; - headElement = &(pDevice->firstButton); - } - break; - default: - break; - } - } - } - else if (kIOHIDElementTypeCollection == elementType) - HIDGetCollectionElements ((CFMutableDictionaryRef) refElement, pDevice); - } - - if (element && headElement) /* add to list */ - { - pDevice->elements++; - if (NULL == *headElement) - *headElement = element; - else - { - recElement *elementPrevious, *elementCurrent; - elementCurrent = *headElement; - while (elementCurrent) - { - elementPrevious = elementCurrent; - elementCurrent = elementPrevious->pNext; - } - elementPrevious->pNext = element; - } - element->pNext = NULL; - HIDGetElementInfo (refElement, element); - } + recElement *element = NULL; + recElement **headElement = NULL; + long elementType, usagePage, usage; + CFTypeRef refElementType = + CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementTypeKey)); + CFTypeRef refUsagePage = + CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsagePageKey)); + CFTypeRef refUsage = + CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsageKey)); + + + if ((refElementType) + && + (CFNumberGetValue(refElementType, kCFNumberLongType, &elementType))) { + /* look at types of interest */ + if ((elementType == kIOHIDElementTypeInput_Misc) + || (elementType == kIOHIDElementTypeInput_Button) + || (elementType == kIOHIDElementTypeInput_Axis)) { + if (refUsagePage + && CFNumberGetValue(refUsagePage, kCFNumberLongType, + &usagePage) && refUsage + && CFNumberGetValue(refUsage, kCFNumberLongType, &usage)) { + switch (usagePage) { /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ + case kHIDPage_GenericDesktop: + { + switch (usage) { /* look at usage to determine function */ + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: + case kHIDUsage_GD_Dial: + case kHIDUsage_GD_Wheel: + element = (recElement *) + NewPtrClear(sizeof(recElement)); + if (element) { + pDevice->axes++; + headElement = &(pDevice->firstAxis); + } + break; + case kHIDUsage_GD_Hatswitch: + element = (recElement *) + NewPtrClear(sizeof(recElement)); + if (element) { + pDevice->hats++; + headElement = &(pDevice->firstHat); + } + break; + } + } + break; + case kHIDPage_Button: + element = (recElement *) + NewPtrClear(sizeof(recElement)); + if (element) { + pDevice->buttons++; + headElement = &(pDevice->firstButton); + } + break; + default: + break; + } + } + } else if (kIOHIDElementTypeCollection == elementType) + HIDGetCollectionElements((CFMutableDictionaryRef) refElement, + pDevice); + } + + if (element && headElement) { /* add to list */ + recElement *elementPrevious = NULL; + recElement *elementCurrent = *headElement; + while (elementCurrent && usage >= elementCurrent->usage) { + elementPrevious = elementCurrent; + elementCurrent = elementCurrent->pNext; + } + if (elementPrevious) { + elementPrevious->pNext = element; + } else { + *headElement = element; + } + element->usagePage = usagePage; + element->usage = usage; + element->pNext = elementCurrent; + HIDGetElementInfo(refElement, element); + pDevice->elements++; + } } /* collects information from each array member in device element list (each array memeber = element) */ -static void HIDGetElementsCFArrayHandler (const void * value, void * parameter) +static void +HIDGetElementsCFArrayHandler(const void *value, void *parameter) { - if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) - HIDAddElement ((CFTypeRef) value, (recDevice *) parameter); + if (CFGetTypeID(value) == CFDictionaryGetTypeID()) + HIDAddElement((CFTypeRef) value, (recDevice *) parameter); } /* handles retrieval of element information from arrays of elements in device IO registry information */ -static void HIDGetElements (CFTypeRef refElementCurrent, recDevice *pDevice) +static void +HIDGetElements(CFTypeRef refElementCurrent, recDevice * pDevice) { - CFTypeID type = CFGetTypeID (refElementCurrent); - if (type == CFArrayGetTypeID()) /* if element is an array */ - { - CFRange range = {0, CFArrayGetCount (refElementCurrent)}; - /* CountElementsCFArrayHandler called for each array member */ - CFArrayApplyFunction (refElementCurrent, range, HIDGetElementsCFArrayHandler, pDevice); - } -} + CFTypeID type = CFGetTypeID(refElementCurrent); + if (type == CFArrayGetTypeID()) { /* if element is an array */ + CFRange range = { 0, CFArrayGetCount(refElementCurrent) }; + /* CountElementsCFArrayHandler called for each array member */ + CFArrayApplyFunction(refElementCurrent, range, + HIDGetElementsCFArrayHandler, pDevice); + } +} /* handles extracting element information from element collection CF types * used from top level element decoding and hierarchy deconstruction to flatten device element list */ -static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice) +static void +HIDGetCollectionElements(CFMutableDictionaryRef deviceProperties, + recDevice * pDevice) { - CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); - if (refElementTop) - HIDGetElements (refElementTop, pDevice); + CFTypeRef refElementTop = + CFDictionaryGetValue(deviceProperties, CFSTR(kIOHIDElementKey)); + if (refElementTop) + HIDGetElements(refElementTop, pDevice); } /* use top level element usage page and usage to discern device usage page and usage setting appropriate vlaues in device record */ -static void HIDTopLevelElementHandler (const void * value, void * parameter) +static void +HIDTopLevelElementHandler(const void *value, void *parameter) { - CFTypeRef refCF = 0; - if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) - return; - refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); - if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usagePage)) - SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); - refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); - if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usage)) - SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); + CFTypeRef refCF = 0; + if (CFGetTypeID(value) != CFDictionaryGetTypeID()) + return; + refCF = CFDictionaryGetValue(value, CFSTR(kIOHIDElementUsagePageKey)); + if (!CFNumberGetValue + (refCF, kCFNumberLongType, &((recDevice *) parameter)->usagePage)) + SDL_SetError("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = CFDictionaryGetValue(value, CFSTR(kIOHIDElementUsageKey)); + if (!CFNumberGetValue + (refCF, kCFNumberLongType, &((recDevice *) parameter)->usage)) + SDL_SetError("CFNumberGetValue error retrieving pDevice->usage."); } /* extracts device info from CF dictionary records in IO registry */ -static void HIDGetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, recDevice *pDevice) +static void +HIDGetDeviceInfo(io_object_t hidDevice, CFMutableDictionaryRef hidProperties, + recDevice * pDevice) { - CFMutableDictionaryRef usbProperties = 0; - io_registry_entry_t parent1, parent2; - - /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also - * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties - */ - if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && - (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && - (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) - { - if (usbProperties) - { - CFTypeRef refCF = 0; - /* get device info - * try hid dictionary first, if fail then go to usb dictionary - */ - - - /* get product name */ - refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); - if (!refCF) - refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); - if (refCF) - { - if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) - SDL_SetError ("CFStringGetCString error retrieving pDevice->product."); - } - - /* get usage page and usage */ - refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); - if (refCF) - { - if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) - SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); - refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); - if (refCF) - if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) - SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); - } - - if (NULL == refCF) /* get top level element HID usage page or usage */ - { - /* use top level element instead */ - CFTypeRef refCFTopElement = 0; - refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); - { - /* refCFTopElement points to an array of element dictionaries */ - CFRange range = {0, CFArrayGetCount (refCFTopElement)}; - CFArrayApplyFunction (refCFTopElement, range, HIDTopLevelElementHandler, pDevice); - } - } - - CFRelease (usbProperties); - } - else - SDL_SetError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); - - if (kIOReturnSuccess != IOObjectRelease (parent2)) - SDL_SetError ("IOObjectRelease error with parent2."); - if (kIOReturnSuccess != IOObjectRelease (parent1)) - SDL_SetError ("IOObjectRelease error with parent1."); - } + CFMutableDictionaryRef usbProperties = 0; + io_registry_entry_t parent1, parent2; + + /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + */ + if ((KERN_SUCCESS == + IORegistryEntryGetParentEntry(hidDevice, kIOServicePlane, &parent1)) + && (KERN_SUCCESS == + IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2)) + && (KERN_SUCCESS == + IORegistryEntryCreateCFProperties(parent2, &usbProperties, + kCFAllocatorDefault, + kNilOptions))) { + if (usbProperties) { + CFTypeRef refCF = 0; + /* get device info + * try hid dictionary first, if fail then go to usb dictionary + */ + + + /* get product name */ + refCF = + CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey)); + if (!refCF) + refCF = + CFDictionaryGetValue(usbProperties, + CFSTR("USB Product Name")); + if (refCF) { + if (!CFStringGetCString + (refCF, pDevice->product, 256, + CFStringGetSystemEncoding())) + SDL_SetError + ("CFStringGetCString error retrieving pDevice->product."); + } + + /* get usage page and usage */ + refCF = + CFDictionaryGetValue(hidProperties, + CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) { + if (!CFNumberGetValue + (refCF, kCFNumberLongType, &pDevice->usagePage)) + SDL_SetError + ("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = + CFDictionaryGetValue(hidProperties, + CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) + if (!CFNumberGetValue + (refCF, kCFNumberLongType, &pDevice->usage)) + SDL_SetError + ("CFNumberGetValue error retrieving pDevice->usage."); + } + + if (NULL == refCF) { /* get top level element HID usage page or usage */ + /* use top level element instead */ + CFTypeRef refCFTopElement = 0; + refCFTopElement = + CFDictionaryGetValue(hidProperties, + CFSTR(kIOHIDElementKey)); + { + /* refCFTopElement points to an array of element dictionaries */ + CFRange range = { 0, CFArrayGetCount(refCFTopElement) }; + CFArrayApplyFunction(refCFTopElement, range, + HIDTopLevelElementHandler, pDevice); + } + } + + CFRelease(usbProperties); + } else + SDL_SetError + ("IORegistryEntryCreateCFProperties failed to create usbProperties."); + + if (kIOReturnSuccess != IOObjectRelease(parent2)) + SDL_SetError("IOObjectRelease error with parent2."); + if (kIOReturnSuccess != IOObjectRelease(parent1)) + SDL_SetError("IOObjectRelease error with parent1."); + } } -static recDevice *HIDBuildDevice (io_object_t hidDevice) +static recDevice * +HIDBuildDevice(io_object_t hidDevice) { - recDevice *pDevice = (recDevice *) NewPtrClear (sizeof (recDevice)); - if (pDevice) - { - /* get dictionary for HID properties */ - CFMutableDictionaryRef hidProperties = 0; - kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); - if ((result == KERN_SUCCESS) && hidProperties) - { - /* create device interface */ - result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); - if (kIOReturnSuccess == result) - { - HIDGetDeviceInfo (hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */ - HIDGetCollectionElements (hidProperties, pDevice); - } - else - { - DisposePtr((Ptr)pDevice); - pDevice = NULL; - } - CFRelease (hidProperties); - } - else - { - DisposePtr((Ptr)pDevice); - pDevice = NULL; - } - } - return pDevice; + recDevice *pDevice = (recDevice *) NewPtrClear(sizeof(recDevice)); + if (pDevice) { + /* get dictionary for HID properties */ + CFMutableDictionaryRef hidProperties = 0; + kern_return_t result = + IORegistryEntryCreateCFProperties(hidDevice, &hidProperties, + kCFAllocatorDefault, + kNilOptions); + if ((result == KERN_SUCCESS) && hidProperties) { + /* create device interface */ + result = HIDCreateOpenDeviceInterface(hidDevice, pDevice); + if (kIOReturnSuccess == result) { + HIDGetDeviceInfo(hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */ + HIDGetCollectionElements(hidProperties, pDevice); + } else { + DisposePtr((Ptr) pDevice); + pDevice = NULL; + } + CFRelease(hidProperties); + } else { + DisposePtr((Ptr) pDevice); + pDevice = NULL; + } + } + return pDevice; } /* disposes of the element list associated with a device and the memory associated with the list */ -static void HIDDisposeElementList (recElement **elementList) +static void +HIDDisposeElementList(recElement ** elementList) { - recElement *pElement = *elementList; - while (pElement) - { - recElement *pElementNext = pElement->pNext; - DisposePtr ((Ptr) pElement); - pElement = pElementNext; - } - *elementList = NULL; + recElement *pElement = *elementList; + while (pElement) { + recElement *pElementNext = pElement->pNext; + DisposePtr((Ptr) pElement); + pElement = pElementNext; + } + *elementList = NULL; } /* disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL * all your device no longer belong to us... (i.e., you do not 'own' the device anymore) */ -static recDevice *HIDDisposeDevice (recDevice **ppDevice) +static recDevice * +HIDDisposeDevice(recDevice ** ppDevice) { - kern_return_t result = KERN_SUCCESS; - recDevice *pDeviceNext = NULL; - if (*ppDevice) - { - /* save next device prior to disposing of this device */ - pDeviceNext = (*ppDevice)->pNext; - - /* free element lists */ - HIDDisposeElementList (&(*ppDevice)->firstAxis); - HIDDisposeElementList (&(*ppDevice)->firstButton); - HIDDisposeElementList (&(*ppDevice)->firstHat); - - result = HIDCloseReleaseInterface (*ppDevice); /* function sanity checks interface value (now application does not own device) */ - if (kIOReturnSuccess != result) - HIDReportErrorNum ("HIDCloseReleaseInterface failed when trying to dipose device.", result); - DisposePtr ((Ptr)*ppDevice); - *ppDevice = NULL; - } - return pDeviceNext; + kern_return_t result = KERN_SUCCESS; + recDevice *pDeviceNext = NULL; + if (*ppDevice) { + /* save next device prior to disposing of this device */ + pDeviceNext = (*ppDevice)->pNext; + + /* free posible io_service_t */ + if ((*ppDevice)->ffservice) { + IOObjectRelease((*ppDevice)->ffservice); + (*ppDevice)->ffservice = 0; + } + + /* free element lists */ + HIDDisposeElementList(&(*ppDevice)->firstAxis); + HIDDisposeElementList(&(*ppDevice)->firstButton); + HIDDisposeElementList(&(*ppDevice)->firstHat); + + result = HIDCloseReleaseInterface(*ppDevice); /* function sanity checks interface value (now application does not own device) */ + if (kIOReturnSuccess != result) + HIDReportErrorNum + ("HIDCloseReleaseInterface failed when trying to dipose device.", + result); + DisposePtr((Ptr) * ppDevice); + *ppDevice = NULL; + } + return pDeviceNext; } @@ -570,127 +575,125 @@ static recDevice *HIDDisposeDevice (recDevice **ppDevice) * This function should return the number of available joysticks, or -1 * on an unrecoverable fatal error. */ -int SDL_SYS_JoystickInit(void) +int +SDL_SYS_JoystickInit(void) { - IOReturn result = kIOReturnSuccess; - mach_port_t masterPort = 0; - io_iterator_t hidObjectIterator = 0; - CFMutableDictionaryRef hidMatchDictionary = NULL; - recDevice *device, *lastDevice; - io_object_t ioHIDDeviceObject = 0; - - SDL_numjoysticks = 0; - - if (gpDeviceList) - { - SDL_SetError("Joystick: Device list already inited."); - return -1; - } - - result = IOMasterPort (bootstrap_port, &masterPort); - if (kIOReturnSuccess != result) - { - SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); - return -1; - } - - /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ - hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); - if (hidMatchDictionary) - { - /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ - - /* NOTE: we now perform this filtering later - UInt32 usagePage = kHIDPage_GenericDesktop; - UInt32 usage = kHIDUsage_GD_Joystick; - CFNumberRef refUsage = NULL, refUsagePage = NULL; - - refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); - refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); - CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); - */ - } - else - { - SDL_SetError("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); - return -1; - } - - /*/ Now search I/O Registry for matching devices. */ - result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); - /* Check for errors */ - if (kIOReturnSuccess != result) - { - SDL_SetError("Joystick: Couldn't create a HID object iterator."); - return -1; - } - if (!hidObjectIterator) /* there are no joysticks */ - { - gpDeviceList = NULL; - SDL_numjoysticks = 0; - return 0; - } - /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ - - /* build flat linked list of devices from device iterator */ - - gpDeviceList = lastDevice = NULL; - - while ((ioHIDDeviceObject = IOIteratorNext (hidObjectIterator))) - { - /* build a device record */ - device = HIDBuildDevice (ioHIDDeviceObject); - if (!device) - continue; - - /* dump device object, it is no longer needed */ - result = IOObjectRelease (ioHIDDeviceObject); -/* if (KERN_SUCCESS != result) - HIDReportErrorNum ("IOObjectRelease error with ioHIDDeviceObject.", result); -*/ - - /* Filter device list to non-keyboard/mouse stuff */ - if ( (device->usagePage != kHIDPage_GenericDesktop) || - ((device->usage != kHIDUsage_GD_Joystick && - device->usage != kHIDUsage_GD_GamePad && - device->usage != kHIDUsage_GD_MultiAxisController)) ) { - - /* release memory for the device */ - HIDDisposeDevice (&device); - DisposePtr((Ptr)device); - continue; - } - - /* Add device to the end of the list */ - if (lastDevice) - lastDevice->pNext = device; - else - gpDeviceList = device; - lastDevice = device; - } - result = IOObjectRelease (hidObjectIterator); /* release the iterator */ - - /* Count the total number of devices we found */ - device = gpDeviceList; - while (device) - { - SDL_numjoysticks++; - device = device->pNext; - } - - return SDL_numjoysticks; + IOReturn result = kIOReturnSuccess; + mach_port_t masterPort = 0; + io_iterator_t hidObjectIterator = 0; + CFMutableDictionaryRef hidMatchDictionary = NULL; + recDevice *device, *lastDevice; + io_object_t ioHIDDeviceObject = 0; + + SDL_numjoysticks = 0; + + if (gpDeviceList) { + SDL_SetError("Joystick: Device list already inited."); + return -1; + } + + result = IOMasterPort(bootstrap_port, &masterPort); + if (kIOReturnSuccess != result) { + SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); + return -1; + } + + /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ + hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); + if (hidMatchDictionary) { + /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ + + /* NOTE: we now perform this filtering later + UInt32 usagePage = kHIDPage_GenericDesktop; + UInt32 usage = kHIDUsage_GD_Joystick; + CFNumberRef refUsage = NULL, refUsagePage = NULL; + + refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); + refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); + */ + } else { + SDL_SetError + ("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); + return -1; + } + + /*/ Now search I/O Registry for matching devices. */ + result = + IOServiceGetMatchingServices(masterPort, hidMatchDictionary, + &hidObjectIterator); + /* Check for errors */ + if (kIOReturnSuccess != result) { + SDL_SetError("Joystick: Couldn't create a HID object iterator."); + return -1; + } + if (!hidObjectIterator) { /* there are no joysticks */ + gpDeviceList = NULL; + SDL_numjoysticks = 0; + return 0; + } + /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ + + /* build flat linked list of devices from device iterator */ + + gpDeviceList = lastDevice = NULL; + + while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) { + /* build a device record */ + device = HIDBuildDevice(ioHIDDeviceObject); + if (!device) + continue; + + /* Filter device list to non-keyboard/mouse stuff */ + if ((device->usagePage != kHIDPage_GenericDesktop) || + ((device->usage != kHIDUsage_GD_Joystick && + device->usage != kHIDUsage_GD_GamePad && + device->usage != kHIDUsage_GD_MultiAxisController))) { + + /* release memory for the device */ + HIDDisposeDevice(&device); + DisposePtr((Ptr) device); + continue; + } + + /* We have to do some storage of the io_service_t for + * SDL_HapticOpenFromJoystick */ + if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) { + device->ffservice = ioHIDDeviceObject; + } else { + device->ffservice = 0; + } + + /* Add device to the end of the list */ + if (lastDevice) + lastDevice->pNext = device; + else + gpDeviceList = device; + lastDevice = device; + } + result = IOObjectRelease(hidObjectIterator); /* release the iterator */ + + /* Count the total number of devices we found */ + device = gpDeviceList; + while (device) { + SDL_numjoysticks++; + device = device->pNext; + } + + return SDL_numjoysticks; } /* Function to get the device-dependent name of a joystick */ -const char *SDL_SYS_JoystickName(int index) +const char * +SDL_SYS_JoystickName(int index) { - recDevice *device = gpDeviceList; - - for (; index > 0; index--) - device = device->pNext; + recDevice *device = gpDeviceList; - return device->product; + for (; index > 0; index--) + device = device->pNext; + + return device->product; } /* Function to open a joystick for use. @@ -698,23 +701,24 @@ const char *SDL_SYS_JoystickName(int index) * This should fill the nbuttons and naxes fields of the joystick structure. * It returns 0, or -1 if there is an error. */ -int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +int +SDL_SYS_JoystickOpen(SDL_Joystick * joystick) { - recDevice *device = gpDeviceList; - int index; - - for (index = joystick->index; index > 0; index--) - device = device->pNext; + recDevice *device = gpDeviceList; + int index; + + for (index = joystick->index; index > 0; index--) + device = device->pNext; - joystick->hwdata = device; - joystick->name = device->product; + joystick->hwdata = device; + joystick->name = device->product; - joystick->naxes = device->axes; - joystick->nhats = device->hats; - joystick->nballs = 0; - joystick->nbuttons = device->buttons; + joystick->naxes = device->axes; + joystick->nhats = device->hats; + joystick->nballs = 0; + joystick->nbuttons = device->buttons; - return 0; + return 0; } /* Function to update the state of a joystick - called as a device poll. @@ -722,124 +726,122 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ -void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +void +SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { - recDevice *device = joystick->hwdata; - recElement *element; - SInt32 value, range; - int i; - - if (device->removed) /* device was unplugged; ignore it. */ - { - if (device->uncentered) - { - device->uncentered = 0; - - /* Tell the app that everything is centered/unpressed... */ - for (i = 0; i < device->axes; i++) - SDL_PrivateJoystickAxis(joystick, i, 0); - - for (i = 0; i < device->buttons; i++) - SDL_PrivateJoystickButton(joystick, i, 0); - - for (i = 0; i < device->hats; i++) - SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); - } - - return; - } - - element = device->firstAxis; - i = 0; - while (element) - { - value = HIDScaledCalibratedValue(device, element, -32768, 32767); - if ( value != joystick->axes[i] ) - SDL_PrivateJoystickAxis(joystick, i, value); - element = element->pNext; - ++i; - } - - element = device->firstButton; - i = 0; - while (element) - { - value = HIDGetElementValue(device, element); - if (value > 1) /* handle pressure-sensitive buttons */ + recDevice *device = joystick->hwdata; + recElement *element; + SInt32 value, range; + int i; + + if (device->removed) { /* device was unplugged; ignore it. */ + if (device->uncentered) { + device->uncentered = 0; + + /* Tell the app that everything is centered/unpressed... */ + for (i = 0; i < device->axes; i++) + SDL_PrivateJoystickAxis(joystick, i, 0); + + for (i = 0; i < device->buttons; i++) + SDL_PrivateJoystickButton(joystick, i, 0); + + for (i = 0; i < device->hats; i++) + SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); + } + + return; + } + + element = device->firstAxis; + i = 0; + while (element) { + value = HIDScaledCalibratedValue(device, element, -32768, 32767); + if (value != joystick->axes[i]) + SDL_PrivateJoystickAxis(joystick, i, value); + element = element->pNext; + ++i; + } + + element = device->firstButton; + i = 0; + while (element) { + value = HIDGetElementValue(device, element); + if (value > 1) /* handle pressure-sensitive buttons */ value = 1; - if ( value != joystick->buttons[i] ) - SDL_PrivateJoystickButton(joystick, i, value); - element = element->pNext; - ++i; - } - - element = device->firstHat; - i = 0; - while (element) - { - Uint8 pos = 0; - - range = (element->max - element->min + 1); - value = HIDGetElementValue(device, element) - element->min; - if (range == 4) /* 4 position hatswitch - scale up value */ - value *= 2; - else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ - value = -1; - switch(value) - { - case 0: - pos = SDL_HAT_UP; - break; - case 1: - pos = SDL_HAT_RIGHTUP; - break; - case 2: - pos = SDL_HAT_RIGHT; - break; - case 3: - pos = SDL_HAT_RIGHTDOWN; - break; - case 4: - pos = SDL_HAT_DOWN; - break; - case 5: - pos = SDL_HAT_LEFTDOWN; - break; - case 6: - pos = SDL_HAT_LEFT; - break; - case 7: - pos = SDL_HAT_LEFTUP; - break; - default: - /* Every other value is mapped to center. We do that because some - * joysticks use 8 and some 15 for this value, and apparently - * there are even more variants out there - so we try to be generous. - */ - pos = SDL_HAT_CENTERED; - break; - } - if ( pos != joystick->hats[i] ) - SDL_PrivateJoystickHat(joystick, i, pos); - element = element->pNext; - ++i; - } - - return; + if (value != joystick->buttons[i]) + SDL_PrivateJoystickButton(joystick, i, value); + element = element->pNext; + ++i; + } + + element = device->firstHat; + i = 0; + while (element) { + Uint8 pos = 0; + + range = (element->max - element->min + 1); + value = HIDGetElementValue(device, element) - element->min; + if (range == 4) /* 4 position hatswitch - scale up value */ + value *= 2; + else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ + value = -1; + switch (value) { + case 0: + pos = SDL_HAT_UP; + break; + case 1: + pos = SDL_HAT_RIGHTUP; + break; + case 2: + pos = SDL_HAT_RIGHT; + break; + case 3: + pos = SDL_HAT_RIGHTDOWN; + break; + case 4: + pos = SDL_HAT_DOWN; + break; + case 5: + pos = SDL_HAT_LEFTDOWN; + break; + case 6: + pos = SDL_HAT_LEFT; + break; + case 7: + pos = SDL_HAT_LEFTUP; + break; + default: + /* Every other value is mapped to center. We do that because some + * joysticks use 8 and some 15 for this value, and apparently + * there are even more variants out there - so we try to be generous. + */ + pos = SDL_HAT_CENTERED; + break; + } + if (pos != joystick->hats[i]) + SDL_PrivateJoystickHat(joystick, i, pos); + element = element->pNext; + ++i; + } + + return; } /* Function to close a joystick after use */ -void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +void +SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - /* Should we do anything here? */ - return; + /* Should we do anything here? */ + return; } /* Function to perform any system-specific joystick related cleanup */ -void SDL_SYS_JoystickQuit(void) +void +SDL_SYS_JoystickQuit(void) { - while (NULL != gpDeviceList) - gpDeviceList = HIDDisposeDevice (&gpDeviceList); + while (NULL != gpDeviceList) + gpDeviceList = HIDDisposeDevice(&gpDeviceList); } #endif /* SDL_JOYSTICK_IOKIT */ +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick_c.h b/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick_c.h new file mode 100644 index 00000000..d413f336 --- /dev/null +++ b/macosx/plugins/DFInput/SDL/src/joystick/darwin/SDL_sysjoystick_c.h @@ -0,0 +1,88 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_JOYSTICK_IOKIT_H + + +#if MAC_OS_X_VERSION_MIN_REQUIRED == 1030 +#include "10.3.9-FIX/IOHIDLib.h" +#else +#include <IOKit/hid/IOHIDLib.h> +#endif +#include <IOKit/hid/IOHIDKeys.h> + + +struct recElement +{ + IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */ + long usagePage, usage; /* HID usage */ + long min; /* reported min value possible */ + long max; /* reported max value possible */ +#if 0 + /* TODO: maybe should handle the following stuff somehow? */ + + long scaledMin; /* reported scaled min value possible */ + long scaledMax; /* reported scaled max value possible */ + long size; /* size in bits of data return from element */ + Boolean relative; /* are reports relative to last report (deltas) */ + Boolean wrapping; /* does element wrap around (one value higher than max is min) */ + Boolean nonLinear; /* are the values reported non-linear relative to element movement */ + Boolean preferredState; /* does element have a preferred state (such as a button) */ + Boolean nullState; /* does element have null state */ +#endif /* 0 */ + + /* runtime variables used for auto-calibration */ + long minReport; /* min returned value */ + long maxReport; /* max returned value */ + + struct recElement *pNext; /* next element in list */ +}; +typedef struct recElement recElement; + +struct joystick_hwdata +{ + io_service_t ffservice; /* Interface for force feedback, 0 = no ff */ + IOHIDDeviceInterface **interface; /* interface to device, NULL = no interface */ + + char product[256]; /* name of product */ + long usage; /* usage page from IOUSBHID Parser.h which defines general usage */ + long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ + + long axes; /* number of axis (calculated, not reported by device) */ + long buttons; /* number of buttons (calculated, not reported by device) */ + long hats; /* number of hat switches (calculated, not reported by device) */ + long elements; /* number of total elements (shouldbe total of above) (calculated, not reported by device) */ + + recElement *firstAxis; + recElement *firstButton; + recElement *firstHat; + + int removed; + int uncentered; + + struct joystick_hwdata *pNext; /* next device */ +}; +typedef struct joystick_hwdata recDevice; + + +#endif /* SDL_JOYSTICK_IOKIT_H */ |
