changeset 2480:b883974445fc gsoc2008_force_feedback

Some more error reporting. Added periodic effect. Confirmed it works.
author Edgar Simo <bobbens@gmail.com>
date Tue, 01 Jul 2008 09:22:22 +0000
parents b9eb2cfe16cd
children 5d0ea4576f20
files include/SDL_haptic.h src/haptic/SDL_haptic.c src/haptic/SDL_syshaptic.h src/haptic/linux/SDL_syshaptic.c
diffstat 4 files changed, 141 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/include/SDL_haptic.h	Mon Jun 30 21:38:29 2008 +0000
+++ b/include/SDL_haptic.h	Tue Jul 01 09:22:22 2008 +0000
@@ -60,15 +60,57 @@
 typedef struct SDL_HapticConstant {
    /* Header */
    Uint16 type;
+   Uint16 direction;
+
+   /* Replay */
    Uint16 length;
    Uint16 delay;
+
+   /* Trigger */
+   Uint16 button;
+   Uint16 interval;
+
+   /* Constant */
+   Sint16 level;
+
+   /* Envelope */
+   Uint16 attack_length;
+   Uint16 attack_level;
+   Uint16 fade_length;
+   Uint16 fade_level;
+} SDL_HapticConstant;
+typedef struct SDL_HapticPeriodic {
+   /* Header */
+   Uint16 type;
    Uint16 direction;
-} SDL_HapticConstant;
+
+   /* Replay */
+   Uint16 length;
+   Uint16 delay;
+
+   /* Trigger */
+   Uint16 button;
+   Uint16 interval;
+
+   /* Periodic */
+   Uint16 waveform;
+   Uint16 period;
+   Sint16 magnitude;
+   Sint16 offset;
+   Uint16 phase;
+
+   /* Envelope */
+   Uint16 attack_length;
+   Uint16 attack_level;
+   Uint16 fade_length;
+   Uint16 fade_level;
+} SDL_HapticPeriodic;
 
 typedef union SDL_HapticEffect {
    /* Common for all force feedback effects */
    Uint16 type; /* Effect type */
    SDL_HapticConstant constant; /* Constant effect */
+   SDL_HapticPeriodic periodic; /* Periodic effect */
 } SDL_HapticEffect;
 
 
--- a/src/haptic/SDL_haptic.c	Mon Jun 30 21:38:29 2008 +0000
+++ b/src/haptic/SDL_haptic.c	Tue Jul 01 09:22:22 2008 +0000
@@ -166,7 +166,12 @@
       return;
    }
 
