From 5bc44151e820716f1511302ba6239ae0dd8d1265 Mon Sep 17 00:00:00 2001 From: Edgar Simo Date: Thu, 17 Jul 2008 11:47:48 +0000 Subject: [PATCH] Haptic subsystem handles haptic axes now. Support for SDL_HAPTIC_SPHERICAL on linux. More error checking. Improved documentation. Added missing SDLCALLs to SDL_haptic.h. --- include/SDL_haptic.h | 142 ++++++++++++++++++------------- src/haptic/SDL_haptic.c | 14 +++ src/haptic/SDL_syshaptic.h | 1 + src/haptic/linux/SDL_syshaptic.c | 11 +++ 4 files changed, 110 insertions(+), 58 deletions(-) diff --git a/include/SDL_haptic.h b/include/SDL_haptic.h index 48030b3e8..c2eda2fa5 100644 --- a/include/SDL_haptic.h +++ b/include/SDL_haptic.h @@ -292,36 +292,37 @@ typedef struct _SDL_Haptic SDL_Haptic; * Directions can be specified by: * - SDL_HAPTIC_POLAR : Specified by polar coordinates. * - SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates. + * - SDL_HAPTIC_SHPERICAL : Specified by spherical coordinates. * * Cardinal directions of the haptic device are relative to the positioning * of the device. North is considered to be away from the user. * * The following diagram represents the cardinal directions: * \code - * .--. - * |__| .-------. - * |=.| |.-----.| - * |--| || || - * | | |'-----'| - * |__|~')_____(' - * [ COMPUTER ] - * - * - * North (-1) - * ^ - * | - * | - * (1) West <----[ HAPTIC ]----> East (-1) - * | - * | - * v - * South (1) - * - * - * [ USER ] - * \|||/ - * (o o) - * ---ooO-(_)-Ooo--- + * .--. + * |__| .-------. + * |=.| |.-----.| + * |--| || || + * | | |'-----'| + * |__|~')_____(' + * [ COMPUTER ] + * + * + * North (0,-1) + * ^ + * | + * | + * (1,0) West <----[ HAPTIC ]----> East (-1,0) + * | + * | + * v + * South (0,1) + * + * + * [ USER ] + * \|||/ + * (o o) + * ---ooO-(_)-Ooo--- * \endcode * * If type is SDL_HAPTIC_POLAR, direction is encoded by hundredths of a @@ -332,35 +333,49 @@ typedef struct _SDL_Haptic SDL_Haptic; * - South: 18000 (180 degrees) * - West: 27000 (270 degrees) * - * If type is SDL_HAPTIC_CARTESIAN, direction is encoded by two positions - * (X axis and Y axis). SDL_HAPTIC_CARTESIAN uses the first two dir - * parameters. The cardinal directions would be: - * - North: 0,-1 - * - East: -1, 0 - * - South: 0, 1 - * - West: 1, 0 - * - * If type is SDL_HAPTIC_SPHERICAL, direction is encoded by three rotations. - * All three dir parameters are used. The dir parameters are as follows + * If type is SDL_HAPTIC_CARTESIAN, direction is encoded by three positions + * (X axis, Y axis and Z axis (with 3 axes)). SDL_HAPTIC_CARTESIAN uses + * the first three dir parameters. The cardinal directions would be: + * - North: 0,-1, 0 + * - East: -1, 0, 0 + * - South: 0, 1, 0 + * - West: 1, 0, 0 + * The Z axis represents the height of the effect if supported, otherwise + * it's unused. In cartesian encoding (1,2) would be the same as (2,4), you + * can use any multiple you want, only the direction matters. + * + * If type is SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations. + * The first two dir parameters are used. The dir parameters are as follows * (all values are in hundredths of degrees): * 1) Degrees from (1, 0) rotated towards (0, 1). * 2) Degrees towards (0, 0, 1) (device needs at least 3 axes). - * 3) Degrees tworads (0, 0, 0, 1) (device needs at least 4 axes). * * - * Example: + * Example of force coming from the south with all encodings (force coming + * from the south means the user will have to pull the stick to counteract): * \code * SDL_HapticDirection direction; * + * // Cartesian directions + * direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding. + * direction.dir[0] = 0; // X position + * direction.dir[1] = 1; // Y position + * // Assuming the device has 2 axes, we don't need to specify third parameter. + * + * // Polar directions * direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding. - * direction.dir = 18000; // Force comes from the south meaning the user will - * // have to pull the stick to counteract. + * direction.dir[0] = 18000; // Polar only uses first parameter + * + * // Spherical coordinates + * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding + * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters. * \endcode * * \sa SDL_HAPTIC_POLAR * \sa SDL_HAPTIC_CARTESIAN * \sa SDL_HAPTIC_SHPERICAL * \sa SDL_HapticEffect + * \sa SDL_HapticNumAxes */ typedef struct SDL_HapticDirection { Uint8 type; /**< The type of encoding. */ @@ -510,6 +525,7 @@ typedef struct SDL_HapticCondition { /* Header */ Uint16 type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER, SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION */ + SDL_HapticDirection direction; /**< Direction of the effect - Not used ATM. */ /* Replay */ Uint32 length; /**< Duration of the effect. */ @@ -679,7 +695,7 @@ extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index); * \sa SDL_HapticSetGain * \sa SDL_HapticSetAutocenter */ -extern DECLSPEC SDL_Haptic * SDL_HapticOpen(int device_index); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index); /** * \fn int SDL_HapticOpened(int device_index) @@ -692,7 +708,7 @@ extern DECLSPEC SDL_Haptic * SDL_HapticOpen(int device_index); * \sa SDL_HapticOpen * \sa SDL_HapticIndex */ -extern DECLSPEC int SDL_HapticOpened(int device_index); +extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index); /** * \fn int SDL_HapticIndex(SDL_Haptic * haptic) @@ -705,7 +721,7 @@ extern DECLSPEC int SDL_HapticOpened(int device_index); * \sa SDL_HapticOpen * \sa SDL_HapticOpened */ -extern DECLSPEC int SDL_HapticIndex(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic); /** * \fn int SDL_MouseIsHaptic(void) @@ -716,7 +732,7 @@ extern DECLSPEC int SDL_HapticIndex(SDL_Haptic * haptic); * * \sa SDL_HapticOpenFromMouse */ -extern DECLSPEC int SDL_MouseIsHaptic(void); +extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void); /** * \fn SDL_Haptic * SDL_HapticOpenFromMouse(void) @@ -728,7 +744,7 @@ extern DECLSPEC int SDL_MouseIsHaptic(void); * \sa SDL_MouseIsHaptic * \sa SDL_HapticOpen */ -extern DECLSPEC SDL_Haptic * SDL_HapticOpenFromMouse(void); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void); /** * \fn int SDL_JoystickIsHaptic(SDL_Joystick * joystick) @@ -741,7 +757,7 @@ extern DECLSPEC SDL_Haptic * SDL_HapticOpenFromMouse(void); * * \sa SDL_HapticOpenFromJoystick */ -extern DECLSPEC int SDL_JoystickIsHaptic(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick); /** * \fn SDL_Haptic * SDL_HapticOpenFromJoystick(SDL_Joystick * joystick) @@ -755,7 +771,7 @@ extern DECLSPEC int SDL_JoystickIsHaptic(SDL_Joystick * joystick); * \sa SDL_HapticOpen * \sa SDL_HapticClose */ -extern DECLSPEC SDL_Haptic * SDL_HapticOpenFromJoystick(SDL_Joystick * joystick); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick * joystick); /** * \fn void SDL_HapticClose(SDL_Haptic * haptic) @@ -764,7 +780,7 @@ extern DECLSPEC SDL_Haptic * SDL_HapticOpenFromJoystick(SDL_Joystick * joystick) * * \param haptic Haptic device to close. */ -extern DECLSPEC void SDL_HapticClose(SDL_Haptic * haptic); +extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic); /** * \fn int SDL_HapticNumEffects(SDL_Haptic * haptic) @@ -778,7 +794,7 @@ extern DECLSPEC void SDL_HapticClose(SDL_Haptic * haptic); * \sa SDL_HapticNumEffectsPlaying * \sa SDL_HapticQuery */ -extern DECLSPEC int SDL_HapticNumEffects(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic); /** * \fn int SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic) @@ -792,7 +808,7 @@ extern DECLSPEC int SDL_HapticNumEffects(SDL_Haptic * haptic); * \sa SDL_HapticNumEffects * \sa SDL_HapticQuery */ -extern DECLSPEC int SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); /** * \fn unsigned int SDL_HapticQuery(SDL_Haptic * haptic) @@ -813,7 +829,17 @@ extern DECLSPEC int SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); * \sa SDL_HapticNumEffects * \sa SDL_HapticEffectSupported */ -extern DECLSPEC unsigned int SDL_HapticQuery(SDL_Haptic * haptic); +extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic); + + +/** + * \fn int SDL_HapticNumAxes(SDL_Haptic * haptic) + * + * \brief Gets the number of haptic axes the device has. + * + * \sa SDL_HapticDirection + */ +extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic); /** * \fn int SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect) @@ -828,7 +854,7 @@ extern DECLSPEC unsigned int SDL_HapticQuery(SDL_Haptic * haptic); * \sa SDL_HapticQuery * \sa SDL_HapticNewEffect */ -extern DECLSPEC int SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect); +extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect); /** * \fn int SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect) @@ -843,7 +869,7 @@ extern DECLSPEC int SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEff * \sa SDL_HapticRunEffect * \sa SDL_HapticDestroyEffect */ -extern DECLSPEC int SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect); +extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect); /** * \fn int SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data) @@ -862,7 +888,7 @@ extern DECLSPEC int SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * * \sa SDL_HapticRunEffect * \sa SDL_HapticDestroyEffect */ -extern DECLSPEC int SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data); +extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data); /** * \fn int SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, int iterations) @@ -879,7 +905,7 @@ extern DECLSPEC int SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_ * \sa SDL_HapticDestroyEffect * \sa SDL_HapticGetEffectStatus */ -extern DECLSPEC int SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 iterations); +extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 iterations); /** * \fn int SDL_HapticStopEffect(SDL_Haptic * haptic, int effect) @@ -893,7 +919,7 @@ extern DECLSPEC int SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 * \sa SDL_HapticRunEffect * \sa SDL_HapticDestroyEffect */ -extern DECLSPEC int SDL_HapticStopEffect(SDL_Haptic * haptic, int effect); +extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic, int effect); /** * \fn void SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect) @@ -907,7 +933,7 @@ extern DECLSPEC int SDL_HapticStopEffect(SDL_Haptic * haptic, int effect); * * \sa SDL_HapticNewEffect */ -extern DECLSPEC void SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect); +extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect); /** * \fn int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect) @@ -924,7 +950,7 @@ extern DECLSPEC void SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect); * \sa SDL_HapticRunEffect * \sa SDL_HapticStopEffect */ -extern DECLSPEC int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect); +extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect); /** * \fn int SDL_HapticSetGain(SDL_Haptic * haptic, int gain) @@ -944,7 +970,7 @@ extern DECLSPEC int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect); * * \sa SDL_HapticQuery */ -extern DECLSPEC int SDL_HapticSetGain(SDL_Haptic * haptic, int gain); +extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain); /** * \fn int SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter) @@ -960,7 +986,7 @@ extern DECLSPEC int SDL_HapticSetGain(SDL_Haptic * haptic, int gain); * * \sa SDL_HapticQuery */ -extern DECLSPEC int SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter); +extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter); /* Ends C function definitions when using C++ */ diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index 38dbdb26a..dcacdd6bc 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -384,6 +384,20 @@ SDL_HapticQuery(SDL_Haptic * haptic) 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. */ diff --git a/src/haptic/SDL_syshaptic.h b/src/haptic/SDL_syshaptic.h index 777636be5..b8919bef2 100644 --- a/src/haptic/SDL_syshaptic.h +++ b/src/haptic/SDL_syshaptic.h @@ -49,6 +49,7 @@ struct _SDL_Haptic 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 */ diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 5000faefe..33d1c3d8e 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -255,6 +255,7 @@ SDL_SYS_HapticOpenFromFD(SDL_Haptic * haptic, int fd) /* Set the data */ haptic->hwdata->fd = fd; haptic->supported = EV_IsHaptic(fd); + haptic->naxes = 2; /* Hardcoded for now, not sure if it's possible to find out. */ /* Set the effects */ if (ioctl(fd, EVIOCGEFFECTS, &haptic->neffects) < 0) { @@ -419,6 +420,7 @@ SDL_SYS_ToDirection( SDL_HapticDirection * dir ) /* Linux directions are inverted. */ tmp = (((18000 + dir->dir[0]) % 36000) * 0xFFFF) / 36000; return (Uint16) tmp; + case SDL_HAPTIC_CARTESIAN: /* We must invert "x" and "y" to go clockwise. */ f = atan2(dir->dir[0], dir->dir[1]); @@ -426,7 +428,13 @@ SDL_SYS_ToDirection( SDL_HapticDirection * dir ) tmp = (tmp * 0xFFFF) / 36000; return (Uint16) tmp; + case SDL_HAPTIC_SPHERICAL: + tmp = (36000 - dir->dir[0]) + 27000; /* Convert to polars */ + tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; + return (Uint16) tmp; + default: + SDL_SetError("Haptic: Unsupported direction type."); return -1; } @@ -456,6 +464,7 @@ SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) /* Header */ dest->type = FF_CONSTANT; dest->direction = SDL_SYS_ToDirection(&constant->direction); + if (dest->direction < 0) return -1; /* Replay */ dest->replay.length = CLAMP(constant->length); @@ -486,6 +495,7 @@ SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) /* Header */ dest->type = FF_PERIODIC; dest->direction = SDL_SYS_ToDirection(&periodic->direction); + if (dest->direction < 0) return -1; /* Replay */ dest->replay.length = CLAMP(periodic->length); @@ -568,6 +578,7 @@ SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) /* Header */ dest->type = FF_RAMP; dest->direction = SDL_SYS_ToDirection(&ramp->direction); + if (dest->direction < 0) return -1; /* Replay */ dest->replay.length = CLAMP(ramp->length);