-   /* Close it */
+   /* 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 */
@@ -248,12 +253,18 @@
       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]) != 0) {
+         if (SDL_SYS_HapticNewEffect(haptic,&haptic->effects[i],effect) != 0) {
             return -1; /* Backend failed to create effect */
          }
          return i;
@@ -265,12 +276,25 @@
 }
 
 /*
+ * Checks to see if an effect is valid.
+ */
+static int
+ValidEffect(SDL_Haptic * haptic, int effect)
+{
+   if ((effect < 0) || (effect >= haptic->neffects)) {
+      SDL_SetError("Invalid haptic effect identifier.");
+      return 0;
+   }
+   return 1;
+}
+
+/*
  * Runs the haptic effect on the device.
  */
 int
 SDL_HapticRunEffect(SDL_Haptic * haptic, int effect)
 {
-   if (!ValidHaptic(&haptic)) {
+   if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
       return -1;
    }
 
@@ -288,7 +312,7 @@
 void
 SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect)
 {
-   if (!ValidHaptic(&haptic)) {
+   if (!ValidHaptic(&haptic) || !ValidEffect(haptic,effect)) {
       return;
    }
 
--- a/src/haptic/SDL_syshaptic.h	Mon Jun 30 21:38:29 2008 +0000
+++ b/src/haptic/SDL_syshaptic.h	Tue Jul 01 09:22:22 2008 +0000
@@ -53,7 +53,7 @@
 extern void SDL_SYS_HapticClose(SDL_Haptic * haptic);
 extern void SDL_SYS_HapticQuit(void);
 extern int SDL_SYS_HapticNewEffect(SDL_Haptic * haptic,
-      struct haptic_effect * effect);
+      struct haptic_effect * effect, SDL_HapticEffect * base);
 extern int SDL_SYS_HapticRunEffect(SDL_Haptic * haptic,
       struct haptic_effect * effect);
 extern void SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic,
--- a/src/haptic/linux/SDL_syshaptic.c	Mon Jun 30 21:38:29 2008 +0000
+++ b/src/haptic/linux/SDL_syshaptic.c	Tue Jul 01 09:22:22 2008 +0000
@@ -35,6 +35,7 @@
 #include <fcntl.h>
 #include <linux/limits.h>
 #include <string.h>
+#include <errno.h>
 
 
 #define MAX_HAPTICS  32
@@ -274,12 +275,68 @@
  * Initializes the linux effect struct from a haptic_effect.
  */
 static int
-SDL_SYS_ToFFEffect( struct ff_effect * dest, struct haptic_effect * src )
+SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src )
 {
+   SDL_HapticConstant *constant;
+   SDL_HapticPeriodic *periodic;
+
+   /* Clear up */
    SDL_memset(dest, 0, sizeof(struct ff_effect));
-   switch (src->effect.type) {
+
+   switch (src->type) {
       case SDL_HAPTIC_CONSTANT:
+         constant = &src->constant;
+
+         /* Header */
          dest->type = FF_CONSTANT;
+         dest->direction = constant->direction;
+
+         /* Replay */
+         dest->replay.length = constant->length;
+         dest->replay.delay = constant->delay;
+
+         /* Trigger */
+         dest->trigger.button = constant->button;
+         dest->trigger.interval = constant->interval;
+
+         /* Constant */
+         dest->u.constant.level = constant->level;
+
+         /* Envelope */
+         dest->u.constant.envelope.attack_length = constant->attack_length;
+         dest->u.constant.envelope.attack_level = constant->attack_level;
+         dest->u.constant.envelope.fade_length = constant->fade_length;
+         dest->u.constant.envelope.fade_level = constant->fade_level;
+
+         break;
+
+      case SDL_HAPTIC_PERIODIC:
+         periodic = &src->periodic;
+
+         /* Header */
+         dest->type = FF_PERIODIC;
+         dest->direction = periodic->direction;
+         
+         /* Replay */
+         dest->replay.length = periodic->length;
+         dest->replay.delay = periodic->delay;
+         
+         /* Trigger */
+         dest->trigger.button = periodic->button;
+         dest->trigger.interval = periodic->interval;
+         
+         /* Constant */
+         dest->u.periodic.waveform = periodic->waveform;
+         dest->u.periodic.period = periodic->period;
+         dest->u.periodic.magnitude = periodic->magnitude;
+         dest->u.periodic.offset = periodic->offset;
+         dest->u.periodic.phase = periodic->phase;
+         
+         /* Envelope */
+         dest->u.periodic.envelope.attack_length = periodic->attack_length;
+         dest->u.periodic.envelope.attack_level = periodic->attack_level;
+         dest->u.periodic.envelope.fade_length = periodic->fade_length;
+         dest->u.periodic.envelope.fade_level = periodic->fade_level;
 
          break;
 
@@ -295,8 +352,11 @@
  * Creates a new haptic effect.
  */
 int
-SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect * effect)
+SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect * effect,
+      SDL_HapticEffect * base)
 {
+   struct ff_effect * linux_effect;
+
    /* Allocate the hardware effect */
    effect->hweffect = (struct haptic_hweffect *) 
          SDL_malloc(sizeof(struct haptic_hweffect));
@@ -306,14 +366,16 @@
    }
 
    /* Prepare the ff_effect */
-   if (SDL_SYS_ToFFEffect( &effect->hweffect->effect, effect ) != 0) {
+   linux_effect = &effect->hweffect->effect;
+   if (SDL_SYS_ToFFEffect( linux_effect, base ) != 0) {
       return -1;
    }
-   effect->hweffect->effect.id = -1; /* Have the kernel give it an id */
+   linux_effect->id = -1; /* Have the kernel give it an id */
 
    /* Upload the effect */
-   if (ioctl(haptic->hwdata->fd, EVIOCSFF, &effect->hweffect->effect) < 0) {
-      SDL_SetError("Error uploading effect to the haptic device.");
+   if (ioctl(haptic->hwdata->fd, EVIOCSFF, linux_effect) < 0) {
+      SDL_SetError("Error uploading effect to the haptic device: %s",
+            strerror(errno));
       return -1;
    }