[AD] Allegro haptics and linux drivers

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


This isa patch that adds the general support for force feedback /
haptic devices for allegro and Linux drivers. I rebased the previous
patch on the latest 5.1 branch and also cleaned it up a bit and passed
in through indent.

Kind Regards, B.
From b32613ec7336c1f9bc77e2fd1f8d0ef57339e39b Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Thu, 6 Jun 2013 20:31:16 +0200
Subject: [PATCH 01/10] Haptics or force feedback. A lot of boilerplate and
 some beginnings of a linux driver...

---
 cmake/FileList.cmake                       |    6 +-
 examples/CMakeLists.txt                    |    1 +
 examples/ex_haptic.c                       |   64 ++++
 include/allegro5/haptic.h                  |  183 ++++++++++++
 include/allegro5/internal/aintern_haptic.h |   87 ++++++
 include/allegro5/internal/aintern_system.h |    2 +
 include/allegro5/platform/aintunix.h       |    9 +
 lib/Headers/allegro5/haptic.h              |  183 ++++++++++++
 src/haptic.c                               |  239 +++++++++++++++
 src/linux/lhaptic.c                        |  439 ++++++++++++++++++++++++++++
 src/x/xsystem.c                            |    9 +
 11 files changed, 1221 insertions(+), 1 deletion(-)
 create mode 100644 examples/ex_haptic.c
 create mode 100644 include/allegro5/haptic.h
 create mode 100644 include/allegro5/internal/aintern_haptic.h
 create mode 100644 lib/Headers/allegro5/haptic.h
 create mode 100644 src/haptic.c
 create mode 100644 src/linux/lhaptic.c
 create mode 100644 src/macosx/ohaptic.m
 create mode 100644 src/win/whaptic.c

diff --git a/cmake/FileList.cmake b/cmake/FileList.cmake
index 3a33c50..12754f6 100644
--- a/cmake/FileList.cmake
+++ b/cmake/FileList.cmake
@@ -23,6 +23,7 @@ set(ALLEGRO_SRC_FILES
     src/fshook.c
     src/fshook_stdio.c
     src/fullscreen_mode.c
+    src/haptic.c
     src/inline.c
     src/joynu.c
     src/keybdnu.c
@@ -112,7 +113,8 @@ set(ALLEGRO_SRC_X_FILES
     src/x/xmousenu.c
     src/x/xrandr.c
     src/x/xsystem.c
-    src/x/xwindow.c
+    src/x/xwindow.c    
+    src/linux/lhaptic.c
     src/linux/ljoynu.c
     )
 
@@ -164,6 +166,7 @@ set(ALLEGRO_SRC_RASPBERRYPI_FILES
    src/linux/lkeybdnu.c
    src/linux/lmseev.c
    src/linux/lmsedrv.c
+   src/linux/lhaptic.c
    src/linux/ljoynu.c
    src/x/xevents.c
    src/x/xkeyboard.c
@@ -196,6 +199,7 @@ set(ALLEGRO_INCLUDE_ALLEGRO_FILES
     include/allegro5/fmaths.h
     include/allegro5/fshook.h
     include/allegro5/fullscreen_mode.h
+    include/allegro5/haptic.h
     include/allegro5/joystick.h
     include/allegro5/keyboard.h
     include/allegro5/keycodes.h
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index a9d4389..f45c0da 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -135,6 +135,7 @@ example(ex_fs_resize ${IMAGE} ${PRIM})
 example(ex_fs_window ${IMAGE} ${PRIM} ${FONT})
 example(ex_icon ${IMAGE})
 example(ex_icon2 ${IMAGE})
+example(ex_haptic ${PRIM})
 example(ex_joystick_events ${PRIM} ${FONT})
 example(ex_joystick_hotplugging ${PRIM})
 example(ex_keyboard_events)
diff --git a/examples/ex_haptic.c b/examples/ex_haptic.c
new file mode 100644
index 0000000..efaa0bf
--- /dev/null
+++ b/examples/ex_haptic.c
@@ -0,0 +1,64 @@
+/*
+ *    Example program for the Allegro library, by Peter Wang.
+ *
+ *    This program tests joystick events.
+ */
+
+#include <allegro5/allegro.h>
+#include <allegro5/haptic.h>
+#include <allegro5/allegro_primitives.h>
+
+#include "common.c"
+
+#define MAX_HAPTICS  32
+
+/* globals */
+ALLEGRO_EVENT_QUEUE  *event_queue;
+
+int num_haptics = 0;
+ALLEGRO_HAPTIC * haptics[MAX_HAPTICS];
+
+
+int main(void)
+{
+   int index;
+   ALLEGRO_DISPLAY *display;
+
+   if (!al_init()) {
+      abort_example("Could not init Allegro.\n");
+   }
+
+   display = al_create_display(640, 480);
+   if (!display) {
+      abort_example("al_create_display failed\n");
+   }
+
+   al_install_haptic();
+
+   event_queue = al_create_event_queue();
+   if (!event_queue) {
+      abort_example("al_create_event_queue failed\n");
+   }
+   open_log();
+   num_haptics = al_get_num_haptics();
+   log_printf("Found %d haptic devices.\n", num_haptics);
+   for(index = 0; index < num_haptics; index++) {
+     ALLEGRO_HAPTIC * hap = al_get_haptic(index);; 
+     haptics[index] = hap;
+     if (hap) {  
+      log_printf("Opened device %d: %s.\n", al_get_haptic_name(hap));
+     } else {
+      log_printf("Could not open haptic device %d.\n", index);
+     }
+   }
+   
+   
+   close_log(true);
+   // al_register_event_source(event_queue, al_get_display_event_source(display));
+   // al_register_event_source(event_queue, al_get_haptic_event_source());
+
+   
+   return 0;
+}
+
+/* vim: set ts=8 sts=3 sw=3 et: */
diff --git a/include/allegro5/haptic.h b/include/allegro5/haptic.h
new file mode 100644
index 0000000..3da4415
--- /dev/null
+++ b/include/allegro5/haptic.h
@@ -0,0 +1,183 @@
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      Haptic (that is, force feedback) routines for Allegro. 
+ *      By Beoran (beoran@xxxxxxxxx), 2013.
+ *
+ *      See readme.txt for copyright information.
+ */
+
+#ifndef __al_included_allegro5_haptic_h
+#define __al_included_allegro5_haptic_h
+
+#include "allegro5/base.h"
+#include "allegro5/events.h"
+#include "allegro5/mouse.h"
+#include "allegro5/joystick.h"
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+/* Enum: ALLEGRO_HAPTIC_FLAGS
+ */
+enum ALLEGRO_HAPTIC_FLAGS { 
+  ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
+  ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
+  ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
+  ALLEGRO_HAPTIC_SPRING       = 1 << 3,
+  ALLEGRO_HAPTIC_FRICTION     = 1 << 4,
+  ALLEGRO_HAPTIC_DAMPER       = 1 << 5,
+  ALLEGRO_HAPTIC_INERTIA      = 1 << 6,
+  ALLEGRO_HAPTIC_RAMP         = 1 << 7,
+  ALLEGRO_HAPTIC_SQUARE       = 1 << 8,
+  ALLEGRO_HAPTIC_TRIANGLE     = 1 << 9,
+  ALLEGRO_HAPTIC_SINE         = 1 << 10,
+  ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
+  ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
+  ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
+  ALLEGRO_HAPTIC_GAIN         = 1 << 14,  
+  ALLEGRO_HAPTIC_AUTOCENTER   = 1 << 15,  
+};
+
+
+/* Type: ALLEGRO_HAPTIC
+ */
+typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
+
+/* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
+ * An angle 0 means oriented towards the user, M_PI is away from the user 
+ * (towards the screen). 
+ * Radius (if supported ) is the diistance of the effect from the user 
+ * as a value between 0 and 1. Normally it is 0. 
+ * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
+ * horizontal plane, -M_PI points down, and M_PI points up.
+ * 
+ */
+struct ALLEGRO_HAPTIC_DIRECTION {
+  double angle; 
+  double radius;
+  double azimuth;
+};
+
+struct ALLEGRO_HAPTIC_REPLAY {
+    double length;
+    double delay;
+};
+
+struct ALLEGRO_HAPTIC_ENVELOPE {
+    double attack_length;
+    double attack_level;
+    double fade_length;
+    double fade_level;
+};
+
+struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
+    double level;
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+};
+
+struct ALLEGRO_HAPTIC_RAMP_EFFECT {
+    double start_level;
+    double end_level;
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+};
+
+struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
+    double right_saturation;
+    double left_saturation;
+    double right_coeff;
+    double left_coeff;
+    double deadband;
+    double center;
+};
+
+struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
+    int waveform;
+    double period;
+    double magnitude;
+    double offset;
+    double phase;
+    
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+    int    custom_len;
+    double *custom_data;
+};
+
+struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
+    double strong_magnitude;
+    double weak_magnitude;
+};
+
+union ALLEGRO_HAPTIC_EFFECT_UNION {
+    struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
+    struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
+    struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
+    struct ALLEGRO_HAPTIC_CONDITION_EFFECT  condition; 
+    struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
+};
+
+/* Type: ALLEGRO_HAPTIC_EFFECT
+ */
+struct ALLEGRO_HAPTIC_EFFECT {
+        int                                type;
+        int                                id;
+        struct ALLEGRO_HAPTIC_DIRECTION    direction;
+        struct ALLEGRO_HAPTIC_REPLAY       replay;
+        union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
+};
+
+
+/* Type: ALLEGRO_HAPTIC_EFFECT
+ */
+typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
+
+
+
+
+AL_FUNC(bool,             al_install_haptic          , (void));
+AL_FUNC(void,             al_uninstall_haptic        , (void));
+AL_FUNC(bool,             al_is_haptic_installed     , (void));
+AL_FUNC(bool,             al_reconfigure_haptic      , (void));
+
+AL_FUNC(int,              al_get_num_haptics         , (void));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
+AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
+AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
+
+AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
+
+AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
+AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
+AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
+AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
+AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_effect_stopped, (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
+
+AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_haptic_event_source, (void));
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/allegro5/internal/aintern_haptic.h b/include/allegro5/internal/aintern_haptic.h
new file mode 100644
index 0000000..f384c54
--- /dev/null
+++ b/include/allegro5/internal/aintern_haptic.h
@@ -0,0 +1,87 @@
+#ifndef __al_included_allegro5_aintern_haptic_h
+#define __al_included_allegro5_aintern_haptic_h
+
+#include "allegro5/haptic.h"
+
+#include "allegro5/internal/aintern_driver.h"
+#include "allegro5/internal/aintern_events.h"
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+/* Haptic devices driver virtual table.  */
+typedef struct ALLEGRO_HAPTIC_DRIVER
+{
+   int          hapdrv_id;
+   const char * hapdrv_name;
+   const char * hapdrv_desc;
+   const char * hapdrv_ascii_name;
+   AL_METHOD(bool, init_haptic, (void));
+   AL_METHOD(void, exit_haptic, (void));
+   AL_METHOD(bool, reconfigure_haptics, (void));
+   AL_METHOD(int, num_haptics, (void));
+   AL_METHOD(ALLEGRO_HAPTIC *, get_haptic, (int));
+   AL_METHOD(void, release_haptic    , (ALLEGRO_HAPTIC *));
+   AL_METHOD(int, get_haptic_flags   , (ALLEGRO_HAPTIC *));
+   AL_METHOD(const char *, get_name  , (ALLEGRO_HAPTIC *));
+   AL_METHOD(bool, get_active        , (ALLEGRO_HAPTIC *));
+   AL_METHOD(bool, is_mouse_haptic   , (ALLEGRO_MOUSE *));
+   AL_METHOD(bool, is_joystick_haptic, (ALLEGRO_JOYSTICK *));
+   AL_METHOD(ALLEGRO_HAPTIC *, get_from_mouse   , (ALLEGRO_MOUSE *));
+   AL_METHOD(ALLEGRO_HAPTIC *, get_from_joystick, (ALLEGRO_JOYSTICK *));
+   AL_METHOD(int , get_num_axes      , (ALLEGRO_HAPTIC *)); 
+   AL_METHOD(bool, is_effect_ok      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+   AL_METHOD(bool, upload_effect     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int *));
+   AL_METHOD(bool, play_effect       , (ALLEGRO_HAPTIC *, int, int ));
+   AL_METHOD(bool, stop_effect       , (ALLEGRO_HAPTIC *, int));
+   AL_METHOD(bool, is_effect_stopped , (ALLEGRO_HAPTIC *, int));
+   AL_METHOD(bool, stop_all_efects   , (ALLEGRO_HAPTIC *, int));
+   AL_METHOD(bool, is_effect_playing , (ALLEGRO_HAPTIC *, int));
+} ALLEGRO_HAPTIC_DRIVER;
+
+
+extern ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver;
+
+
+
+/* macros for constructing the driver list */
+#define _AL_BEGIN_HAPTIC_DRIVER_LIST                         \
+   _AL_DRIVER_INFO _al_haptic_driver_list[] =                \
+   {
+
+#define _AL_END_HAPTIC_DRIVER_LIST                           \
+      {  0,                NULL,                false }      \
+   };
+
+#define _AL_HAPTIC_INFO_NAME_MAX            256
+   
+/* Can playback at most 32 haptic effects at the same time. */   
+#define _AL_HAPTIC_EFFECT_PLAYBACK_MAX      32    
+
+   
+/* information about an entire haptic */
+typedef struct _AL_HAPTIC_INFO
+{
+  int  id;
+  int  flags; 
+  int  num_axes;
+  char name[_AL_HAPTIC_INFO_NAME_MAX];
+} _AL_HAPTIC_INFO;
+
+
+
+struct ALLEGRO_HAPTIC
+{
+   _AL_HAPTIC_INFO info;
+};
+
+void _al_generate_haptic_event(ALLEGRO_EVENT *event);
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif
+
+/* vi ts=8 sts=3 sw=3 et */
diff --git a/include/allegro5/internal/aintern_system.h b/include/allegro5/internal/aintern_system.h
index 669a97c..ee54836 100644
--- a/include/allegro5/internal/aintern_system.h
+++ b/include/allegro5/internal/aintern_system.h
@@ -5,6 +5,7 @@
 #include "allegro5/internal/aintern_display.h"
 #include "allegro5/internal/aintern_dtor.h"
 #include "allegro5/internal/aintern_events.h"
+#include "allegro5/internal/aintern_haptic.h"
 #include "allegro5/internal/aintern_joystick.h"
 #include "allegro5/internal/aintern_keyboard.h"
 #include "allegro5/internal/aintern_mouse.h"
@@ -26,6 +27,7 @@ struct ALLEGRO_SYSTEM_INTERFACE
    ALLEGRO_MOUSE_DRIVER *(*get_mouse_driver)(void);
    ALLEGRO_TOUCH_INPUT_DRIVER *(*get_touch_input_driver)(void);
    ALLEGRO_JOYSTICK_DRIVER *(*get_joystick_driver)(void);
+   ALLEGRO_HAPTIC_DRIVER *(*get_haptic_driver)(void);   
    int (*get_num_display_modes)(void);
    ALLEGRO_DISPLAY_MODE *(*get_display_mode)(int index, ALLEGRO_DISPLAY_MODE *mode);
    void (*shutdown_system)(void);
diff --git a/include/allegro5/platform/aintunix.h b/include/allegro5/platform/aintunix.h
index 5dcd098..f721b05 100644
--- a/include/allegro5/platform/aintunix.h
+++ b/include/allegro5/platform/aintunix.h
@@ -74,6 +74,15 @@ void _al_unix_stop_watching_fd(int fd);
 AL_VAR(struct ALLEGRO_JOYSTICK_DRIVER, _al_joydrv_linux);
 #endif
 
+/* lhaptic.c */
+/* This isn't in aintlnx.h because it's needed for the X11 port as well. */
+#define _ALLEGRO_HAPDRV_LINUX    AL_ID('L','N','X','H')
+
+#ifdef ALLEGRO_HAVE_LINUX_HAPTIC_H
+AL_VAR(struct ALLEGRO_HAPTIC_DRIVER, _al_hapdrv_linux);
+#endif
+
+
 #ifdef __cplusplus
    }
 #endif
diff --git a/lib/Headers/allegro5/haptic.h b/lib/Headers/allegro5/haptic.h
new file mode 100644
index 0000000..3da4415
--- /dev/null
+++ b/lib/Headers/allegro5/haptic.h
@@ -0,0 +1,183 @@
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      Haptic (that is, force feedback) routines for Allegro. 
+ *      By Beoran (beoran@xxxxxxxxx), 2013.
+ *
+ *      See readme.txt for copyright information.
+ */
+
+#ifndef __al_included_allegro5_haptic_h
+#define __al_included_allegro5_haptic_h
+
+#include "allegro5/base.h"
+#include "allegro5/events.h"
+#include "allegro5/mouse.h"
+#include "allegro5/joystick.h"
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+/* Enum: ALLEGRO_HAPTIC_FLAGS
+ */
+enum ALLEGRO_HAPTIC_FLAGS { 
+  ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
+  ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
+  ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
+  ALLEGRO_HAPTIC_SPRING       = 1 << 3,
+  ALLEGRO_HAPTIC_FRICTION     = 1 << 4,
+  ALLEGRO_HAPTIC_DAMPER       = 1 << 5,
+  ALLEGRO_HAPTIC_INERTIA      = 1 << 6,
+  ALLEGRO_HAPTIC_RAMP         = 1 << 7,
+  ALLEGRO_HAPTIC_SQUARE       = 1 << 8,
+  ALLEGRO_HAPTIC_TRIANGLE     = 1 << 9,
+  ALLEGRO_HAPTIC_SINE         = 1 << 10,
+  ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
+  ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
+  ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
+  ALLEGRO_HAPTIC_GAIN         = 1 << 14,  
+  ALLEGRO_HAPTIC_AUTOCENTER   = 1 << 15,  
+};
+
+
+/* Type: ALLEGRO_HAPTIC
+ */
+typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
+
+/* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
+ * An angle 0 means oriented towards the user, M_PI is away from the user 
+ * (towards the screen). 
+ * Radius (if supported ) is the diistance of the effect from the user 
+ * as a value between 0 and 1. Normally it is 0. 
+ * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
+ * horizontal plane, -M_PI points down, and M_PI points up.
+ * 
+ */
+struct ALLEGRO_HAPTIC_DIRECTION {
+  double angle; 
+  double radius;
+  double azimuth;
+};
+
+struct ALLEGRO_HAPTIC_REPLAY {
+    double length;
+    double delay;
+};
+
+struct ALLEGRO_HAPTIC_ENVELOPE {
+    double attack_length;
+    double attack_level;
+    double fade_length;
+    double fade_level;
+};
+
+struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
+    double level;
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+};
+
+struct ALLEGRO_HAPTIC_RAMP_EFFECT {
+    double start_level;
+    double end_level;
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+};
+
+struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
+    double right_saturation;
+    double left_saturation;
+    double right_coeff;
+    double left_coeff;
+    double deadband;
+    double center;
+};
+
+struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
+    int waveform;
+    double period;
+    double magnitude;
+    double offset;
+    double phase;
+    
+    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+    int    custom_len;
+    double *custom_data;
+};
+
+struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
+    double strong_magnitude;
+    double weak_magnitude;
+};
+
+union ALLEGRO_HAPTIC_EFFECT_UNION {
+    struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
+    struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
+    struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
+    struct ALLEGRO_HAPTIC_CONDITION_EFFECT  condition; 
+    struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
+};
+
+/* Type: ALLEGRO_HAPTIC_EFFECT
+ */
+struct ALLEGRO_HAPTIC_EFFECT {
+        int                                type;
+        int                                id;
+        struct ALLEGRO_HAPTIC_DIRECTION    direction;
+        struct ALLEGRO_HAPTIC_REPLAY       replay;
+        union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
+};
+
+
+/* Type: ALLEGRO_HAPTIC_EFFECT
+ */
+typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
+
+
+
+
+AL_FUNC(bool,             al_install_haptic          , (void));
+AL_FUNC(void,             al_uninstall_haptic        , (void));
+AL_FUNC(bool,             al_is_haptic_installed     , (void));
+AL_FUNC(bool,             al_reconfigure_haptic      , (void));
+
+AL_FUNC(int,              al_get_num_haptics         , (void));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
+AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
+AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
+
+AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
+
+AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
+AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
+AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
+AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
+AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_effect_stopped, (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
+
+AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_haptic_event_source, (void));
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/haptic.c b/src/haptic.c
new file mode 100644
index 0000000..7dcdc6c
--- /dev/null
+++ b/src/haptic.c
@@ -0,0 +1,239 @@
+/*         ______   ___    ___ 
+ *        /\  _  \ /\_ \  /\_ \ 
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      New haptic API.
+ * 
+ *      By Peter Wang.
+ *
+ *      See readme.txt for copyright information.
+ */
+
+/* Title: Joystick routines
+ */
+
+
+#define ALLEGRO_NO_COMPATIBILITY
+
+#include "allegro5/allegro.h"
+#include "allegro5/haptic.h"
+#include "allegro5/internal/aintern.h"
+#include "allegro5/internal/aintern_events.h"
+#include "allegro5/internal/aintern_exitfunc.h"
+#include "allegro5/internal/aintern_haptic.h"
+#include "allegro5/internal/aintern_system.h"
+
+
+
+/* the active haptic driver */
+static ALLEGRO_HAPTIC_DRIVER *haptic_driver = NULL;
+static ALLEGRO_EVENT_SOURCE   haptic_es;
+
+
+/* Function: al_install_haptic
+ */
+bool al_install_haptic(void)
+{
+   ALLEGRO_SYSTEM *sysdrv;
+   ALLEGRO_HAPTIC_DRIVER *hapdrv;
+
+   if (haptic_driver)
+      return true;
+
+   sysdrv = al_get_system_driver();
+   ASSERT(sysdrv);
+
+   /* Currently every platform only has at most one haptic driver. */
+   if (sysdrv->vt->get_haptic_driver) {
+      hapdrv = sysdrv->vt->get_haptic_driver();
+      /* Avoid race condition in case the haptic driver generates an
+       * event right after ->init_haptic.
+       */
+      _al_event_source_init(&haptic_es);
+      if (hapdrv && hapdrv->init_haptic()) {
+         haptic_driver = hapdrv;
+         _al_add_exit_func(al_uninstall_haptic, "al_uninstall_haptic");
+         return true;
+      }
+      _al_event_source_free(&haptic_es);
+   }
+
+   return false;
+}
+
+
+
+/* Function: al_uninstall_haptic
+ */
+void al_uninstall_haptic(void)
+{
+   if (haptic_driver) {
+      /* perform driver clean up */
+      haptic_driver->exit_haptic();
+      _al_event_source_free(&haptic_es);
+      haptic_driver = NULL;
+   }
+}
+
+
+/* Function: al_is_haptic_installed
+ */
+bool al_is_haptic_installed(void)
+{
+   return (haptic_driver) ? true : false;
+}
+
+
+/* Function: al_reconfigure_haptics
+ */
+bool al_reconfigure_haptics(void)
+{
+   if (!haptic_driver)
+      return false;
+   
+   return haptic_driver->reconfigure_haptics();
+}
+
+
+
+/* Function: al_get_haptic_event_source
+ */
+ALLEGRO_EVENT_SOURCE *al_get_haptic_event_source(void)
+{
+   if (!haptic_driver)
+      return NULL;
+   return &haptic_es;
+}
+
+
+
+void _al_generate_haptic_event(ALLEGRO_EVENT *event)
+{
+   ASSERT(haptic_driver);
+
+   _al_event_source_lock(&haptic_es);
+   if (_al_event_source_needs_to_generate_event(&haptic_es)) {
+      _al_event_source_emit_event(&haptic_es, event);
+   }
+   _al_event_source_unlock(&haptic_es);
+}
+
+
+
+/* Function: al_get_num_haptics
+ */
+int al_get_num_haptics(void)
+{
+   if (haptic_driver)
+      return haptic_driver->num_haptics();
+
+   return 0;
+}
+
+
+
+/* Function: al_get_haptic
+ */
+ALLEGRO_HAPTIC * al_get_haptic(int num)
+{
+   ASSERT(haptic_driver);
+   ASSERT(num >= 0);
+
+   return haptic_driver->get_haptic(num);
+}
+
+
+
+/* Function: al_release_haptic
+ */
+void al_release_haptic(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(haptic_driver);
+   ASSERT(hap);
+
+   haptic_driver->release_haptic(hap);
+}
+
+
+
+/* Function: al_get_haptic_active
+ */
+bool al_get_haptic_active(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(hap);
+
+   return hap->info.flags;
+}
+
+
+/* Function: al_get_haptic_num_axes
+ */
+int al_get_haptic_num_axes(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(hap);
+
+   return hap->info.num_axes;
+}
+
+
+/* Function: al_get_haptic_flags
+ */
+int al_get_haptic_flags(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(hap);
+
+   return haptic_driver->get_haptic_flags(hap);
+}
+
+
+
+/* Function: al_get_haptic_name
+ */
+const char *al_get_haptic_name(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(hap);
+   return haptic_driver->get_name(hap);
+   return NULL;
+}
+
+/*
+AL_FUNC(bool,             al_install_haptic          , (void));
+AL_FUNC(void,             al_uninstall_haptic        , (void));
+AL_FUNC(bool,             al_is_haptic_installed     , (void));
+AL_FUNC(bool,             al_reconfigure_haptic      , (void));
+
+AL_FUNC(int,              al_get_num_haptics         , (void));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
+AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
+AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
+
+AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
+
+AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
+AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
+AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
+AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
+AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_is_haptic_stopped       , (ALLEGRO_HAPTIC *, int play_id));
+AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
+
+
+*/
+
+
+
+
diff --git a/src/linux/lhaptic.c b/src/linux/lhaptic.c
new file mode 100644
index 0000000..3d0d69e
--- /dev/null
+++ b/src/linux/lhaptic.c
@@ -0,0 +1,439 @@
+/*         ______   ___    ___ 
+ *        /\  _  \ /\_ \  /\_ \ 
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      Linux haptic (force-feedback) device driver.
+ *
+ *      By Beoran.
+ * 
+ *      See readme.txt for copyright information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <fcntl.h>      
+#include <limits.h>     
+#include <errno.h>      
+#include <math.h>
+#include <glob.h>
+
+
+#define ALLEGRO_NO_KEY_DEFINES
+#define ALLEGRO_NO_COMPATIBILITY
+
+#include "allegro5/allegro.h"
+#include "allegro5/haptic.h"
+#include "allegro5/path.h"
+#include "allegro5/platform/alplatf.h"
+#include "allegro5/internal/aintern.h"
+#include "allegro5/internal/aintern_events.h"
+#include "allegro5/internal/aintern_haptic.h"
+#include "allegro5/platform/aintunix.h"
+#include </home/bjorn/src/allegro/lib/Headers/allegro5/haptic.h>
+
+
+#if defined(ALLEGRO_HAVE_SYS_INOTIFY_H) && defined(ALLEGRO_HAVE_SYS_TIMERFD_H)
+   #define SUPPORT_HOTPLUG
+   #include <sys/inotify.h>
+   #include <sys/timerfd.h>
+#endif
+
+ALLEGRO_DEBUG_CHANNEL("lhaptic");
+
+/* Support at most 32 haptic devices. */
+#define HAPTICS_MAX             32
+/* Use dumb char buffers of 100 characters. whihc is "enough 
+ *for everyone" for now. :p */
+#define HAPTICS_BUF_MAX         1000
+
+
+typedef struct ALLEGRO_HAPTIC_LINUX
+{
+   int in_use;
+   ALLEGRO_HAPTIC parent;
+   int config_state;
+   bool marked;
+   int fd;
+   char device_name[HAPTICS_BUF_MAX];
+   int state;
+   char name[HAPTICS_BUF_MAX];
+   int flags;
+} ALLEGRO_HAPTIC_LINUX;
+
+
+
+static bool lhap_init_haptic(void);
+static void lhap_exit_haptic(void);
+
+static bool lhap_reconfigure_haptics(void);
+static int lhap_num_haptics(void);
+static ALLEGRO_HAPTIC *lhap_get_haptic(int num);
+static void lhap_release_haptic(ALLEGRO_HAPTIC *hap_);
+
+static int lhap_get_flags(ALLEGRO_HAPTIC *hap_);
+static const char *lhap_get_name(ALLEGRO_HAPTIC *hap_);
+
+
+/* forward declarations 
+static bool lhap_get_active(ALLEGRO_HAPTIC *hap_);
+static void lhap_generate_event(ALLEGRO_HAPTIC_LINUX *joy, int button, ALLEGRO_EVENT_TYPE event_type);
+*/
+
+static bool lhap_get_active(ALLEGRO_HAPTIC *);
+static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE *);
+static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK *);
+static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE *);
+static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK *);
+static int               lhap_get_num_axes(ALLEGRO_HAPTIC *); 
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *);
+static bool lhap_upload_effect(ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int *);
+static bool lhap_play_effect(ALLEGRO_HAPTIC *, int, int);
+static bool lhap_stop_effect(ALLEGRO_HAPTIC *, int);
+static bool lhap_is_effect_stopped(ALLEGRO_HAPTIC *, int);
+static bool lhap_stop_all_effects(ALLEGRO_HAPTIC *);
+static bool lhap_is_effect_playing(ALLEGRO_HAPTIC *, int);
+
+/* The haptics driver vtable. */
+ALLEGRO_HAPTIC_DRIVER hapdrv_linux = 
+{
+   _ALLEGRO_HAPDRV_LINUX,
+   "",
+   "",
+   "Linux haptic(s)",
+   lhap_init_haptic,
+   lhap_exit_haptic,
+   lhap_reconfigure_haptics,
+   lhap_num_haptics,
+   lhap_get_haptic,
+   lhap_release_haptic,
+   lhap_get_flags,
+   lhap_get_name,
+   lhap_get_active,
+   lhap_is_mouse_haptic,
+   lhap_is_joystick_haptic,
+   lhap_get_from_mouse,
+   lhap_get_from_joystick,
+   lhap_get_num_axes,
+   lhap_is_effect_ok,
+   lhap_upload_effect,
+   lhap_play_effect,
+   lhap_stop_effect,
+   lhap_is_effect_stopped,
+   lhap_stop_all_effects,
+   lhap_is_effect_playing
+};
+
+
+ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver = &hapdrv_linux;
+
+
+
+ALLEGRO_HAPTIC_DRIVER *_al_linux_haptic_driver(void)
+{
+   return &hapdrv_linux;
+}
+
+
+
+static unsigned                 num_haptics = 0;  
+/* number of haptics known to the user */
+static ALLEGRO_HAPTIC_LINUX     haptics[HAPTICS_MAX];
+static ALLEGRO_MUTEX          * haptic_mutex;
+#ifdef SUPPORT_HOTPLUG
+
+static int                      haptic_inotify_fd = -1;
+static int                      haptic_timer_fd = -1;
+
+#endif
+
+/* Approach: to find the available haptic devices, scan 
+ * the /sys/class/input directory for any directory named eventxxx. 
+ * Then read  /sys/class/input/event1/capabilities/ff to find out the 
+ * capabilities of the device. If it's 0, then no it doesn't support force feedback.
+ * The idea of this approach is that the /dev file doesn' t have to be opened
+ * to inspect the existence of the haptic device. 
+ */
+
+/*
+ * Scans the /sys/class/input/ directory to find any haptic devices and 
+ * already sets them up to be used if needed. Returns the amount of haptics found
+ * or negative or error.
+ */
+int lhap_scan_haptics(void) {
+  char buf[HAPTICS_BUF_MAX];
+  char line[HAPTICS_BUF_MAX];
+  glob_t found;
+  int res;
+  unsigned int index;
+  num_haptics = 0;
+  for (index = 0; index < HAPTICS_MAX; index ++) {
+    haptics[index].in_use = 0;
+    haptics[index].fd     = -1;
+  }  
+  res         = glob("/sys/class/input/event*", GLOB_MARK, NULL, &found);
+  if (res == GLOB_NOMATCH) { 
+    globfree(&found);
+    return -ENOENT;
+  }
+  for (index = 0; index < found.gl_pathc; index ++) {
+    int scanres;
+    unsigned int capa = 0, extra = 0;
+    FILE * fin;
+    char * path = found.gl_pathv[index]; 
+    memset(buf, 0, HAPTICS_BUF_MAX);
+    snprintf(buf, HAPTICS_BUF_MAX, "%sdevice/capabilities/ff", path);
+    fin = fopen(buf, "r");
+    if(!fin) {  continue;  }
+    scanres = fscanf(fin, "%u%u", &capa, &extra);
+    fclose(fin);
+    
+    if (capa > 0) { 
+      char * devname = strchr(strchr(path + 1, '/') + 1, '/');
+      /* It's a haptic device. */
+      ALLEGRO_HAPTIC_LINUX * hap = haptics + num_haptics;
+      hap->parent.info.id        = num_haptics;
+      num_haptics++;
+      hap->flags     = capa;
+      snprintf(hap->device_name, HAPTICS_BUF_MAX, "/dev%s", devname);
+      hap->device_name[strlen(hap->device_name) -1] = '\0';
+      snprintf(buf, HAPTICS_BUF_MAX, "%sdevice/name", path);
+      fin = fopen(buf, "r");
+      if (!fin) {  continue;  }
+      if(fgets(line, HAPTICS_BUF_MAX, fin)) {
+        line[HAPTICS_BUF_MAX-1] = '\0';
+        line[strlen(line)]      = '\0';
+        strcpy(hap->name, line);      
+      }
+      fclose(fin);      
+      fprintf(stderr, "Haptic device found: %s (%s) (%s), %d %d %d\n", buf, hap->device_name, hap->name, scanres, capa, extra);
+      
+    }
+    
+  }
+  globfree(&found);  
+  return num_haptics;
+} 
+
+
+bool lhap_init_haptic(void) {
+  return lhap_scan_haptics() >= 0;
+}
+
+
+void lhap_exit_haptic() {
+   return;
+}
+
+static bool lhap_reconfigure_haptics(void){
+  return 0;
+}
+
+int lhap_num_haptics() {
+  return num_haptics;
+}
+
+ALLEGRO_HAPTIC_LINUX * lhap_al2lin(ALLEGRO_HAPTIC * haptic) {
+  if(!haptic) return NULL;
+  ALLEGRO_HAPTIC_LINUX  * lhap = haptics + haptic->info.id;
+  /* Could also have used offsetof, but, hey... */
+  return lhap;
+}
+
+
+void lhap_release_haptic(ALLEGRO_HAPTIC * haptic) {
+  ALLEGRO_HAPTIC_LINUX  * lhap = lhap_al2lin(haptic);
+  ASSERT(haptic);
+  if (!lhap->in_use) return;
+  if (lhap->fd < 0) return;
+  close(lhap->fd);
+}
+
+
+ALLEGRO_HAPTIC * lhap_get_haptic(int index) {
+  ALLEGRO_HAPTIC_LINUX * lhap;
+  if(index >= HAPTICS_MAX) return NULL;
+  lhap = haptics + index;
+  if (!lhap->in_use) {
+    lhap->fd     = open(lhap->device_name, O_RDWR);
+    if(lhap->fd < 0 ) return NULL;
+    lhap->in_use = 1;
+    return &lhap->parent;
+  } else {
+    return &lhap->parent;
+  }
+  return NULL;
+}
+
+
+const char * lhap_get_name(ALLEGRO_HAPTIC * haptic) {
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
+  return lhap->name;
+}
+
+int lhap_get_flags(ALLEGRO_HAPTIC * haptic) {
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
+  return lhap->flags;
+}
+
+
+static bool lhap_type2lin(__u16 * res, int type) {
+  ASSERT(res);
+  
+  switch (type) {
+    case ALLEGRO_HAPTIC_RUMBLE          : (*res) = FF_RUMBLE       ; break;
+    case ALLEGRO_HAPTIC_PERIODIC        : (*res) = FF_PERIODIC     ; break;
+    case ALLEGRO_HAPTIC_CONSTANT        : (*res) = FF_CONSTANT     ; break;
+    case ALLEGRO_HAPTIC_SPRING          : (*res) = FF_SPRING       ; break;
+    case ALLEGRO_HAPTIC_FRICTION        : (*res) = FF_FRICTION     ; break;
+    case ALLEGRO_HAPTIC_DAMPER          : (*res) = FF_DAMPER       ; break;
+    case ALLEGRO_HAPTIC_INERTIA         : (*res) = FF_INERTIA      ; break;
+    case ALLEGRO_HAPTIC_RAMP            : (*res) = FF_RAMP         ; break;
+    default: 
+      return false;
+  }
+  return true;
+}
+
+static bool lhap_wave2lin(__u16 * res, int type) {
+  ASSERT(res);
+  
+  switch (type) {
+    case ALLEGRO_HAPTIC_SQUARE          : (*res) = FF_SQUARE       ; break;
+    case ALLEGRO_HAPTIC_TRIANGLE        : (*res) = FF_TRIANGLE     ; break;
+    case ALLEGRO_HAPTIC_SINE            : (*res) = FF_SINE         ; break;
+    case ALLEGRO_HAPTIC_SAW_UP          : (*res) = FF_SAW_UP       ; break;
+    case ALLEGRO_HAPTIC_SAW_DOWN        : (*res) = FF_SAW_DOWN     ; break;
+    case ALLEGRO_HAPTIC_CUSTOM          : (*res) = FF_CUSTOM       ; break;    
+    default: 
+      return false;
+  }
+  return true;
+}
+
+/* converts the time in seconds to a linux compatible time. Return false if
+ out of bounds. */
+static bool lhap_time2lin(__u16 * res, double sec) {
+  ASSERT(res); 
+  
+  if (sec < 0.0)        return false; 
+  if (sec > 32.767)     return false;
+  return (__u16) round(sec * 1000.0);
+}
+
+/* Converts replay data to linux. */
+static bool lhap_replay2lin(struct ff_replay * lin, ALLEGRO_HAPTIC_REPLAY * al) {
+  if(!lhap_time2lin(&lin.delay, al.delay))  return false;
+  if(!lhap_time2lin(&lin.length, al.length)) return false;
+  return true;
+}
+
+/* Converts the level in range 0.0 to 1.0 to a linux compatible level. 
+ * Returns false if out of bounds. */
+static bool lhap_level2lin(__u16 * res, double level) {
+  ASSERT(res);   
+  if (level < 0.0)        return false; 
+  if (level > 1.0)        return false;
+  return (__u16) round(level * ((double) 0x7fff));
+}
+
+/* Converts a rumble effect to linux. */
+static bool lhap_rumble2lin(struct ff_rumble_effect * lin, ALLEGRO_HAPTIC_RUMBLE_EFFECT * al) {
+  if(!lhap_level2lin(&lin->strong_magnitude, al->strong_magnitude)) return false;
+  if(!lhap_level2lin(&lin->weak_magnitude  , al->weak_magnitude)) return false;
+  return true;
+}
+
+/* converts a periodic effect  to linux */
+static bool lhap_periodic2lin(struct ff_periodic_effect * lin, ALLEGRO_HAPTIC_PERIODIC_EFFECT * al) {
+  
+  return true;
+}
+
+/* Converts allegro haptic effect to linux haptic effect. */
+static bool lhap_effect2lin(struct ff_effect * lin, ALLEGRO_HAPTIC_EFFECT * al) {
+  if(!lhap_type2lin(&lin->type, al->type,) return false;
+  /* lin_effect->replay = effect->re; */
+  lin->direction = (__u16) round(((double)0xC000 * al->direction.angle) / (2 * M_PI));
+  lin->id        = -1;
+  if(!lhap_replay2lin(&lin->replay, &al->replay);
+  switch(lin->type) {
+    case FF_RUMBLE:
+      if(!lhap_rumble2lin(&lin->rumble, &al->rumble);
+      break;
+    case FF_PERIODIC:      
+      if(!lhap_periodic2lin(&lin->periodic, al->data.periodic)) return false;
+      break;
+      
+  }
+     
+  return false;
+}
+
+
+
+static bool lhap_get_active(ALLEGRO_HAPTIC * haptic) {
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
+  return lhap->in_use;
+}
+
+static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * mouse) {
+  return false;
+}
+
+static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK * joy) {
+   return false;
+}
+
+static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE * mouse) {
+  return NULL;
+}
+
+static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK * joy) {
+  return NULL;
+}
+
+static int lhap_get_num_axes(ALLEGRO_HAPTIC * haptic) {
+  return 1;
+}
+
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect) {
+   return false;
+}
+
+static bool lhap_upload_effect(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect, int * playid) {
+  return false;
+}
+
+static bool lhap_play_effect(ALLEGRO_HAPTIC * haptic, int repeats, int playid) {
+  return false;  
+}
+
+static bool lhap_stop_effect(ALLEGRO_HAPTIC * haptic, int playid) {
+  return false;
+}
+
+static bool lhap_is_effect_stopped(ALLEGRO_HAPTIC * haptic, int playid) {
+  return true;
+}
+
+static bool lhap_stop_all_effects(ALLEGRO_HAPTIC * haptic) {
+  return false;
+}
+
+static bool lhap_is_effect_playing(ALLEGRO_HAPTIC * haptic, int playid) {
+  return false;
+}
+
+
+
diff --git a/src/macosx/ohaptic.m b/src/macosx/ohaptic.m
new file mode 100644
index 0000000..e69de29
diff --git a/src/win/whaptic.c b/src/win/whaptic.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/x/xsystem.c b/src/x/xsystem.c
index ae4c41e..81a6855 100644
--- a/src/x/xsystem.c
+++ b/src/x/xsystem.c
@@ -173,6 +173,13 @@ static ALLEGRO_JOYSTICK_DRIVER *xglx_get_joystick_driver(void)
    return _al_joystick_driver_list[0].driver;
 }
 
+
+static ALLEGRO_HAPTIC_DRIVER *xglx_get_haptic_driver(void)
+{
+   return _al_haptic_driver;
+}
+
+
 static int xglx_get_num_video_adapters(void)
 {
    ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver();
@@ -239,6 +246,7 @@ ALLEGRO_SYSTEM_INTERFACE *_al_system_xglx_driver(void)
    xglx_vt->get_keyboard_driver = xglx_get_keyboard_driver;
    xglx_vt->get_mouse_driver = xglx_get_mouse_driver;
    xglx_vt->get_joystick_driver = xglx_get_joystick_driver;
+   xglx_vt->get_haptic_driver     = xglx_get_haptic_driver;
    xglx_vt->get_num_display_modes = xglx_get_num_display_modes;
    xglx_vt->get_display_mode = xglx_get_display_mode;
    xglx_vt->shutdown_system = xglx_shutdown_system;
@@ -251,6 +259,7 @@ ALLEGRO_SYSTEM_INTERFACE *_al_system_xglx_driver(void)
    xglx_vt->ungrab_mouse = _al_xwin_ungrab_mouse;
    xglx_vt->get_path = _al_unix_get_path;
    xglx_vt->inhibit_screensaver = xglx_inhibit_screensaver;
+   
 
    return xglx_vt;
 }
-- 
1.7.10.4


From 1ca9a6284f8c88955552ea7cfa5dd578dd219d5c Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Sat, 8 Jun 2013 23:17:28 +0200
Subject: [PATCH 02/10] Quick and very dirty commit before pushing to github

---
 include/allegro5/haptic.h |  102 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 83 insertions(+), 19 deletions(-)

diff --git a/include/allegro5/haptic.h b/include/allegro5/haptic.h
index 3da4415..a0ecd19 100644
--- a/include/allegro5/haptic.h
+++ b/include/allegro5/haptic.h
@@ -26,9 +26,9 @@
    extern "C" {
 #endif
 
-/* Enum: ALLEGRO_HAPTIC_FLAGS
+/* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_FLAGS { 
+enum ALLEGRO_HAPTIC_CONSTANTS { 
   ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
   ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
   ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
@@ -43,22 +43,29 @@ enum ALLEGRO_HAPTIC_FLAGS {
   ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
   ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
   ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
-  ALLEGRO_HAPTIC_GAIN         = 1 << 14,  
-  ALLEGRO_HAPTIC_AUTOCENTER   = 1 << 15,  
+  ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
+  ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
+  ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
+  ALLEGRO_HAPRIC_AZIMUTH      = 1 << 17,
 };
 
 
+
 /* Type: ALLEGRO_HAPTIC
  */
 typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
 
 /* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
  * An angle 0 means oriented towards the user, M_PI is away from the user 
- * (towards the screen). 
- * Radius (if supported ) is the diistance of the effect from the user 
- * as a value between 0 and 1. Normally it is 0. 
+ * (towards the screen). Angle is only supported if the device capabilities include
+ * ALLEGRO_HAPTIC_ANGLE.  
+ * Radius (if supported ) is the distance of the effect from the user 
+ * as a value between 0 and 1. Normally it is 0. Radius is only supported if the 
+ * device capabilities include ALLEGRO_HAPTIC_RADIUS .  
  * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
  * horizontal plane, -M_PI points down, and M_PI points up.
+ * Azimuth is only supported if the device capabilities include 
+ * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
 struct ALLEGRO_HAPTIC_DIRECTION {
@@ -67,11 +74,17 @@ struct ALLEGRO_HAPTIC_DIRECTION {
   double azimuth;
 };
 
+/* In all of the following structs, the doubles that express duration represent 
+ * time in seconds. The double that represent levels of intensity are between 0.0 
+ * and 1.0 that mean no effect and full 100% effect. */
+
+/* Delay to start the replay and duration of the replay, expressed  in seconds. */
 struct ALLEGRO_HAPTIC_REPLAY {
     double length;
     double delay;
 };
 
+/* Envelope of the effect. */
 struct ALLEGRO_HAPTIC_ENVELOPE {
     double attack_length;
     double attack_level;
@@ -79,17 +92,20 @@ struct ALLEGRO_HAPTIC_ENVELOPE {
     double fade_level;
 };
 
+/* Constant effect.  Level is between 0.0 and 1.0. */
 struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
     double level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
+/* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
 struct ALLEGRO_HAPTIC_RAMP_EFFECT {
     double start_level;
     double end_level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
+/* Condition effect. */
 struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
     double right_saturation;
     double left_saturation;
@@ -99,6 +115,7 @@ struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
     double center;
 };
 
+/* Periodic (wave) effect. */
 struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
     int waveform;
     double period;
@@ -111,6 +128,8 @@ struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
     double *custom_data;
 };
 
+/* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
+ the strong and the weak rumble motors in the haptic device.  */
 struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
     double strong_magnitude;
     double weak_magnitude;
@@ -124,7 +143,8 @@ union ALLEGRO_HAPTIC_EFFECT_UNION {
     struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
 };
 
-/* Type: ALLEGRO_HAPTIC_EFFECT
+/* Type: ALLEGRO_HAPTIC_EFFECT. This neeeds to be filled in and uploaded to
+ * the haptic device before it can be played back. 
  */
 struct ALLEGRO_HAPTIC_EFFECT {
         int                                type;
@@ -141,35 +161,79 @@ typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
 
-
+/* Installs the haptic (force feedback) device subsystem. */
 AL_FUNC(bool,             al_install_haptic          , (void));
+/* Uninstalls the haptic device subsystem. */
 AL_FUNC(void,             al_uninstall_haptic        , (void));
+/* Returns true if the haptic device subsystem is installed, false if not. */
 AL_FUNC(bool,             al_is_haptic_installed     , (void));
+/* Checks if no new haptic devices became availabe and reconfigues the haptic 
+ *subsystem. */
 AL_FUNC(bool,             al_reconfigure_haptic      , (void));
 
+/* Gets the amount of available haptic devices.*/
 AL_FUNC(int,              al_get_num_haptics         , (void));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
+
+/* Opens and initializes the haptic device and returns a pointer 
+ * to a device handle, or NULL on error.  */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic             , (int hapticn));
+/* Closes the haptic device. */
 AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
+/* Returns true if the haptic device can currently be used, false if not.*/
 AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+/* Gets a string that describes the name of the haptic device.*/
 AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
 
-AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
+/* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if
+ set indicate that the haptic device supports the given feature. */
+AL_FUNC(int,              al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
+
+/* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
+ it is as if every effect's intensity is multiplied by it. Gain is a value between 
+ 0.0 and 1.0. Returns true if set sucessfully, false if not.*/
+AL_FUNC(bool,             al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
+/* Returns the current gain of the device. */
+AL_FUNC(double,           al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
 
+/* Returns true if the mouse has haptic capabilities, false if not.*/
 AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+
+/* Returns true if the joystick has haptic capabilities, false if not.*/
 AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL;*/
 AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL;*/
 AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
-AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
+
+/* Returns the maximum amount of haptic effects that can be uploaded to the device. */
+AL_FUNC(int,              al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the haptic device can play the haptic effect as given, false if not. */
 AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
 
-AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
-AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
-AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_effect_stopped, (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
+/* Uploads the haptic effect to the device. In play_id, an integer is stored that is 
+ a reference to be used to control playback of the effect.*/
+AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+/* Plays back a previously uploaded haptic effect on this device. */
+AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT , * int loop));
+
+/* Stops playing a haptic effect on this device. */
+AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+/* Stops playing all haptic effects on this device. */
+AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the haptic effect is playing on the device false if not or if stopped. */
+AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+/* Uploads a simple rumble effect to the haptic device and starts playback immediately.
+ */
+AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, double intensity));
 
+/* Event source for haptic device events. 
+ *(XXX: currently no events are planned to be emitted, but that may change. )*/
 AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_haptic_event_source, (void));
 
 
-- 
1.7.10.4


From 6ff0cb9960bf6e1dba1424209e970102e0e3b84b Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Fri, 21 Jun 2013 15:09:36 +0200
Subject: [PATCH 03/10] Interface and implementation of haptic devices with
 linux driver and an example.

---
 examples/ex_haptic.c                       |   58 ++-
 include/allegro5/haptic.h                  |  118 +++--
 include/allegro5/internal/aintern_haptic.h |   56 +--
 lib/Headers/allegro5/haptic.h              |  154 +++++--
 src/haptic.c                               |  238 ++++++----
 src/linux/lhaptic.c                        |  672 ++++++++++++++++++++--------
 6 files changed, 906 insertions(+), 390 deletions(-)

diff --git a/examples/ex_haptic.c b/examples/ex_haptic.c
index efaa0bf..c8dcf41 100644
--- a/examples/ex_haptic.c
+++ b/examples/ex_haptic.c
@@ -10,19 +10,31 @@
 
 #include "common.c"
 
+
 #define MAX_HAPTICS  32
 
 /* globals */
 ALLEGRO_EVENT_QUEUE  *event_queue;
 
-int num_haptics = 0;
-ALLEGRO_HAPTIC * haptics[MAX_HAPTICS];
 
 
 int main(void)
 {
    int index;
-   ALLEGRO_DISPLAY *display;
+   ALLEGRO_DISPLAY * display;
+   ALLEGRO_HAPTIC  * haptic = NULL;
+   ALLEGRO_HAPTIC_EFFECT effect = {0};
+   double intensity = 1.0;
+   double duration  = 1.0;
+   effect.type                           = ALLEGRO_HAPTIC_RUMBLE;
+   effect.data.rumble.strong_magnitude   = intensity;
+   effect.data.rumble.weak_magnitude     = intensity;  
+   effect.replay.delay                   = 0.1;
+   effect.replay.length                  = duration;
+   
+   
+   int num_joysticks;
+   double gain = -1.0;
 
    if (!al_init()) {
       abort_example("Could not init Allegro.\n");
@@ -32,7 +44,7 @@ int main(void)
    if (!display) {
       abort_example("al_create_display failed\n");
    }
-
+   al_install_joystick();
    al_install_haptic();
 
    event_queue = al_create_event_queue();
@@ -40,15 +52,37 @@ int main(void)
       abort_example("al_create_event_queue failed\n");
    }
    open_log();
-   num_haptics = al_get_num_haptics();
-   log_printf("Found %d haptic devices.\n", num_haptics);
-   for(index = 0; index < num_haptics; index++) {
-     ALLEGRO_HAPTIC * hap = al_get_haptic(index);; 
-     haptics[index] = hap;
-     if (hap) {  
-      log_printf("Opened device %d: %s.\n", al_get_haptic_name(hap));
+     
+   num_joysticks = al_get_num_joysticks();
+   for(index = 0; index < num_joysticks; index++) {
+     ALLEGRO_JOYSTICK * joy = al_get_joystick(index);
+     if(!joy) continue;
+     if (!al_is_joystick_haptic(joy)) {  
+       log_printf("Joystick %s does not support force feedback.\n", al_get_joystick_name(joy));
+       al_release_joystick(joy);
+       continue;
      } else {
-      log_printf("Could not open haptic device %d.\n", index);
+       ALLEGRO_HAPTIC_EFFECT_ID id;
+       log_printf("Joystick %s supports force feedback.\n", al_get_joystick_name(joy));
+       haptic = al_get_haptic_from_joystick(joy);
+       log_printf("Can play back %d haptic effects.\n", al_get_num_haptic_effects(haptic));
+       log_printf("Set gain: %d.\n", al_set_haptic_gain(haptic, 0.8));
+       log_printf("Get gain: %lf.\n", al_get_haptic_gain(haptic));
+       log_printf("Capabilities: %d.\n", al_get_haptic_capabilities(haptic));
+       log_printf("Upload: %d.\n: ", al_upload_haptic_effect(haptic, &effect, &id));
+       log_printf("Play: %d.\n: ", al_play_haptic_effect(&id, 5));
+       // al_rest(1.1 * 5 + 0.5);
+       while (al_is_haptic_effect_playing(&id)) {
+         //log_printf(".");
+       }
+       log_printf("Set gain: %d.\n", al_set_haptic_gain(haptic, 0.4));
+       log_printf("Play: %d.\n: ", al_play_haptic_effect(&id, 5));
+       while (al_is_haptic_effect_playing(&id)) {
+         //log_printf(".");
+       }
+       log_printf("Release: %d.\n: ", al_release_haptic_effect(&id));
+       
+       log_printf("\nAll done!\n");       
      }
    }
    
diff --git a/include/allegro5/haptic.h b/include/allegro5/haptic.h
index a0ecd19..2e5e1a3 100644
--- a/include/allegro5/haptic.h
+++ b/include/allegro5/haptic.h
@@ -161,80 +161,108 @@ typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
 
+/* Type: ALLEGRO_HAPTIC_EFFECT_ID
+ */
+typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
+
+struct ALLEGRO_HAPTIC_EFFECT_ID {
+  ALLEGRO_HAPTIC        * _haptic;
+  ALLEGRO_HAPTIC_EFFECT * _effect;
+  int                     _id;
+  int                     _handle;
+  bool                    _playing;  
+  double                  _started;
+  int                     _loops; 
+};
+
+
 /* Installs the haptic (force feedback) device subsystem. */
 AL_FUNC(bool,             al_install_haptic          , (void));
 /* Uninstalls the haptic device subsystem. */
 AL_FUNC(void,             al_uninstall_haptic        , (void));
 /* Returns true if the haptic device subsystem is installed, false if not. */
 AL_FUNC(bool,             al_is_haptic_installed     , (void));
-/* Checks if no new haptic devices became availabe and reconfigues the haptic 
- *subsystem. */
-AL_FUNC(bool,             al_reconfigure_haptic      , (void));
-
-/* Gets the amount of available haptic devices.*/
-AL_FUNC(int,              al_get_num_haptics         , (void));
-
-/* Opens and initializes the haptic device and returns a pointer 
- * to a device handle, or NULL on error.  */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic             , (int hapticn));
-/* Closes the haptic device. */
-AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the mouse has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+/* Returns true if the joystick has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+/* Returns true if the keyboard has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_keyboard_haptic      , (ALLEGRO_KEYBOARD *));
+/* Returns true if the display has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_display_haptic       , (ALLEGRO_DISPLAY *));
+/* Returns true if the touch input has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_touch_input_haptic   , (ALLEGRO_TOUCH_INPUT *));
+
+
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse    , (ALLEGRO_MOUSE *));
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick , (ALLEGRO_JOYSTICK *));
+/* If the keyboard has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard , (ALLEGRO_KEYBOARD *));
+/* If the display has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
+/* If the touch input has haptic capabilities, returns the associated haptic 
+ * device handle. Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
+
+
+
+
 /* Returns true if the haptic device can currently be used, false if not.*/
-AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
-/* Gets a string that describes the name of the haptic device.*/
-AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
+AL_FUNC(bool,   al_get_haptic_active       , (ALLEGRO_HAPTIC *));
 
 /* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if
  set indicate that the haptic device supports the given feature. */
-AL_FUNC(int,              al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
+AL_FUNC(int,    al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
 
 /* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
  it is as if every effect's intensity is multiplied by it. Gain is a value between 
  0.0 and 1.0. Returns true if set sucessfully, false if not.*/
-AL_FUNC(bool,             al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
+AL_FUNC(bool,   al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
 /* Returns the current gain of the device. */
-AL_FUNC(double,           al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
+AL_FUNC(double, al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
 
-/* Returns true if the mouse has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
-
-/* Returns true if the joystick has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
-/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
- * Otherwise returns NULL;*/
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
-/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
- * Otherwise returns NULL;*/
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
 
 /* Returns the maximum amount of haptic effects that can be uploaded to the device. */
-AL_FUNC(int,              al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
+AL_FUNC(int,    al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
 
 /* Returns true if the haptic device can play the haptic effect as given, false if not. */
-AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+AL_FUNC(bool,   al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+/* Uploads the haptic effect to the device. In play_id, a handle is stored that is 
+ a reference to be used to control playback of the effect. */
+AL_FUNC(bool,   al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
-/* Uploads the haptic effect to the device. In play_id, an integer is stored that is 
- a reference to be used to control playback of the effect.*/
-AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+/* Plays back a previously uploaded haptic effect. */
+AL_FUNC(bool,   al_play_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
 
-/* Plays back a previously uploaded haptic effect on this device. */
-AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT , * int loop));
+/* Uploads and immediately plays back the haptic effect to the device. */
+AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
-/* Stops playing a haptic effect on this device. */
-AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+/* Stops playing a haptic effect . */
+AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
 /* Stops playing all haptic effects on this device. */
-AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
+AL_FUNC(bool,   al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the haptic effect is playing or false if not or if stopped. */
+AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
+
+/* Releases the haptic effect from the device it has been uploaded to, allowing for 
+ other effects to be uploaded. */
+AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+
 
-/* Returns true if the haptic effect is playing on the device false if not or if stopped. */
-AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
 
 /* Uploads a simple rumble effect to the haptic device and starts playback immediately.
  */
-AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, double intensity));
+AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
 
-/* Event source for haptic device events. 
- *(XXX: currently no events are planned to be emitted, but that may change. )*/
-AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_haptic_event_source, (void));
 
 
 
diff --git a/include/allegro5/internal/aintern_haptic.h b/include/allegro5/internal/aintern_haptic.h
index f384c54..548e09f 100644
--- a/include/allegro5/internal/aintern_haptic.h
+++ b/include/allegro5/internal/aintern_haptic.h
@@ -19,25 +19,33 @@ typedef struct ALLEGRO_HAPTIC_DRIVER
    const char * hapdrv_ascii_name;
    AL_METHOD(bool, init_haptic, (void));
    AL_METHOD(void, exit_haptic, (void));
-   AL_METHOD(bool, reconfigure_haptics, (void));
-   AL_METHOD(int, num_haptics, (void));
-   AL_METHOD(ALLEGRO_HAPTIC *, get_haptic, (int));
-   AL_METHOD(void, release_haptic    , (ALLEGRO_HAPTIC *));
-   AL_METHOD(int, get_haptic_flags   , (ALLEGRO_HAPTIC *));
-   AL_METHOD(const char *, get_name  , (ALLEGRO_HAPTIC *));
-   AL_METHOD(bool, get_active        , (ALLEGRO_HAPTIC *));
+   
    AL_METHOD(bool, is_mouse_haptic   , (ALLEGRO_MOUSE *));
    AL_METHOD(bool, is_joystick_haptic, (ALLEGRO_JOYSTICK *));
+   AL_METHOD(bool, is_keyboard_haptic, (ALLEGRO_KEYBOARD *));
+   AL_METHOD(bool, is_display_haptic , (ALLEGRO_DISPLAY *));
+   AL_METHOD(bool, is_touch_input_haptic , (ALLEGRO_TOUCH_INPUT *));
+   
    AL_METHOD(ALLEGRO_HAPTIC *, get_from_mouse   , (ALLEGRO_MOUSE *));
    AL_METHOD(ALLEGRO_HAPTIC *, get_from_joystick, (ALLEGRO_JOYSTICK *));
-   AL_METHOD(int , get_num_axes      , (ALLEGRO_HAPTIC *)); 
+   AL_METHOD(ALLEGRO_HAPTIC *, get_from_keyboard, (ALLEGRO_KEYBOARD *));
+   AL_METHOD(ALLEGRO_HAPTIC *, get_from_display , (ALLEGRO_DISPLAY *));
+   AL_METHOD(ALLEGRO_HAPTIC *, get_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
+
+   AL_METHOD(bool  , get_active        , (ALLEGRO_HAPTIC *)); 
+   AL_METHOD(int   , get_capabilities  , (ALLEGRO_HAPTIC *));   
+   AL_METHOD(double, get_gain          , (ALLEGRO_HAPTIC *));
+   AL_METHOD(bool  , set_gain          , (ALLEGRO_HAPTIC *, double));
+   AL_METHOD(int   , get_num_effects   , (ALLEGRO_HAPTIC *));   
+   
    AL_METHOD(bool, is_effect_ok      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
-   AL_METHOD(bool, upload_effect     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int *));
-   AL_METHOD(bool, play_effect       , (ALLEGRO_HAPTIC *, int, int ));
-   AL_METHOD(bool, stop_effect       , (ALLEGRO_HAPTIC *, int));
-   AL_METHOD(bool, is_effect_stopped , (ALLEGRO_HAPTIC *, int));
-   AL_METHOD(bool, stop_all_efects   , (ALLEGRO_HAPTIC *, int));
-   AL_METHOD(bool, is_effect_playing , (ALLEGRO_HAPTIC *, int));
+   AL_METHOD(bool, upload_effect     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID *));
+   AL_METHOD(bool, play_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *, int));
+   AL_METHOD(bool, stop_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *));   
+   AL_METHOD(bool, is_effect_playing , (ALLEGRO_HAPTIC_EFFECT_ID *));   
+   AL_METHOD(bool, stop_all_efects   , (ALLEGRO_HAPTIC *));
+   AL_METHOD(bool, release_effect    , (ALLEGRO_HAPTIC_EFFECT_ID *));
+   
 } ALLEGRO_HAPTIC_DRIVER;
 
 
@@ -56,24 +64,22 @@ extern ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver;
 
 #define _AL_HAPTIC_INFO_NAME_MAX            256
    
-/* Can playback at most 32 haptic effects at the same time. */   
+/* Can upload at most 32 haptic effects at the same time. */   
 #define _AL_HAPTIC_EFFECT_PLAYBACK_MAX      32    
 
    
-/* information about an entire haptic */
-typedef struct _AL_HAPTIC_INFO
-{
-  int  id;
-  int  flags; 
-  int  num_axes;
-  char name[_AL_HAPTIC_INFO_NAME_MAX];
-} _AL_HAPTIC_INFO;
-
+#define _AL_HAPTIC_FROM_JOYSTICK        1
+#define _AL_HAPTIC_FROM_MOUSE           2
+#define _AL_HAPTIC_FROM_KEYBOARD        3
+#define _AL_HAPTIC_FROM_DISPLAY         4
+#define _AL_HAPTIC_FROM_TOUCH_INPUT     5
 
 
 struct ALLEGRO_HAPTIC
 {
-   _AL_HAPTIC_INFO info;
+  int    from;
+  void * device;
+  double gain;
 };
 
 void _al_generate_haptic_event(ALLEGRO_EVENT *event);
diff --git a/lib/Headers/allegro5/haptic.h b/lib/Headers/allegro5/haptic.h
index 3da4415..2e5e1a3 100644
--- a/lib/Headers/allegro5/haptic.h
+++ b/lib/Headers/allegro5/haptic.h
@@ -26,9 +26,9 @@
    extern "C" {
 #endif
 
-/* Enum: ALLEGRO_HAPTIC_FLAGS
+/* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_FLAGS { 
+enum ALLEGRO_HAPTIC_CONSTANTS { 
   ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
   ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
   ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
@@ -43,22 +43,29 @@ enum ALLEGRO_HAPTIC_FLAGS {
   ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
   ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
   ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
-  ALLEGRO_HAPTIC_GAIN         = 1 << 14,  
-  ALLEGRO_HAPTIC_AUTOCENTER   = 1 << 15,  
+  ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
+  ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
+  ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
+  ALLEGRO_HAPRIC_AZIMUTH      = 1 << 17,
 };
 
 
+
 /* Type: ALLEGRO_HAPTIC
  */
 typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
 
 /* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
  * An angle 0 means oriented towards the user, M_PI is away from the user 
- * (towards the screen). 
- * Radius (if supported ) is the diistance of the effect from the user 
- * as a value between 0 and 1. Normally it is 0. 
+ * (towards the screen). Angle is only supported if the device capabilities include
+ * ALLEGRO_HAPTIC_ANGLE.  
+ * Radius (if supported ) is the distance of the effect from the user 
+ * as a value between 0 and 1. Normally it is 0. Radius is only supported if the 
+ * device capabilities include ALLEGRO_HAPTIC_RADIUS .  
  * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
  * horizontal plane, -M_PI points down, and M_PI points up.
+ * Azimuth is only supported if the device capabilities include 
+ * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
 struct ALLEGRO_HAPTIC_DIRECTION {
@@ -67,11 +74,17 @@ struct ALLEGRO_HAPTIC_DIRECTION {
   double azimuth;
 };
 
+/* In all of the following structs, the doubles that express duration represent 
+ * time in seconds. The double that represent levels of intensity are between 0.0 
+ * and 1.0 that mean no effect and full 100% effect. */
+
+/* Delay to start the replay and duration of the replay, expressed  in seconds. */
 struct ALLEGRO_HAPTIC_REPLAY {
     double length;
     double delay;
 };
 
+/* Envelope of the effect. */
 struct ALLEGRO_HAPTIC_ENVELOPE {
     double attack_length;
     double attack_level;
@@ -79,17 +92,20 @@ struct ALLEGRO_HAPTIC_ENVELOPE {
     double fade_level;
 };
 
+/* Constant effect.  Level is between 0.0 and 1.0. */
 struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
     double level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
+/* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
 struct ALLEGRO_HAPTIC_RAMP_EFFECT {
     double start_level;
     double end_level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
+/* Condition effect. */
 struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
     double right_saturation;
     double left_saturation;
@@ -99,6 +115,7 @@ struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
     double center;
 };
 
+/* Periodic (wave) effect. */
 struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
     int waveform;
     double period;
@@ -111,6 +128,8 @@ struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
     double *custom_data;
 };
 
+/* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
+ the strong and the weak rumble motors in the haptic device.  */
 struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
     double strong_magnitude;
     double weak_magnitude;
@@ -124,7 +143,8 @@ union ALLEGRO_HAPTIC_EFFECT_UNION {
     struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
 };
 
-/* Type: ALLEGRO_HAPTIC_EFFECT
+/* Type: ALLEGRO_HAPTIC_EFFECT. This neeeds to be filled in and uploaded to
+ * the haptic device before it can be played back. 
  */
 struct ALLEGRO_HAPTIC_EFFECT {
         int                                type;
@@ -141,36 +161,108 @@ typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
 
+/* Type: ALLEGRO_HAPTIC_EFFECT_ID
+ */
+typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
+
+struct ALLEGRO_HAPTIC_EFFECT_ID {
+  ALLEGRO_HAPTIC        * _haptic;
+  ALLEGRO_HAPTIC_EFFECT * _effect;
+  int                     _id;
+  int                     _handle;
+  bool                    _playing;  
+  double                  _started;
+  int                     _loops; 
+};
+
 
+/* Installs the haptic (force feedback) device subsystem. */
 AL_FUNC(bool,             al_install_haptic          , (void));
+/* Uninstalls the haptic device subsystem. */
 AL_FUNC(void,             al_uninstall_haptic        , (void));
+/* Returns true if the haptic device subsystem is installed, false if not. */
 AL_FUNC(bool,             al_is_haptic_installed     , (void));
-AL_FUNC(bool,             al_reconfigure_haptic      , (void));
-
-AL_FUNC(int,              al_get_num_haptics         , (void));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
-AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
-AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
-AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
-
-AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
 
+/* Returns true if the mouse has haptic capabilities, false if not.*/
 AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+/* Returns true if the joystick has haptic capabilities, false if not.*/
 AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
-AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
-AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
-
-AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
-AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
-AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_effect_stopped, (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
-
-AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_haptic_event_source, (void));
+/* Returns true if the keyboard has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_keyboard_haptic      , (ALLEGRO_KEYBOARD *));
+/* Returns true if the display has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_display_haptic       , (ALLEGRO_DISPLAY *));
+/* Returns true if the touch input has haptic capabilities, false if not.*/
+AL_FUNC(bool,             al_is_touch_input_haptic   , (ALLEGRO_TOUCH_INPUT *));
+
+
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse    , (ALLEGRO_MOUSE *));
+/* If the mouse has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick , (ALLEGRO_JOYSTICK *));
+/* If the keyboard has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard , (ALLEGRO_KEYBOARD *));
+/* If the display has haptic capabilities, returns the associated haptic device handle. 
+ * Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
+/* If the touch input has haptic capabilities, returns the associated haptic 
+ * device handle. Otherwise returns NULL. */
+AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
+
+
+
+
+/* Returns true if the haptic device can currently be used, false if not.*/
+AL_FUNC(bool,   al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+
+/* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if
+ set indicate that the haptic device supports the given feature. */
+AL_FUNC(int,    al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
+
+/* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
+ it is as if every effect's intensity is multiplied by it. Gain is a value between 
+ 0.0 and 1.0. Returns true if set sucessfully, false if not.*/
+AL_FUNC(bool,   al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
+/* Returns the current gain of the device. */
+AL_FUNC(double, al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
+
+
+/* Returns the maximum amount of haptic effects that can be uploaded to the device. */
+AL_FUNC(int,    al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the haptic device can play the haptic effect as given, false if not. */
+AL_FUNC(bool,   al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+
+/* Uploads the haptic effect to the device. In play_id, a handle is stored that is 
+ a reference to be used to control playback of the effect. */
+AL_FUNC(bool,   al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+
+/* Plays back a previously uploaded haptic effect. */
+AL_FUNC(bool,   al_play_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
+
+/* Uploads and immediately plays back the haptic effect to the device. */
+AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+
+/* Stops playing a haptic effect . */
+AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
+/* Stops playing all haptic effects on this device. */
+AL_FUNC(bool,   al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
+
+/* Returns true if the haptic effect is playing or false if not or if stopped. */
+AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
+
+/* Releases the haptic effect from the device it has been uploaded to, allowing for 
+ other effects to be uploaded. */
+AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+
+
+
+/* Uploads a simple rumble effect to the haptic device and starts playback immediately.
+ */
+AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
+
 
 
 
diff --git a/src/haptic.c b/src/haptic.c
index 7dcdc6c..cf38874 100644
--- a/src/haptic.c
+++ b/src/haptic.c
@@ -33,7 +33,6 @@
 
 /* the active haptic driver */
 static ALLEGRO_HAPTIC_DRIVER *haptic_driver = NULL;
-static ALLEGRO_EVENT_SOURCE   haptic_es;
 
 
 /* Function: al_install_haptic
@@ -55,13 +54,11 @@ bool al_install_haptic(void)
       /* Avoid race condition in case the haptic driver generates an
        * event right after ->init_haptic.
        */
-      _al_event_source_init(&haptic_es);
       if (hapdrv && hapdrv->init_haptic()) {
          haptic_driver = hapdrv;
          _al_add_exit_func(al_uninstall_haptic, "al_uninstall_haptic");
          return true;
       }
-      _al_event_source_free(&haptic_es);
    }
 
    return false;
@@ -76,7 +73,6 @@ void al_uninstall_haptic(void)
    if (haptic_driver) {
       /* perform driver clean up */
       haptic_driver->exit_haptic();
-      _al_event_source_free(&haptic_es);
       haptic_driver = NULL;
    }
 }
@@ -90,149 +86,221 @@ bool al_is_haptic_installed(void)
 }
 
 
-/* Function: al_reconfigure_haptics
+
+
+/* Function: al_is_joystick_haptic
  */
-bool al_reconfigure_haptics(void)
+bool al_is_joystick_haptic(ALLEGRO_JOYSTICK * dev) 
 {
-   if (!haptic_driver)
-      return false;
-   
-   return haptic_driver->reconfigure_haptics();
+  ASSERT(dev);
+
+  return haptic_driver->is_joystick_haptic(dev);
 }
 
+/* Function: al_is_mouse_haptic
+ */
+bool al_is_mouse_haptic(ALLEGRO_MOUSE * mouse) 
+{
+  ASSERT(mouse);
 
+  return haptic_driver->is_mouse_haptic(mouse);
+}
 
-/* Function: al_get_haptic_event_source
+/* Function: al_is_keyboard_haptic
  */
-ALLEGRO_EVENT_SOURCE *al_get_haptic_event_source(void)
+bool al_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev) 
 {
-   if (!haptic_driver)
-      return NULL;
-   return &haptic_es;
+  ASSERT(dev);
+
+  return haptic_driver->is_keyboard_haptic(dev);
 }
 
+/* Function: al_is_display_haptic
+ */
+bool al_is_display_haptic(ALLEGRO_DISPLAY * dev) 
+{
+  ASSERT(dev);
+
+  return haptic_driver->is_display_haptic(dev);
+}
 
 
-void _al_generate_haptic_event(ALLEGRO_EVENT *event)
+/* Function: al_get_haptic_from_joystick
+ */
+ALLEGRO_HAPTIC * al_get_haptic_from_joystick (ALLEGRO_JOYSTICK * dev) 
 {
-   ASSERT(haptic_driver);
-
-   _al_event_source_lock(&haptic_es);
-   if (_al_event_source_needs_to_generate_event(&haptic_es)) {
-      _al_event_source_emit_event(&haptic_es, event);
-   }
-   _al_event_source_unlock(&haptic_es);
+  ASSERT(dev);
+  
+  return haptic_driver->get_from_joystick(dev);
 }
 
+/* Function: al_get_haptic_from_mouse
+ */
+ALLEGRO_HAPTIC * al_get_haptic_from_mouse (ALLEGRO_MOUSE * dev) 
+{
+  ASSERT(dev);
+  
+  return haptic_driver->get_from_mouse(dev);
+}
 
+/* Function: al_get_haptic_from_keyboard
+ */
+ALLEGRO_HAPTIC * al_get_haptic_from_keyboard(ALLEGRO_KEYBOARD * dev) 
+{
+  ASSERT(dev);
+  
+  return haptic_driver->get_from_keyboard(dev);
+}
 
-/* Function: al_get_num_haptics
+/* Function: al_get_haptic_from_display
  */
-int al_get_num_haptics(void)
+ALLEGRO_HAPTIC * al_get_haptic_from_display(ALLEGRO_DISPLAY * dev) 
 {
-   if (haptic_driver)
-      return haptic_driver->num_haptics();
+  ASSERT(dev);
+  
+  return haptic_driver->get_from_display(dev);
+}
 
-   return 0;
+/* Function: al_get_haptic_from_touch_input
+ */
+ALLEGRO_HAPTIC * al_get_haptic_from_touch_input(ALLEGRO_TOUCH_INPUT * dev) {
+  ASSERT(dev);
+  
+  return haptic_driver->get_from_touch_input(dev);
 }
 
+/* Function: al_get_haptic_active
+ */
+bool al_get_haptic_active(ALLEGRO_HAPTIC *hap)
+{
+   ASSERT(hap);
+   
+   return haptic_driver->get_active(hap);
+}
 
 
-/* Function: al_get_haptic
+/* Function: al_get_haptic_flags
  */
-ALLEGRO_HAPTIC * al_get_haptic(int num)
+int al_get_haptic_capabilities(ALLEGRO_HAPTIC *hap)
 {
-   ASSERT(haptic_driver);
-   ASSERT(num >= 0);
+   ASSERT(hap);
 
-   return haptic_driver->get_haptic(num);
+   return haptic_driver->get_capabilities(hap);
 }
 
 
 
-/* Function: al_release_haptic
+/* Function: al_get_haptic_gain
  */
-void al_release_haptic(ALLEGRO_HAPTIC *hap)
+double al_get_haptic_gain (ALLEGRO_HAPTIC * hap) 
 {
-   ASSERT(haptic_driver);
    ASSERT(hap);
-
-   haptic_driver->release_haptic(hap);
+   
+   return haptic_driver->get_gain(hap);
 }
 
+/* Function: al_set_haptic_gain
+ */
+bool al_set_haptic_gain (ALLEGRO_HAPTIC * hap, double gain) 
+{
+  ASSERT(hap);
+     
+  return haptic_driver->set_gain(hap, gain);
+}
 
-
-/* Function: al_get_haptic_active
+/* Function: al_get_num_haptic_effects
  */
-bool al_get_haptic_active(ALLEGRO_HAPTIC *hap)
+int al_get_num_haptic_effects (ALLEGRO_HAPTIC * hap) 
 {
    ASSERT(hap);
 
-   return hap->info.flags;
+   return haptic_driver->get_num_effects(hap);
+}
+
+/* Function: al_is_haptic_effect_ok
+ */
+bool al_is_haptic_effect_ok(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect) 
+{
+  ASSERT(hap);
+     
+  return haptic_driver->is_effect_ok(hap, effect);
 }
 
 
-/* Function: al_get_haptic_num_axes
+/* Function: al_upload_haptic_effect 
  */
-int al_get_haptic_num_axes(ALLEGRO_HAPTIC *hap)
+bool al_upload_haptic_effect(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect,  ALLEGRO_HAPTIC_EFFECT_ID * id) 
 {
-   ASSERT(hap);
+  ASSERT(hap);  
+  
+  return haptic_driver->upload_effect(hap, effect, id);
+}
+
 
-   return hap->info.num_axes;
+/* Function: al_play_haptic_effect
+ */
+bool al_play_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id, int loop) 
+{
+  return haptic_driver->play_effect(id, loop);
 }
 
 
-/* Function: al_get_haptic_flags
+/* Function: al_upload_and_play_haptic_effect
  */
-int al_get_haptic_flags(ALLEGRO_HAPTIC *hap)
+bool al_upload_and_play_haptic_effect 
+(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect , int loop, ALLEGRO_HAPTIC_EFFECT_ID * id) 
 {
-   ASSERT(hap);
+  if (!al_upload_haptic_effect(hap, effect, id)) return false;
+  return al_play_haptic_effect(id, loop);
+}
+
 
-   return haptic_driver->get_haptic_flags(hap);
+/* Function: al_stop_haptic_effect
+ */
+bool al_stop_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id) 
+{
+    return haptic_driver->stop_effect(id);
 }
 
+/* Function: al_stop_all_haptic_effects
+ */
+bool al_stop_all_haptic_effects (ALLEGRO_HAPTIC * hap) 
+{
+  return haptic_driver->stop_all_efects(hap);
+}
 
 
-/* Function: al_get_haptic_name
+/* Function: al_is_haptic_effect_playing
  */
-const char *al_get_haptic_name(ALLEGRO_HAPTIC *hap)
+bool al_is_haptic_effect_playing (ALLEGRO_HAPTIC_EFFECT_ID * id) 
 {
-   ASSERT(hap);
-   return haptic_driver->get_name(hap);
-   return NULL;
+  return haptic_driver->is_effect_playing(id);
 }
 
+
+/* Function: al_rumble_haptic
+ */
+bool al_rumble_haptic (ALLEGRO_HAPTIC * hap,  double intensity, double duration,  ALLEGRO_HAPTIC_EFFECT_ID * id) {
+  ALLEGRO_HAPTIC_EFFECT effect;
+  effect.type                           = ALLEGRO_HAPTIC_RUMBLE;
+  effect.data.rumble.strong_magnitude   = intensity;
+  effect.data.rumble.weak_magnitude     = intensity;  
+  effect.replay.delay                   = 0.0;
+  effect.replay.length                  = duration;
+  return al_upload_and_play_haptic_effect(hap, &effect, 1, id);
+}
+
+
 /*
-AL_FUNC(bool,             al_install_haptic          , (void));
-AL_FUNC(void,             al_uninstall_haptic        , (void));
-AL_FUNC(bool,             al_is_haptic_installed     , (void));
-AL_FUNC(bool,             al_reconfigure_haptic      , (void));
-
-AL_FUNC(int,              al_get_num_haptics         , (void));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic              , (int hapticn));
-AL_FUNC(void,             al_release_haptic          , (ALLEGRO_HAPTIC *));
-AL_FUNC(bool,             al_get_haptic_active       , (ALLEGRO_HAPTIC *));
-AL_FUNC(const char*,      al_get_haptic_name         , (ALLEGRO_HAPTIC *));
-
-AL_FUNC(int,              al_get_haptic_flags        , (ALLEGRO_HAPTIC *)); 
-
-AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
-AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse   , (ALLEGRO_MOUSE *));
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick, (ALLEGRO_JOYSTICK *));
-AL_FUNC(int,              al_get_haptic_num_axes     , (ALLEGRO_HAPTIC *)); 
-AL_FUNC(bool,             al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
-
-AL_FUNC(bool,             al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int * play_id));
-AL_FUNC(bool,             al_play_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id, int loop));
-AL_FUNC(bool,             al_stop_haptic_effect      , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_effect_playing, (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_is_haptic_stopped       , (ALLEGRO_HAPTIC *, int play_id));
-AL_FUNC(bool,             al_rumble_haptic           , (ALLEGRO_HAPTIC *, double intensity, double duration, int * play_id));
-
-
-*/
+ * Function: al_release_haptic_effect 
+ */
+bool al_release_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id) 
+{
+  return haptic_driver->release_effect(id);
+}
+
+
+
 
 
 
diff --git a/src/linux/lhaptic.c b/src/linux/lhaptic.c
index 3d0d69e..a97b030 100644
--- a/src/linux/lhaptic.c
+++ b/src/linux/lhaptic.c
@@ -17,6 +17,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -33,14 +34,17 @@
 #define ALLEGRO_NO_COMPATIBILITY
 
 #include "allegro5/allegro.h"
+#include "allegro5/joystick.h"
 #include "allegro5/haptic.h"
 #include "allegro5/path.h"
 #include "allegro5/platform/alplatf.h"
 #include "allegro5/internal/aintern.h"
 #include "allegro5/internal/aintern_events.h"
 #include "allegro5/internal/aintern_haptic.h"
+#include "allegro5/internal/aintern_ljoynu.h"
 #include "allegro5/platform/aintunix.h"
-#include </home/bjorn/src/allegro/lib/Headers/allegro5/haptic.h>
+
+
 
 
 #if defined(ALLEGRO_HAVE_SYS_INOTIFY_H) && defined(ALLEGRO_HAVE_SYS_TIMERFD_H)
@@ -57,11 +61,17 @@ ALLEGRO_DEBUG_CHANNEL("lhaptic");
  *for everyone" for now. :p */
 #define HAPTICS_BUF_MAX         1000
 
+/* Support at most 16 effects per device. */
+#define HAPTICS_EFFECTS_MAX     16
+
+/* Tests if a bit in a byte array is set. */
+#define test_bit(bit, array)  (array [bit / (sizeof(long) * 8)] & (1 << (bit % (8 * sizeof(long)) )))
+
 
 typedef struct ALLEGRO_HAPTIC_LINUX
 {
+   struct ALLEGRO_HAPTIC parent;
    int in_use;
-   ALLEGRO_HAPTIC parent;
    int config_state;
    bool marked;
    int fd;
@@ -69,6 +79,7 @@ typedef struct ALLEGRO_HAPTIC_LINUX
    int state;
    char name[HAPTICS_BUF_MAX];
    int flags;
+   int effects[HAPTICS_EFFECTS_MAX];
 } ALLEGRO_HAPTIC_LINUX;
 
 
@@ -76,33 +87,34 @@ typedef struct ALLEGRO_HAPTIC_LINUX
 static bool lhap_init_haptic(void);
 static void lhap_exit_haptic(void);
 
-static bool lhap_reconfigure_haptics(void);
-static int lhap_num_haptics(void);
-static ALLEGRO_HAPTIC *lhap_get_haptic(int num);
-static void lhap_release_haptic(ALLEGRO_HAPTIC *hap_);
-
-static int lhap_get_flags(ALLEGRO_HAPTIC *hap_);
-static const char *lhap_get_name(ALLEGRO_HAPTIC *hap_);
 
 
-/* forward declarations 
-static bool lhap_get_active(ALLEGRO_HAPTIC *hap_);
-static void lhap_generate_event(ALLEGRO_HAPTIC_LINUX *joy, int button, ALLEGRO_EVENT_TYPE event_type);
-*/
 
-static bool lhap_get_active(ALLEGRO_HAPTIC *);
-static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE *);
+static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * dev);
 static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK *);
-static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE *);
-static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK *);
-static int               lhap_get_num_axes(ALLEGRO_HAPTIC *); 
-static bool lhap_is_effect_ok(ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *);
-static bool lhap_upload_effect(ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int *);
-static bool lhap_play_effect(ALLEGRO_HAPTIC *, int, int);
-static bool lhap_stop_effect(ALLEGRO_HAPTIC *, int);
-static bool lhap_is_effect_stopped(ALLEGRO_HAPTIC *, int);
-static bool lhap_stop_all_effects(ALLEGRO_HAPTIC *);
-static bool lhap_is_effect_playing(ALLEGRO_HAPTIC *, int);
+static bool lhap_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev);
+static bool lhap_is_display_haptic(ALLEGRO_DISPLAY * dev);
+static bool lhap_is_touch_input_haptic(ALLEGRO_TOUCH_INPUT * dev);
+
+static ALLEGRO_HAPTIC * lhap_get_from_mouse(ALLEGRO_MOUSE *dev);
+static ALLEGRO_HAPTIC * lhap_get_from_joystick(ALLEGRO_JOYSTICK *dev);
+static ALLEGRO_HAPTIC * lhap_get_from_keyboard(ALLEGRO_KEYBOARD *dev);
+static ALLEGRO_HAPTIC * lhap_get_from_display(ALLEGRO_DISPLAY *dev);
+static ALLEGRO_HAPTIC * lhap_get_from_touch_input(ALLEGRO_TOUCH_INPUT *dev);
+
+static bool   lhap_get_active(ALLEGRO_HAPTIC * hap);
+static int    lhap_get_capabilities(ALLEGRO_HAPTIC * dev);   
+static double lhap_get_gain(ALLEGRO_HAPTIC * dev);
+static bool   lhap_set_gain(ALLEGRO_HAPTIC * dev, double);
+static int    lhap_get_num_effects(ALLEGRO_HAPTIC * dev);   
+
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff);
+static bool lhap_upload_effect(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff, ALLEGRO_HAPTIC_EFFECT_ID * id);
+static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loop);
+static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
+static bool lhap_stop_all_effects(ALLEGRO_HAPTIC *dev);
+static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id);
+static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
 
 /* The haptics driver vtable. */
 ALLEGRO_HAPTIC_DRIVER hapdrv_linux = 
@@ -113,32 +125,36 @@ ALLEGRO_HAPTIC_DRIVER hapdrv_linux =
    "Linux haptic(s)",
    lhap_init_haptic,
    lhap_exit_haptic,
-   lhap_reconfigure_haptics,
-   lhap_num_haptics,
-   lhap_get_haptic,
-   lhap_release_haptic,
-   lhap_get_flags,
-   lhap_get_name,
-   lhap_get_active,
+   
    lhap_is_mouse_haptic,
    lhap_is_joystick_haptic,
+   lhap_is_keyboard_haptic,
+   lhap_is_display_haptic,
+   lhap_is_touch_input_haptic,
+      
    lhap_get_from_mouse,
    lhap_get_from_joystick,
-   lhap_get_num_axes,
+   lhap_get_from_keyboard,
+   lhap_get_from_display,
+   lhap_get_from_touch_input,
+   
+   lhap_get_active,
+   lhap_get_capabilities,
+   lhap_get_gain,
+   lhap_set_gain,
+   lhap_get_num_effects,
+   
    lhap_is_effect_ok,
    lhap_upload_effect,
    lhap_play_effect,
    lhap_stop_effect,
-   lhap_is_effect_stopped,
+   lhap_is_effect_playing,
    lhap_stop_all_effects,
-   lhap_is_effect_playing
+   lhap_release_effect
 };
 
-
 ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver = &hapdrv_linux;
 
-
-
 ALLEGRO_HAPTIC_DRIVER *_al_linux_haptic_driver(void)
 {
    return &hapdrv_linux;
@@ -146,144 +162,49 @@ ALLEGRO_HAPTIC_DRIVER *_al_linux_haptic_driver(void)
 
 
 
-static unsigned                 num_haptics = 0;  
+// static unsigned                 num_haptics = 0;  
 /* number of haptics known to the user */
 static ALLEGRO_HAPTIC_LINUX     haptics[HAPTICS_MAX];
-static ALLEGRO_MUTEX          * haptic_mutex;
-#ifdef SUPPORT_HOTPLUG
-
-static int                      haptic_inotify_fd = -1;
-static int                      haptic_timer_fd = -1;
+static ALLEGRO_MUTEX          * haptic_mutex = NULL;
 
-#endif
-
-/* Approach: to find the available haptic devices, scan 
- * the /sys/class/input directory for any directory named eventxxx. 
- * Then read  /sys/class/input/event1/capabilities/ff to find out the 
- * capabilities of the device. If it's 0, then no it doesn't support force feedback.
- * The idea of this approach is that the /dev file doesn' t have to be opened
- * to inspect the existence of the haptic device. 
- */
 
-/*
- * Scans the /sys/class/input/ directory to find any haptic devices and 
- * already sets them up to be used if needed. Returns the amount of haptics found
- * or negative or error.
- */
-int lhap_scan_haptics(void) {
-  char buf[HAPTICS_BUF_MAX];
-  char line[HAPTICS_BUF_MAX];
-  glob_t found;
-  int res;
-  unsigned int index;
-  num_haptics = 0;
+static bool lhap_init_haptic(void) {
+  int index;
+  haptic_mutex = al_create_mutex();
+  if (!haptic_mutex) return false;
   for (index = 0; index < HAPTICS_MAX; index ++) {
-    haptics[index].in_use = 0;
-    haptics[index].fd     = -1;
-  }  
-  res         = glob("/sys/class/input/event*", GLOB_MARK, NULL, &found);
-  if (res == GLOB_NOMATCH) { 
-    globfree(&found);
-    return -ENOENT;
-  }
-  for (index = 0; index < found.gl_pathc; index ++) {
-    int scanres;
-    unsigned int capa = 0, extra = 0;
-    FILE * fin;
-    char * path = found.gl_pathv[index]; 
-    memset(buf, 0, HAPTICS_BUF_MAX);
-    snprintf(buf, HAPTICS_BUF_MAX, "%sdevice/capabilities/ff", path);
-    fin = fopen(buf, "r");
-    if(!fin) {  continue;  }
-    scanres = fscanf(fin, "%u%u", &capa, &extra);
-    fclose(fin);
-    
-    if (capa > 0) { 
-      char * devname = strchr(strchr(path + 1, '/') + 1, '/');
-      /* It's a haptic device. */
-      ALLEGRO_HAPTIC_LINUX * hap = haptics + num_haptics;
-      hap->parent.info.id        = num_haptics;
-      num_haptics++;
-      hap->flags     = capa;
-      snprintf(hap->device_name, HAPTICS_BUF_MAX, "/dev%s", devname);
-      hap->device_name[strlen(hap->device_name) -1] = '\0';
-      snprintf(buf, HAPTICS_BUF_MAX, "%sdevice/name", path);
-      fin = fopen(buf, "r");
-      if (!fin) {  continue;  }
-      if(fgets(line, HAPTICS_BUF_MAX, fin)) {
-        line[HAPTICS_BUF_MAX-1] = '\0';
-        line[strlen(line)]      = '\0';
-        strcpy(hap->name, line);      
-      }
-      fclose(fin);      
-      fprintf(stderr, "Haptic device found: %s (%s) (%s), %d %d %d\n", buf, hap->device_name, hap->name, scanres, capa, extra);
-      
-    }
-    
+    haptics[index].in_use = false;
   }
-  globfree(&found);  
-  return num_haptics;
-} 
-
-
-bool lhap_init_haptic(void) {
-  return lhap_scan_haptics() >= 0;
-}
-
-
-void lhap_exit_haptic() {
-   return;
-}
-
-static bool lhap_reconfigure_haptics(void){
-  return 0;
-}
-
-int lhap_num_haptics() {
-  return num_haptics;
+  
+  return true;
 }
 
-ALLEGRO_HAPTIC_LINUX * lhap_al2lin(ALLEGRO_HAPTIC * haptic) {
-  if(!haptic) return NULL;
-  ALLEGRO_HAPTIC_LINUX  * lhap = haptics + haptic->info.id;
-  /* Could also have used offsetof, but, hey... */
-  return lhap;
+static ALLEGRO_HAPTIC_LINUX * lhap_get_available_haptic() {
+  int index;
+  haptic_mutex = al_create_mutex();
+  if(!haptic_mutex) return false;
+  for (index = 0; index < HAPTICS_MAX; index ++) {
+    if(!haptics[index].in_use) {
+      haptics[index].in_use = true;
+      return haptics + index;
+    }
+  }
+  return NULL;
 }
 
-
-void lhap_release_haptic(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX  * lhap = lhap_al2lin(haptic);
-  ASSERT(haptic);
-  if (!lhap->in_use) return;
-  if (lhap->fd < 0) return;
-  close(lhap->fd);
+/* Converts a generic haptic device to a linux specific one. */
+static ALLEGRO_HAPTIC_LINUX * lhap_from_al(ALLEGRO_HAPTIC * hap) {
+  void * ptr = hap;
+  if (!ptr) return NULL;
+  return (ALLEGRO_HAPTIC_LINUX *) (ptr - offsetof(ALLEGRO_HAPTIC_LINUX, parent));
 }
 
 
-ALLEGRO_HAPTIC * lhap_get_haptic(int index) {
-  ALLEGRO_HAPTIC_LINUX * lhap;
-  if(index >= HAPTICS_MAX) return NULL;
-  lhap = haptics + index;
-  if (!lhap->in_use) {
-    lhap->fd     = open(lhap->device_name, O_RDWR);
-    if(lhap->fd < 0 ) return NULL;
-    lhap->in_use = 1;
-    return &lhap->parent;
-  } else {
-    return &lhap->parent;
-  }
-  return NULL;
-}
 
 
-const char * lhap_get_name(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
-  return lhap->name;
-}
-
-int lhap_get_flags(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
-  return lhap->flags;
+static void lhap_exit_haptic() {
+  al_destroy_mutex(haptic_mutex);
+  return;
 }
 
 
@@ -328,13 +249,26 @@ static bool lhap_time2lin(__u16 * res, double sec) {
   
   if (sec < 0.0)        return false; 
   if (sec > 32.767)     return false;
-  return (__u16) round(sec * 1000.0);
+  (*res) = (__u16) round(sec * 1000.0);
+  return true;
 }
 
+/* converts the time in seconds to a linux compatible time. 
+ * Return false if out of bounds. This one allows negative times. */
+static bool lhap_stime2lin(__s16 * res, double sec) {
+  ASSERT(res); 
+  
+  if (sec < -32.767)    return false; 
+  if (sec > 32.767)     return false;
+  (*res) = (__s16) round(sec * 1000.0);
+  return true;
+}
+
+
 /* Converts replay data to linux. */
-static bool lhap_replay2lin(struct ff_replay * lin, ALLEGRO_HAPTIC_REPLAY * al) {
-  if(!lhap_time2lin(&lin.delay, al.delay))  return false;
-  if(!lhap_time2lin(&lin.length, al.length)) return false;
+static bool lhap_replay2lin(struct ff_replay * lin, struct ALLEGRO_HAPTIC_REPLAY * al) {
+  if(!lhap_time2lin(&lin->delay, al->delay))  return false;
+  if(!lhap_time2lin(&lin->length, al->length)) return false;
   return true;
 }
 
@@ -344,96 +278,450 @@ static bool lhap_level2lin(__u16 * res, double level) {
   ASSERT(res);   
   if (level < 0.0)        return false; 
   if (level > 1.0)        return false;
-  return (__u16) round(level * ((double) 0x7fff));
+  (*res) = (__u16) round(level * ((double) 0x7fff));
+  return true;
+}
+
+
+/* Converts the level in range -1.0 to 1.0 to a linux compatible level. 
+ * Returns false if out of bounds. */
+static bool lhap_slevel2lin(__s16 * res, double level) {
+  ASSERT(res);   
+  if (level < -1.0)        return false; 
+  if (level > 1.0)        return false;
+  (*res) = (__s16) round(level * ((double) 0x7ffe));
+  return true;
+}
+
+
+/* Converts an allegro haptic effect envelope to the linux structure. */
+static bool lhap_envelope2lin(struct ff_envelope * lin, struct ALLEGRO_HAPTIC_ENVELOPE * al) {
+  if (!lhap_time2lin(&lin->attack_length, al->attack_length)) return false;
+  if (!lhap_time2lin(&lin->fade_length  , al->fade_length)) return false;
+  if (!lhap_level2lin(&lin->attack_level, al->attack_level)) return false;
+  if (!lhap_level2lin(&lin->fade_level, al->fade_level)) return false;
+  return true;
 }
 
 /* Converts a rumble effect to linux. */
-static bool lhap_rumble2lin(struct ff_rumble_effect * lin, ALLEGRO_HAPTIC_RUMBLE_EFFECT * al) {
+static bool lhap_rumble2lin(struct ff_rumble_effect * lin, struct ALLEGRO_HAPTIC_RUMBLE_EFFECT * al) {
   if(!lhap_level2lin(&lin->strong_magnitude, al->strong_magnitude)) return false;
   if(!lhap_level2lin(&lin->weak_magnitude  , al->weak_magnitude)) return false;
   return true;
 }
 
+
+/* Converts a constant effect to linux. */
+static bool lhap_constant2lin(struct ff_constant_effect * lin, struct ALLEGRO_HAPTIC_CONSTANT_EFFECT * al) {
+  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
+  if(!lhap_slevel2lin(&lin->level, al->level)) return false;  
+  return true;
+}
+
+/* Converts a ramp effect to linux. */
+static bool lhap_ramp2lin(struct ff_ramp_effect * lin, struct ALLEGRO_HAPTIC_RAMP_EFFECT * al) {
+  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
+  if(!lhap_slevel2lin(&lin->start_level, al->start_level)) return false;
+  if(!lhap_slevel2lin(&lin->end_level, al->end_level)) return false;
+  return true;
+}
+
+/* Converts a ramp effect to linux. */
+static bool lhap_condition2lin(struct ff_condition_effect * lin, struct ALLEGRO_HAPTIC_CONDITION_EFFECT * al) {
+  if(!lhap_slevel2lin(&lin->center      , al->center)) return false;
+  if(!lhap_level2lin(&lin->deadband    , al->deadband)) return false;
+  if(!lhap_slevel2lin(&lin->right_coeff , al->right_coeff)) return false;
+  if(!lhap_level2lin(&lin->right_saturation , al->right_saturation)) return false;  
+  if(!lhap_slevel2lin(&lin->left_coeff  , al->left_coeff)) return false;
+  if(!lhap_level2lin(&lin->left_saturation , al->left_saturation)) return false;
+  return true;
+}
+
+
 /* converts a periodic effect  to linux */
-static bool lhap_periodic2lin(struct ff_periodic_effect * lin, ALLEGRO_HAPTIC_PERIODIC_EFFECT * al) {
-  
+static bool lhap_periodic2lin(struct ff_periodic_effect * lin, struct ALLEGRO_HAPTIC_PERIODIC_EFFECT * al) {
+  if(!lhap_slevel2lin(&lin->magnitude, al->magnitude)) return false;
+  if(!lhap_stime2lin(&lin->offset, al->offset)) return false;
+  if(!lhap_time2lin(&lin->period, al->period)) return false;
+  if(!lhap_time2lin(&lin->phase, al->phase)) return false;
+  if(!lhap_wave2lin(&lin->waveform, al->waveform)) return false; 
+  if (al->custom_data) {
+    /* Custom data is not supported yet, because currently no Linux 
+     * haptic driver supports it. 
+     */
+    return false;
+  }
+  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
   return true;
 }
 
 /* Converts allegro haptic effect to linux haptic effect. */
 static bool lhap_effect2lin(struct ff_effect * lin, ALLEGRO_HAPTIC_EFFECT * al) {
-  if(!lhap_type2lin(&lin->type, al->type,) return false;
+  if(!lhap_type2lin(&lin->type, al->type)) return false;
   /* lin_effect->replay = effect->re; */
   lin->direction = (__u16) round(((double)0xC000 * al->direction.angle) / (2 * M_PI));
   lin->id        = -1;
-  if(!lhap_replay2lin(&lin->replay, &al->replay);
+  if(!lhap_replay2lin(&lin->replay, &al->replay)) return false;
   switch(lin->type) {
     case FF_RUMBLE:
-      if(!lhap_rumble2lin(&lin->rumble, &al->rumble);
+      if(!lhap_rumble2lin(&lin->u.rumble, &al->data.rumble)) return false;
       break;
     case FF_PERIODIC:      
-      if(!lhap_periodic2lin(&lin->periodic, al->data.periodic)) return false;
+      if(!lhap_periodic2lin(&lin->u.periodic, &al->data.periodic)) return false;
       break;
-      
+    case FF_CONSTANT: 
+      if(!lhap_constant2lin(&lin->u.constant, &al->data.constant)) return false;
+      break;
+    
+    case FF_RAMP:
+    if(!lhap_ramp2lin(&lin->u.ramp, &al->data.ramp)) return false;
+      break;
+    
+    case FF_SPRING:
+    case FF_FRICTION:
+    case FF_DAMPER:
+    case FF_INERTIA:      
+      if(!lhap_condition2lin(&lin->u.condition[0],  &al->data.condition)) return false;
+    break;
+    default:
+      return false;      
   }
      
-  return false;
+  return true;
 }
 
 
 
 static bool lhap_get_active(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_al2lin(haptic);
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(haptic);
   return lhap->in_use;
 }
 
 static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * mouse) {
+  (void) mouse;
   return false;
 }
 
+#define LONG_BITS (sizeof(long) * 8)
+#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
+/* Tests if a bit in an array of longs is set. */
+#define TEST_BIT(nr, addr) \
+    (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
+
+bool lhap_fd_can_ff(int fd) 
+{
+  long bitmask[NLONGS(EV_CNT)]   = {0};
+      
+  if (ioctl (fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
+    return false;
+  }
+  if (TEST_BIT(EV_FF, bitmask)) {
+     return true;
+  }
+  return false;
+}
+
+
+
+
 static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK * joy) {
-   return false;
+  // int newfd = -1;
+  ALLEGRO_JOYSTICK_LINUX * ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
+  if (!al_is_joystick_installed())      return false;
+  if (!al_get_joystick_active(joy))     return false;  
+  if (ljoy->fd <= 0)                    return false; 
+  // al_cstr(ljoy->device_name)
+  // newfd = open("/dev/input/event8", O_RDWR);  
+  // close(newfd);
+  return lhap_fd_can_ff(ljoy->fd); 
+}
+
+static bool lhap_is_display_haptic (ALLEGRO_DISPLAY * dev) {
+  (void) dev;
+  return false;
+}
+
+static bool lhap_is_keyboard_haptic (ALLEGRO_KEYBOARD * dev) {
+  (void) dev;
+  return false;
+}
+
+static bool lhap_is_touch_input_haptic (ALLEGRO_TOUCH_INPUT * dev) {
+  (void) dev;
+  return false;
 }
 
-static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE * mouse) {
+
+static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE * mouse) 
+{
+  (void) mouse;
   return NULL;
 }
 
-static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK * joy) {
+
+#define TEST_CAPA(BIT, MASK, CAP, ALCAPA) do { \
+  if (TEST_BIT(FF_PERIODIC, bitmask)) { cap |= ALCAPA; } \
+} while (0)
+  
+
+static bool get_haptic_capabilities(int fd, int * capabilities) {
+
+  int cap = 0;
+  // unsigned long device_bits[(EV_MAX + 8) / sizeof(unsigned long)];  
+  unsigned long bitmask[NLONGS(FF_CNT)]   = {0};
+  if (ioctl (fd, EVIOCGBIT(EV_FF, sizeof(bitmask)), bitmask) < 0) {
+    perror ("EVIOCGBIT ioctl failed");
+    fprintf(stderr, "For fd %d\n", fd);
+    return false;
+  }
+  TEST_CAPA(FF_PERIODIC, bitmask, cap, ALLEGRO_HAPTIC_PERIODIC); 
+  TEST_CAPA(FF_RUMBLE, bitmask, cap, ALLEGRO_HAPTIC_RUMBLE); 
+  TEST_CAPA(FF_CONSTANT, bitmask, cap, ALLEGRO_HAPTIC_CONSTANT);
+  TEST_CAPA(FF_SPRING, bitmask, cap, ALLEGRO_HAPTIC_SPRING); 
+  TEST_CAPA(FF_FRICTION, bitmask, cap, ALLEGRO_HAPTIC_FRICTION);   
+  TEST_CAPA(FF_DAMPER, bitmask, cap, ALLEGRO_HAPTIC_DAMPER);   
+  TEST_CAPA(FF_INERTIA, bitmask, cap, ALLEGRO_HAPTIC_INERTIA); 
+  TEST_CAPA(FF_RAMP, bitmask, cap, ALLEGRO_HAPTIC_RAMP); 
+  TEST_CAPA(FF_SQUARE, bitmask, cap, ALLEGRO_HAPTIC_SQUARE); 
+  TEST_CAPA(FF_TRIANGLE, bitmask, cap, ALLEGRO_HAPTIC_TRIANGLE); 
+  TEST_CAPA(FF_SINE, bitmask, cap, ALLEGRO_HAPTIC_SINE); 
+  TEST_CAPA(FF_SAW_UP, bitmask, cap, ALLEGRO_HAPTIC_SAW_UP); 
+  TEST_CAPA(FF_SAW_DOWN, bitmask, cap, ALLEGRO_HAPTIC_SAW_DOWN); 
+  TEST_CAPA(FF_CUSTOM, bitmask, cap, ALLEGRO_HAPTIC_CUSTOM); 
+  TEST_CAPA(FF_GAIN, bitmask, cap, ALLEGRO_HAPTIC_GAIN); 
+  
+  (*capabilities) = cap;
+  
+  return true;
+}
+
+static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK * joy) 
+{
+  int index;
+  ALLEGRO_HAPTIC_LINUX *lhap;
+  ALLEGRO_JOYSTICK_LINUX * ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
+  
+  if (!al_is_joystick_haptic(joy)) return NULL;  
+  
+  al_lock_mutex(haptic_mutex);
+  
+  lhap = lhap_get_available_haptic();
+  if (!lhap) return NULL;
+  
+  lhap->parent.device = joy; 
+  lhap->parent.from   = _AL_HAPTIC_FROM_JOYSTICK;
+  
+  
+  lhap->fd            = ljoy->fd;
+  lhap->in_use        = true;
+  for (index = 0; index < HAPTICS_EFFECTS_MAX; index ++) {
+    lhap->effects[index] = -1; // negative means not in use. 
+  }
+  lhap->parent.gain   = 1.0;
+  get_haptic_capabilities(lhap->fd, &lhap->flags);
+  al_unlock_mutex(haptic_mutex);
+  return &(lhap->parent);
+}
+
+static ALLEGRO_HAPTIC * lhap_get_from_display (ALLEGRO_DISPLAY * dev) 
+{
+  (void) dev;
   return NULL;
 }
 
-static int lhap_get_num_axes(ALLEGRO_HAPTIC * haptic) {
-  return 1;
+static  ALLEGRO_HAPTIC * lhap_get_from_keyboard (ALLEGRO_KEYBOARD * dev) 
+{
+  (void) dev;
+  return NULL;
 }
 
-static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect) {
-   return false;
+static ALLEGRO_HAPTIC * lhap_get_from_touch_input (ALLEGRO_TOUCH_INPUT * dev) 
+{
+  (void) dev;
+  return NULL;
 }
 
-static bool lhap_upload_effect(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect, int * playid) {
-  return false;
+
+static int lhap_get_capabilities (ALLEGRO_HAPTIC * dev) 
+{
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
+  return lhap->flags;
 }
 
-static bool lhap_play_effect(ALLEGRO_HAPTIC * haptic, int repeats, int playid) {
-  return false;  
+
+static double lhap_get_gain(ALLEGRO_HAPTIC * dev) {
+  (void) dev;
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
+  /* Unfortunately there seems to be no API to GET gain, only to set?! 
+   * So, retururn the stored gain.
+   */
+  return lhap->parent.gain;
 }
 
-static bool lhap_stop_effect(ALLEGRO_HAPTIC * haptic, int playid) {
-  return false;
+static bool lhap_set_gain(ALLEGRO_HAPTIC * dev, double gain) {  
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
+  struct input_event ie ;  
+  lhap->parent.gain     = gain;
+  timerclear(&ie.time); 
+  ie.type     = EV_FF;
+  ie.code     = FF_GAIN;
+  ie.value    =  (__s32)((double)0xFFFF * gain);
+  if (write(lhap->fd, &ie, sizeof(ie)) < 0) {
+    return false;
+  }
+  return true;
 }
 
-static bool lhap_is_effect_stopped(ALLEGRO_HAPTIC * haptic, int playid) {
+int lhap_get_num_effects (ALLEGRO_HAPTIC * dev) {
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
+  int n_effects; /* Number of effects the device can play at the same time */
+  
+  if (ioctl(lhap->fd, EVIOCGEFFECTS, &n_effects) < 0) {
+    perror("Cannot check amount of effects");
+    fprintf(stderr, "on FD %d\n", lhap->fd);
+    return HAPTICS_EFFECTS_MAX;
+  } 
+  if (n_effects > HAPTICS_EFFECTS_MAX) return HAPTICS_EFFECTS_MAX;
+  return n_effects;
+}
+
+
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect) {
+  struct ff_effect leff;
+  int caps = al_get_haptic_capabilities(haptic);
+  if(!((caps & effect->type) == effect->type)) return false;  
+  if(!lhap_effect2lin(&leff, effect)) return false;
+  return true;  
+}
+
+static double lhap_effect_duration(ALLEGRO_HAPTIC_EFFECT * effect) {
+  return effect->replay.delay + effect->replay.length;   
+}
+
+
+static bool lhap_upload_effect(ALLEGRO_HAPTIC * dev, ALLEGRO_HAPTIC_EFFECT * effect, ALLEGRO_HAPTIC_EFFECT_ID * id) { 
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
+  struct ff_effect leff;
+  int index;
+  int found = -1;
+  
+  ASSERT(dev);
+  ASSERT(id);
+  ASSERT(effect);
+  
+  /* set id's values to indicate failure. */
+  id->_haptic   = NULL;
+  id->_effect   = NULL;
+  id->_id       = -1;
+  id->_handle   = -1;
+  
+  
+  if(!lhap_effect2lin(&leff, effect)) { 
+    return false;
+  }
+  
+  leff.id = -1;
+  
+  /* Find empty spot for effect . */
+  for(index = 0; index < al_get_num_haptic_effects(dev); index ++) {
+    if(lhap->effects[index] < 0) {
+      found = index; 
+      break;
+    }
+  }
+  
+  /* No more space for an effect. */
+  if(found < 0) {
+    return false;
+  }
+  
+  /* Upload effect. */
+  if (ioctl(lhap->fd, EVIOCSFF, &leff) < 0 ) {
+    return false;
+  }
+  
+  id->_haptic   = dev;
+  id->_effect   = effect;
+  id->_id       = found;
+  id->_handle   = leff.id;
+  id->_playing  = false;
+    
   return true;
 }
 
-static bool lhap_stop_all_effects(ALLEGRO_HAPTIC * haptic) {
+static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loops) {
+  struct input_event     play;
+  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;    
+  int fd                     ;
+  
+  if(!lhap) return false; 
+  
+  fd = lhap->fd;
+  
+  timerclear(&play.time);
+  play.type     = EV_FF;
+  play.code     = id->_handle; 
+  loops         = (loops < 0 ) ? 1 : loops; 
+  play.value    = loops; /* play: 1, stop: 0 */
+   
+  if (write(fd, (const void*) &play, sizeof(play)) < 0) {    
+    perror("Effect play failed.");
+    return false;
+  }
+  id->_playing = true;
+  id->_started = al_get_time(); 
+  id->_loops   = loops;
+  
+  return true;  
+}
+
+static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
+  struct input_event play;
+  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;    
+  int loops                   = 0;
+  
+  if(!lhap) return false; 
+  
+   
+  play.type     = EV_FF;
+  play.code     = id->_handle; 
+  loops         = (loops < 0 ) ? 1 : loops;
+  
+  if (write(lhap->fd, (const void*) &play, sizeof(play)) < 0) {
+    return false;
+  }
+  id->_playing  = false;
+  return true;   
+}
+
+static bool lhap_stop_all_effects(ALLEGRO_HAPTIC * haptic) {  
+  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) haptic;    
+  
+  
   return false;
 }
 
-static bool lhap_is_effect_playing(ALLEGRO_HAPTIC * haptic, int playid) {
+static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id) {  
+  double duration;
+  ASSERT(id); 
+  
+  if(!id->_playing) return false;
+  /* Since there is no Linux api to test this, use a timer to check if the 
+   effect has been playing longe enough to be finsihed or not. */
+  duration = lhap_effect_duration(id->_effect) * id->_loops;
+  if((id->_started + duration) >= al_get_time()) return true;  
   return false;
 }
 
+static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
+  ALLEGRO_HAPTIC_LINUX * lhap =  (ALLEGRO_HAPTIC_LINUX *) id->_haptic;  
+  lhap_stop_effect(id);
+  
+  if (ioctl(lhap->fd, EVIOCRMFF, id->_handle) < 0) {
+    return false;
+  }  
+  lhap->effects[id->_id] = -1; // negative means not in use.
+  return true;
+}
 
 
-- 
1.7.10.4


From f346297ef68d66ad7d778f610a5da135d9f1a843 Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 24 Jun 2013 11:02:16 +0200
Subject: [PATCH 04/10] Documentation for haptics.

---
 docs/src/refman/haptic.txt |  386 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 386 insertions(+)
 create mode 100644 docs/src/refman/haptic.txt

diff --git a/docs/src/refman/haptic.txt b/docs/src/refman/haptic.txt
new file mode 100644
index 0000000..3913cb0
--- /dev/null
+++ b/docs/src/refman/haptic.txt
@@ -0,0 +1,386 @@
+# Haptic routines
+
+Haptic functions support force feedback and vibration on input devices.
+These functions are declared in the main Allegro header file:
+
+    #include <allegro5/allegro.h>
+
+## API: ALLEGRO_HAPTIC
+
+This is an abstract data type representing a haptic device that supports force 
+feedback or vibration.
+
+See also: [al_get_haptic_from_joystick]
+
+## API: ALLEGRO_HAPTIC_CONSTANTS
+
+This enum contains flags that are used to define haptic effects and capabilities. 
+If the flag is set in the return value of [al_get_haptic_capabilities], it means
+the device supports the given effect. The value of these flags should be set 
+into a [ALLEGRO_HAPTIC_EFFECT] struct to determine what kind of haptic effect 
+should be caused when it is played. 
+
+* ALLEGRO_HAPTIC_RUMBLE       - simple vibration effects
+* ALLEGRO_HAPTIC_PERIODIC     - periodic, wave-form effects
+* ALLEGRO_HAPTIC_CONSTANT     - constant effects
+* ALLEGRO_HAPTIC_SPRING       - spring effects
+* ALLEGRO_HAPTIC_FRICTION     - friction effects
+* ALLEGRO_HAPTIC_DAMPER       - damper effects
+* ALLEGRO_HAPTIC_INERTIA      - inertia effects
+* ALLEGRO_HAPTIC_RAMP         - ramp effects
+* ALLEGRO_HAPTIC_SQUARE       - square wave periodic effect
+* ALLEGRO_HAPTIC_TRIANGLE     - triangle wave periodic effect
+* ALLEGRO_HAPTIC_SINE         - sine wave periodic effect
+* ALLEGRO_HAPTIC_SAW_UP       - upwards saw wave periodic effect
+* ALLEGRO_HAPTIC_SAW_DOWN     - downwards saw wave periodic effect
+* ALLEGRO_HAPTIC_CUSTOM       - custom wave periodic effect
+* ALLEGRO_HAPTIC_GAIN         - the haptic device supports gain setting
+* ALLEGRO_HAPTIC_ANGLE        - the haptic device supports angle coordinates
+* ALLEGRO_HAPTIC_RADIUS       - the haptic device supports radius coordinates
+* ALLEGRO_HAPTIC_AZIMUTH      - the haptic device supports azimuth coordinates
+
+See also: [al_get_haptic_capabilities], [ALLEGRO_HAPTIC_EFFECT]
+
+## API: ALLEGRO_HAPTIC_EFFECT.
+
+This struct models a particular haptic or vibration effect. It needs to be filled 
+correctly in and uploaded to a haptic device, before the device can play it back. 
+
+*Fields:*
+* type - The type of the haptic effect. May be one of the [ALLEGRO_HAPTIC_CONSTANTS]
+   constants between or equal to [ALLEGRO_HAPTIC_RUMBLE] and [ALLEGRO_HAPTIC_RAMP].
+   
+   If `type` is set to [ALLEGRO_HAPTIC_RUMBLE], then the effect is a simple "rumble" 
+   or vibration effect that shakes the device. In some cases, such as on a mobile 
+   platform, the whole device may shake.
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_PERIODIC], the effect is a shake or 
+   vibration of which the intensity is a periodic wave form. 
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_CONSTANT], the effect is a constant 
+   pressure, motion  or push-back in a certain direction of the axes of the device. 
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_SPRING], the effect is a springy kind of 
+   resistance against motion of the axes of the haptic device. 
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_FRICTION], the effect is a friction kind
+   of resistance against motion of the axes of the haptic device. 
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_DAMPER], the effect is a damper kind
+   of resistance against motion of the axes of the haptic device. 
+   
+   If `type` is set to  [ALLEGRO_HAPTIC_INERTIA], the effect causes inertia or 
+   slowness of motions on the axes of the haptic device. 
+     
+   If `type` is set to  [ALLEGRO_HAPTIC_RAMP], the effect causes a pressure 
+   or push-back that ramps up or down depending on the position of the axis.
+   
+* direction - The direction of location in 3D space where the effect should be 
+   played. Allegro haptic devices model directions in 3D space using spherical 
+   coordinates. However, the haptic device may not support localized effects, or may 
+   not support all coordinate components. 
+   
+   In Allegro's coordinate system, the value in `direction.angle` determines 
+   the planar angle between the effect and the direction of the user who holds the 
+   device, expressed in radians.  So, an effect with an angle 0.0 takes place in 
+   the direction of the user of the  haptic device, and an angle of PI means in the 
+   direction away  from the user. 
+   
+   If [al_get_haptic_capabilities] has the flag [ALLEGRO_HAPTIC_ANGLE] set, 
+   then setting `direction.angle`  is supported. Otherwise,  it is unsupported, 
+   and you should set it to 0.
+   
+   The value in `direction.radius` is a relative value between 0.0 and 1.0 that 
+   determines the relative distance from the center of the haptic device at which 
+   the effect will play back. A value of 0 means that the effect should play back 
+   at the center of the device. A value of 1.0 means that the effect should play 
+   back away from the center as far as is possible.  
+   
+   If [al_get_haptic_capabilities] 
+   has the flag [ALLEGRO_HAPTIC_RADIUS] set,  then setting `direction.radius`  
+   is supported. Otherwise, it is unsupported, and you should set it to 0.
+   
+   The value in `direction.azimuth` determines the elevation angle between the 
+   effect and the plane in which the user is holding the device, expressed in 
+   radians. An effect with an azimuth 0.0 plays back in the plane in which
+   the user is holding the device, an azimuth +PI/2 means the effect plays back 
+   vertically  above the user plane, and an azimuth -PI/2 means the effect plays 
+   back vertically below the user plane.
+   
+   If [al_get_haptic_capabilities] has the flag [ALLEGRO_HAPTIC_AZIMUTH] set, 
+   then setting `direction.azimuth` is supported. Otherwise,  it is unsupported, 
+   and you should set it to 0.   
+   
+* replay - Determines how the effect should be played back. 
+   `replay.length` is the duration in seconds of the effect, and `replay.delay`
+   is the time in seconds that the effect playback should be delayed when playback 
+   is started with [al_play_haptic_effect].
+   
+* data - Determines in detail the parameters of the haptic effect to play back.  
+
+   If `type` is set to [ALLEGRO_HAPTIC_RUMBLE], then `data.rumble.strong_magnitude` 
+   must be set to a relative magnitude between 0.0 and 1.0 to determine how intensely 
+   the "large" rumble motor of the haptic device will vibrate. And 
+   `data.rumble.weak_magnitude` must be set to relative magnitude between 0.0 
+   and 1.0  to determine how intensely the "weak" ruble motor of the haptic device 
+   will vibrate. Not all devices have a "weak" motor, in which case the value set 
+   in `data.rumble.weak_magnitude` will be ignored.
+  
+   If `type` is set to  [ALLEGRO_HAPTIC_PERIODIC], then `data.periodic.waveform` 
+   must be set to one of [ALLEGRO_HAPTIC_SQUARE], [ALLEGRO_HAPTIC_TRIANGLE],
+   [ALLEGRO_HAPTIC_SINE], [ALLEGRO_HAPTIC_SAW_UP], [ALLEGRO_HAPTIC_SAW_DOWN],
+   [ALLEGRO_HAPTIC_CUSTOM]. This will then determine the wave form of the vibration
+   effect that will be played on the haptic device. 
+  
+   In these cases, `data.periodic.period` muust be set to the period in seconds 
+   of the wave form. The field `data.periodic.magnitude must be set to the relative 
+   magnitude of intensity between -1.0 and 1.0 at  which the wave form of the 
+   vibration  will be played back. The field `data.periodic.offset` must be filled 
+   in with the  offset from origin in seconds of the wave form of vibration. And the 
+   field `data.periodic.pahe` is the phase of the wave form of vibration in seconds.
+  
+   If `data.periodic.waveform` is set to [ALLEGRO_HAPTIC_CUSTOM], then 
+   `data.periodic.custom_data` must point to an array of `data.periodic.custom_len`
+   doubles, each with values between -1.0 and 1.0. This value array 
+   will determine the shape of the wave form of the haptic effect. 
+   [ALLEGRO_HAPTIC_CUSTOM] is not supported on some platforms, so use 
+   [al_get_haptic_capabilities] to check if it's available. If not, then 
+   it's a good idea play back a non-cusytom wave effect in stead as a substitute. 
+  
+   If `type` is set to  [ALLEGRO_HAPTIC_CONSTANT], then `data.constant.level` 
+   must be set to a relative intensity value between 0.0 and 1.0 to determine the 
+   intensity of the effect.
+   
+   
+   If `type` is set to  any of [ALLEGRO_HAPTIC_SPRING], [ALLEGRO_HAPTIC_FRICTION], 
+   [ALLEGRO_HAPTIC_DAMPER], [ALLEGRO_HAPTIC_INERTIA], [ALLEGRO_HAPTIC_RAMP], then
+   the `data.condition` struct shuld be filled in. To explain this better, 
+   it's best to keep in mind that this  kind of effects is most useful for 
+   steering-wheel kind of devices, where resistance or inertia should be applied
+   when turning the wheel of the device a certain distance to the right or the left. 
+   
+   The field `data.condition.right_saturation` must be filled in with a relative 
+   magnitude between -1.0 and 1.0 to determine the the intensity of resistance 
+   or inertia on the "right" side of the axis. Likewise, 
+   `data.condition.left_saturation` must be filled in with a relative 
+   magnitude between -1.0 and 1.0 to determine the the intensity of resistance 
+   or inertia on the "left" side of the axis. 
+   
+   The field 'data.condition.deadband' must be filled in with a relative value 
+   between 0.0 and 1.0, to determine the relative width of the "dead band" of the 
+   haptic effect. As long as the axis of the haptic device remains in the 
+   "dead band" area, the effect will not be applied. A value of 0.0 means there is 
+   no dead band, and a value of 1.0 means it applied over the whole range of the 
+   axis in question.   
+   
+   The field 'data.condition.center' must be filled in with a relative value between 
+   -1.0 and 1.0, to determine the relative position of the "center" of the effect 
+   around which the dead band is centered.  It should be set to 0.0 in case 
+   the center should not be shifted.
+   
+   The field `data.condition.right_coef`  and `data.condition.right_left_coef` must 
+   be filled in with a relative  coefficient, that will detemine how quickly the 
+   effect ramps up on the right and  left side. If set to 1.0, then the effect will 
+   be immediately at full intensity when outside of the dead band. If set to 0.0 
+   the effect will not be felt at all.
+
+   If ` type` is set to [ALLEGRO_HAPTIC_RAMP], then `data.ramp.start_level` should 
+   be set to a relative magnitude value between  -1.0 and 1.0 to determine the 
+   initial intensity of the haptic effect. The field  `data.ramp.end_level` should 
+   be set to a relative magnitude value between -1.0 and 1.0 to determine the final  
+   intensity of the haptic effect at the end of playback.
+  
+   If 'type' is set to any of [ALLEGRO_HAPTIC_PERIODIC], [ALLEGRO_HAPTIC_CONSTANT], 
+   [ALLEGRO_HAPTIC_RAMP], then  `data.envelope` determines the "envelope" of 
+   the effect. That is, it determines the duration and intensity for the ramp-up 
+   attack or "fade in" and the ramp-down "fade out" of the effect. 
+  
+   In these cases the field `data.envelope.attack_level` must be set to a relative 
+   value between 0.0 and 1.0 that determines the intensity the effect should have 
+   when it starts playing after `replay.delay` seconds have passed since the playback 
+   started. The field  `data.envelope.attack_length` must be set to the time in seconds 
+   that the effect should  ramp up to the maximum intensity as set by the other 
+   parameters of the effect. If `data.envelope.attack_length` is 0, 
+   then the effect will play immediately at full intensity. 
+  
+   The field `data.envelope.fade_level` must be set to a relative value between 
+   0.0 and 1.0 that determines the intensity the effect should have 
+   when at the moment it stops playing after `replay.length` + 'replay.delay' seconds 
+   have passed since the playback of the effect started. The field 
+   `data.envelope.fade_length` must be set to the time in seconds that the effect 
+   should fade out before it finished playing. If `data.envelope.fade_length` is 0, 
+   then the effect will not fade out.
+  
+   If you don't want to use an envelope, then set all four fields of
+   `data.envelope` to 0.0. The effect will then play back at full intensity 
+   throughout it's playback.
+   
+
+## API: ALLEGRO_HAPTIC_EFFECT_ID
+
+This struct is used as a handle to control playback of a haptic effect.
+The struct should be considered opaque. It's implementation is visible merely to 
+allow allocation by the users of the Allegro library. 
+
+## API: al_install_haptic 
+
+Installs the haptic (force feedback) device subsystem. This must be called before 
+using any other haptic related functions. Returns true if the haptics subsystem
+could be initialized correctly, false if not.
+
+## API: al_uninstall_haptic
+
+Uninstalls the haptic device subsystem.
+
+## API: al_is_haptic_installed
+
+Returns true if the haptic device subsystem is installed, false if not.
+
+## API: al_is_mouse_haptic
+
+Returns true if the mouse has haptic capabilities, false if not.
+
+## API: al_is_keyboard_haptic
+
+Returns true if the keyboard has haptic capabilities, false if not.
+
+## API: al_is_display_haptic
+
+Returns true if the display has haptic capabilities, false if not. To be more 
+precise, this is mainly meant for force feedback that shakes a hand held device,
+such as a phone or a tablet.
+
+## API: al_is_joystick_haptic
+
+Returns true if the joystick has haptic capabilities, false if not.
+
+## API: al_is_touch_input
+
+Returns true if thetouch input device has haptic capabilities, false if not.
+
+
+## API: al_get_haptic_from_mouse
+If the mouse has haptic capabilities, returns the associated haptic device handle. 
+Otherwise returns NULL.
+
+## API: al_get_haptic_from_keyboard
+If the keyboard has haptic capabilities, returns the associated haptic device handle. 
+Otherwise returns NULL.
+
+## API: al_get_haptic_from_display
+If the display has haptic capabilities, returns the associated haptic device handle. 
+Otherwise returns NULL.
+
+## API: al_get_haptic_from_joystick
+If the joystick has haptic capabilities, returns the associated haptic device handle. 
+Otherwise returns NULL. It's neccesary to call this again every time the joystick 
+configuration changes, such as though hot plugging.
+
+## API: al_get_haptic_from_touch_input
+If the touch input device has haptic capabilities, returns the associated haptic 
+device handle. Otherwise returns NULL.
+
+## API: al_release_haptic
+
+Releases the haptic device and it's resources when it's not needed anymore. 
+Should also be used in case the joystick configuration changed, such as when a 
+joystick is hot plugged. 
+
+
+## API:  al_get_haptic_active 
+
+Returns true if the haptic device can currently be used, false if not.
+
+## API:  al_get_haptic_capabilities
+
+Returns an integer with or'ed values from [ALLEGRO_HAPTIC_CONSTANTS], 
+which, if set, indicate that the haptic device supports the given feature. 
+
+## API: al_set_haptic_gain 
+
+Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
+it is as if every effect's intensity is multiplied by it. Gain is a value between 
+0.0 and 1.0. Returns true if set sucessfully, false if not. Only works if 
+[al_get_haptic_capabilities] returns a value that has [ALLEGRO_HAPTIC_GAIN] set. 
+If not, this function returns false, and all effects will be played without any gain 
+influence.
+
+## API: al_get_haptic_gain 
+Returns the current gain of the device. Gain is much like volume for sound, 
+it is as if every effect's intensity is multiplied by it. Gain is a value between 
+0.0 and 1.0. Only works correctly if [al_get_haptic_capabilities] returns a value 
+that has [ALLEGRO_HAPTIC_GAIN] set. If this is not set, this function will simply 
+return 1.0 and all effects will be played without any gain influence.
+
+## API: al_get_num_haptic_effects
+
+Returns the maximum amount of haptic effects that can be uploaded to the device.
+This depends on the platform and the device.
+
+## API: al_is_haptic_effect_ok
+
+Returns true if the haptic device can play the haptic effect as given, false if not.
+The haptic effect must have been filled in completely and correctly.
+
+## API: al_upload_haptic_effect 
+
+Uploads the haptic effect to the device. 
+The haptic effect must have been filled in completely and correctly.
+You must also pass in a pointer to a user allocated [ALLEGRO_HAPTIC_EFFECT_ID]. 
+It it is stored a reference to be used to control playback of the effect. 
+Returns true if the effect was sucesfully uploaded, false if not.
+
+The same haptic effect can be uploaded several times, as long as care is taken to 
+pass in a different [ALLEGRO_HAPTIC_EFFECT_ID].
+
+## API: al_play_haptic_effect 
+
+Plays back a previously uploaded haptic effect. The play_id must be a valid
+[ALLEGRO_HAPTIC_EFFECT_ID] obtained from [al_upload_haptic_effect], 
+[al_upload_and_play_haptic_effect] or [al_rumble_haptic]. 
+
+The haptic effect will be played back loop times in sequence. If loop is less than 
+or equal to 1, then the effect will be played once only. 
+
+This function returns immediately and doesn't wait for the playback to finish. It 
+returns true if the playback was started sucessfully or false ir not.
+
+## API: al_upload_and_play_haptic_effect
+
+Uploads and immediately plays back the haptic effect to the device. Returns 
+true if the upload and playback were sucessful, false if either failed.
+
+See also: [al_upload_haptic_effect], [al_play_haptic_effect]
+
+## API: al_stop_haptic_effect
+
+Stops playing a previously uploaded haptic effect. The play_id must be a valid
+[ALLEGRO_HAPTIC_EFFECT_ID] obtained from [al_upload_haptic_effect], 
+[al_upload_and_play_haptic_effect] or [al_rumble_haptic]. 
+
+## API: al_is_haptic_effect_playing
+
+Returns true if the haptic effect is currently playing. Returns false 
+if the effect has been stopped or if it finsihed playing, or if it has not been 
+played yet. The play_id must be a valid [ALLEGRO_HAPTIC_EFFECT_ID] obtained from 
+[al_upload_haptic_effect], [al_upload_and_play_haptic_effect] or [al_rumble_haptic]. 
+
+## API: al_release_haptic_effect
+
+Releases a previously uploaded haptic effect from the device it has been uploaded 
+to, allowing for other effects to be uploaded. The play_id must be a valid 
+[ALLEGRO_HAPTIC_EFFECT_ID] obtained from [al_upload_haptic_effect], 
+[al_upload_and_play_haptic_effect] or [al_rumble_haptic]. 
+
+## API: al_rumble_haptic
+
+Uploads a simple rumble effect to the haptic device and starts playback immediately.
+The parameter `intensity` is a relative magnitude between 0.0 and 1.0 that 
+determines the intensity of the rumble effect. The `duration` determines the 
+duration of the effect in seconds.  
+
+You must also pass in a pointer to a user allocated [ALLEGRO_HAPTIC_EFFECT_ID]. 
+It it is stored a reference to be used to control playback of the effect. 
+Returns true if the rumble effect was succesfully uploaded and started, false if 
+not.
+
-- 
1.7.10.4


From a9c4f4fbdd33db04fd3d1ce52dc9cc7f36c5293d Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 24 Jun 2013 11:31:46 +0200
Subject: [PATCH 05/10] Documentation for haptics.

---
 docs/Refman.cmake          |    3 +-
 docs/inc.a.html            |   85 ++++++++++++++++++++++++++++++++++++++++++++
 docs/src/refman/haptic.txt |    6 ++--
 3 files changed, 90 insertions(+), 4 deletions(-)
 create mode 100644 docs/inc.a.html

diff --git a/docs/Refman.cmake b/docs/Refman.cmake
index 634359b..869228a 100644
--- a/docs/Refman.cmake
+++ b/docs/Refman.cmake
@@ -13,7 +13,8 @@ set(PAGES
     fshook
     fullscreen_mode
     graphics
-    joystick
+    haptic
+    joystick    
     keyboard
     memory
     misc
diff --git a/docs/inc.a.html b/docs/inc.a.html
new file mode 100644
index 0000000..79c8fee
--- /dev/null
+++ b/docs/inc.a.html
@@ -0,0 +1,85 @@
+<div class="sidebar">
+
+<div>
+<ul>
+<li><a href="index.html"><strong>Contents</strong></a></li>
+<li><a href="config.html">Configuration files</a></li>
+<li><a href="display.html">Display</a></li>
+<li><a href="events.html">Events</a></li>
+<li><a href="file.html">File I/O</a></li>
+<li><a href="fshook.html">Filesystem</a></li>
+<li><a href="fixed.html">Fixed point math</a></li>
+<li><a href="fullscreen_mode.html">Fullscreen modes</a></li>
+<li><a href="graphics.html">Graphics</a></li>
+<li><a href="haptic.html">Haptic</a></li>
+<li><a href="joystick.html">Joystick</a></li>
+<li><a href="keyboard.html">Keyboard</a></li>
+<li><a href="memory.html">Memory</a></li>
+<li><a href="monitor.html">Monitor</a></li>
+<li><a href="mouse.html">Mouse</a></li>
+<li><a href="path.html">Path</a></li>
+<li><a href="shader.html">Shader</a></li>
+<li><a href="state.html">State</a></li>
+<li><a href="system.html">System</a></li>
+<li><a href="threads.html">Threads</a></li>
+<li><a href="time.html">Time</a></li>
+<li><a href="timer.html">Timer</a></li>
+<li><a href="touch.html">Touch input</a></li>
+<li><a href="transformations.html">Transformations</a></li>
+<li><a href="utf8.html">UTF-8</a></li>
+<li><a href="misc.html">Miscellaneous</a></li>
+<li><a href="platform.html">Platform-specific</a></li>
+<li><a href="direct3d.html">Direct3D</a></li>
+<li><a href="opengl.html">OpenGL</a></li>
+</ul>
+<!-- The preceding blank line forces pandoc to terminate the list -->
+</div>
+
+<div>
+<ul>
+<li><a href="index.html#addons"><strong>Addons</strong></a></li>
+<li><a href="audio.html">Audio addon</a></li>
+<li><a href="acodec.html">Audio codecs</a></li>
+<li><a href="color.html">Color addon</a></li>
+<li><a href="font.html">Font addons</a></li>
+<li><a href="image.html">Image I/O addon</a></li>
+<li><a href="main.html">Main addon</a></li>
+<li><a href="memfile.html">Memfile addon</a></li>
+<li><a href="native_dialog.html">Native dialogs addon</a></li>
+<li><a href="physfs.html">PhysicsFS addon</a></li>
+<li><a href="primitives.html">Primitives addon</a></li>
+<li><a href="video.html">Video streaming addon</a></li>
+</ul>
+<!-- The preceding blank line forces pandoc to terminate the list -->
+</div>
+
+<div>
+<ul>
+<li><a href="index_all.html"><strong>Index</strong></a></li>
+</ul>
+<!-- The preceding blank line forces pandoc to terminate the list -->
+</div>
+
+<div class="searchbox">
+<script type="text/javascript">
+function on_search(index, control) {
+    // Note to self: the less-than sign must NOT converted to an entity!
+    // SCRIPT elements are special.  The HTML validator gives bad advice.
+    for (i = 0; i < search_index.length; i++) {
+        if (search_index[i] == control.keywords[index]) {
+            break;
+        }
+    }
+    location.href = search_urls[i];
+}
+</script>
+Search<br/> <input type="text" name="q" id="q" size="15" autocomplete="off"/><br/>
+<script type="text/javascript"> new autosuggest("q", search_index, null, on_search); </script>
+</div>
+
+</div>
+
+<div class="content">
+
+
+
diff --git a/docs/src/refman/haptic.txt b/docs/src/refman/haptic.txt
index 3913cb0..f22b94f 100644
--- a/docs/src/refman/haptic.txt
+++ b/docs/src/refman/haptic.txt
@@ -41,7 +41,7 @@ should be caused when it is played.
 
 See also: [al_get_haptic_capabilities], [ALLEGRO_HAPTIC_EFFECT]
 
-## API: ALLEGRO_HAPTIC_EFFECT.
+## API: ALLEGRO_HAPTIC_EFFECT
 
 This struct models a particular haptic or vibration effect. It needs to be filled 
 correctly in and uploaded to a haptic device, before the device can play it back. 
@@ -254,9 +254,9 @@ such as a phone or a tablet.
 
 Returns true if the joystick has haptic capabilities, false if not.
 
-## API: al_is_touch_input
+## API: al_is_touch_input_haptic
 
-Returns true if thetouch input device has haptic capabilities, false if not.
+Returns true if the touch input device has haptic capabilities, false if not.
 
 
 ## API: al_get_haptic_from_mouse
-- 
1.7.10.4


From 53c88879b874028343050617a20309a84bb5d73e Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 24 Jun 2013 12:11:59 +0200
Subject: [PATCH 06/10] Bugfixes and refinements for haptic devices. Still no
 other drivers than Linux.

---
 examples/ex_haptic.c                       |   38 ++++++++--------
 include/allegro5/allegro.h                 |    1 +
 include/allegro5/haptic.h                  |   67 +++++++++++++++-------------
 include/allegro5/internal/aintern_haptic.h |    2 +-
 lib/Headers/allegro5/haptic.h              |   67 +++++++++++++++-------------
 src/haptic.c                               |   19 +++-----
 src/linux/lhaptic.c                        |   39 ++++++++--------
 7 files changed, 122 insertions(+), 111 deletions(-)

diff --git a/examples/ex_haptic.c b/examples/ex_haptic.c
index c8dcf41..d7e1cbf 100644
--- a/examples/ex_haptic.c
+++ b/examples/ex_haptic.c
@@ -1,11 +1,10 @@
 /*
- *    Example program for the Allegro library, by Peter Wang.
+ *    Example program for the Allegro library, by Beoran.
  *
- *    This program tests joystick events.
+ *    This program tests haptic effects.examples/ex_hapti
  */
 
 #include <allegro5/allegro.h>
-#include <allegro5/haptic.h>
 #include <allegro5/allegro_primitives.h>
 
 #include "common.c"
@@ -26,16 +25,14 @@ int main(void)
    ALLEGRO_HAPTIC_EFFECT effect = {0};
    double intensity = 1.0;
    double duration  = 1.0;
+   int num_joysticks;
+
    effect.type                           = ALLEGRO_HAPTIC_RUMBLE;
    effect.data.rumble.strong_magnitude   = intensity;
    effect.data.rumble.weak_magnitude     = intensity;  
    effect.replay.delay                   = 0.1;
-   effect.replay.length                  = duration;
-   
+   effect.replay.length                  = duration;   
    
-   int num_joysticks;
-   double gain = -1.0;
-
    if (!al_init()) {
       abort_example("Could not init Allegro.\n");
    }
@@ -66,27 +63,28 @@ int main(void)
        log_printf("Joystick %s supports force feedback.\n", al_get_joystick_name(joy));
        haptic = al_get_haptic_from_joystick(joy);
        log_printf("Can play back %d haptic effects.\n", al_get_num_haptic_effects(haptic));
-       log_printf("Set gain: %d.\n", al_set_haptic_gain(haptic, 0.8));
+       log_printf("Set gain to 0.8: %d.\n", al_set_haptic_gain(haptic, 0.8));
        log_printf("Get gain: %lf.\n", al_get_haptic_gain(haptic));
        log_printf("Capabilities: %d.\n", al_get_haptic_capabilities(haptic));
-       log_printf("Upload: %d.\n: ", al_upload_haptic_effect(haptic, &effect, &id));
-       log_printf("Play: %d.\n: ", al_play_haptic_effect(&id, 5));
-       // al_rest(1.1 * 5 + 0.5);
+       log_printf("Upload effect: %d.\n ", al_upload_haptic_effect(haptic, &effect, &id));
+       log_printf("Playing effect: %d.\n ", al_play_haptic_effect(&id, 5));
        while (al_is_haptic_effect_playing(&id)) {
-         //log_printf(".");
        }
-       log_printf("Set gain: %d.\n", al_set_haptic_gain(haptic, 0.4));
-       log_printf("Play: %d.\n: ", al_play_haptic_effect(&id, 5));
+       log_printf("Set gain to 0.4: %d.\n", al_set_haptic_gain(haptic, 0.4));
+       log_printf("Get gain: %lf.\n", al_get_haptic_gain(haptic));
+       log_printf("Playing effect again: %d.\n ", al_play_haptic_effect(&id, 5));
+       al_rest(2.0);
+       log_printf("Stopping effect: %d.\n ", al_stop_haptic_effect(&id));
+       
        while (al_is_haptic_effect_playing(&id)) {
          //log_printf(".");
        }
-       log_printf("Release: %d.\n: ", al_release_haptic_effect(&id));
-       
-       log_printf("\nAll done!\n");       
+       log_printf("Release effect: %d.\n ", al_release_haptic_effect(&id));
+       log_printf("Release haptic: %d.\n ", al_release_haptic(haptic));
      }
    }
-   
-   
+          
+   log_printf("\nAll done!\n");       
    close_log(true);
    // al_register_event_source(event_queue, al_get_display_event_source(display));
    // al_register_event_source(event_queue, al_get_haptic_event_source());
diff --git a/include/allegro5/allegro.h b/include/allegro5/allegro.h
index fe33fc8..e1d8f19 100644
--- a/include/allegro5/allegro.h
+++ b/include/allegro5/allegro.h
@@ -59,6 +59,7 @@
 #include "allegro5/touch_input.h"
 #include "allegro5/transformations.h"
 #include "allegro5/utf8.h"
+#include "allegro5/haptic.h"
 
 
 #ifndef ALLEGRO_NO_COMPATIBILITY
diff --git a/include/allegro5/haptic.h b/include/allegro5/haptic.h
index 2e5e1a3..7463bba 100644
--- a/include/allegro5/haptic.h
+++ b/include/allegro5/haptic.h
@@ -28,7 +28,8 @@
 
 /* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_CONSTANTS { 
+enum ALLEGRO_HAPTIC_CONSTANTS 
+{ 
   ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
   ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
   ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
@@ -46,7 +47,7 @@ enum ALLEGRO_HAPTIC_CONSTANTS {
   ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
   ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
   ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
-  ALLEGRO_HAPRIC_AZIMUTH      = 1 << 17,
+  ALLEGRO_HAPTIC_AZIMUTH      = 1 << 17,
 };
 
 
@@ -62,13 +63,14 @@ typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
  * Radius (if supported ) is the distance of the effect from the user 
  * as a value between 0 and 1. Normally it is 0. Radius is only supported if the 
  * device capabilities include ALLEGRO_HAPTIC_RADIUS .  
- * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
- * horizontal plane, -M_PI points down, and M_PI points up.
+ * Azimuth is the angle of elevation, between -M_PI/2 and M_PI/2. 0 points to the 
+ * horizontal plane, -M_PI/2 points down, and M_PI/2 points up.
  * Azimuth is only supported if the device capabilities include 
  * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
-struct ALLEGRO_HAPTIC_DIRECTION {
+struct ALLEGRO_HAPTIC_DIRECTION 
+{
   double angle; 
   double radius;
   double azimuth;
@@ -79,13 +81,15 @@ struct ALLEGRO_HAPTIC_DIRECTION {
  * and 1.0 that mean no effect and full 100% effect. */
 
 /* Delay to start the replay and duration of the replay, expressed  in seconds. */
-struct ALLEGRO_HAPTIC_REPLAY {
+struct ALLEGRO_HAPTIC_REPLAY 
+{
     double length;
     double delay;
 };
 
 /* Envelope of the effect. */
-struct ALLEGRO_HAPTIC_ENVELOPE {
+struct ALLEGRO_HAPTIC_ENVELOPE 
+{
     double attack_length;
     double attack_level;
     double fade_length;
@@ -93,20 +97,23 @@ struct ALLEGRO_HAPTIC_ENVELOPE {
 };
 
 /* Constant effect.  Level is between 0.0 and 1.0. */
-struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
+struct ALLEGRO_HAPTIC_CONSTANT_EFFECT 
+{
     double level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
 /* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
-struct ALLEGRO_HAPTIC_RAMP_EFFECT {
+struct ALLEGRO_HAPTIC_RAMP_EFFECT 
+{
     double start_level;
     double end_level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
 /* Condition effect. */
-struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
+struct ALLEGRO_HAPTIC_CONDITION_EFFECT 
+{
     double right_saturation;
     double left_saturation;
     double right_coeff;
@@ -116,7 +123,8 @@ struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
 };
 
 /* Periodic (wave) effect. */
-struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
+struct ALLEGRO_HAPTIC_PERIODIC_EFFECT 
+{
     int waveform;
     double period;
     double magnitude;
@@ -130,12 +138,14 @@ struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
 
 /* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
  the strong and the weak rumble motors in the haptic device.  */
-struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
+struct ALLEGRO_HAPTIC_RUMBLE_EFFECT 
+{
     double strong_magnitude;
     double weak_magnitude;
 };
 
-union ALLEGRO_HAPTIC_EFFECT_UNION {
+union ALLEGRO_HAPTIC_EFFECT_UNION 
+{
     struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
     struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
     struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
@@ -143,29 +153,26 @@ union ALLEGRO_HAPTIC_EFFECT_UNION {
     struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
 };
 
-/* Type: ALLEGRO_HAPTIC_EFFECT. This neeeds to be filled in and uploaded to
- * the haptic device before it can be played back. 
+/* Type: ALLEGRO_HAPTIC_EFFECT
  */
-struct ALLEGRO_HAPTIC_EFFECT {
-        int                                type;
-        int                                id;
-        struct ALLEGRO_HAPTIC_DIRECTION    direction;
-        struct ALLEGRO_HAPTIC_REPLAY       replay;
-        union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
+struct ALLEGRO_HAPTIC_EFFECT 
+{
+  
+    int                                type;
+    struct ALLEGRO_HAPTIC_DIRECTION    direction;
+    struct ALLEGRO_HAPTIC_REPLAY       replay;
+    union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
 };
 
-
-/* Type: ALLEGRO_HAPTIC_EFFECT
- */
 typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
-
 /* Type: ALLEGRO_HAPTIC_EFFECT_ID
  */
 typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
 
-struct ALLEGRO_HAPTIC_EFFECT_ID {
+struct ALLEGRO_HAPTIC_EFFECT_ID 
+{
   ALLEGRO_HAPTIC        * _haptic;
   ALLEGRO_HAPTIC_EFFECT * _effect;
   int                     _id;
@@ -211,6 +218,10 @@ AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
  * device handle. Otherwise returns NULL. */
 AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
 
+/* Releases the haptic device when it's not needed anymore. Should also be used in 
+ * case the joystick configuration changed, such as when a joystick is hot plugged.  
+ */
+AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
 
 
 
@@ -247,8 +258,6 @@ AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HA
 
 /* Stops playing a haptic effect . */
 AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
-/* Stops playing all haptic effects on this device. */
-AL_FUNC(bool,   al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
 
 /* Returns true if the haptic effect is playing or false if not or if stopped. */
 AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
@@ -257,8 +266,6 @@ AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
  other effects to be uploaded. */
 AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
-
-
 /* Uploads a simple rumble effect to the haptic device and starts playback immediately.
  */
 AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
diff --git a/include/allegro5/internal/aintern_haptic.h b/include/allegro5/internal/aintern_haptic.h
index 548e09f..ebce39c 100644
--- a/include/allegro5/internal/aintern_haptic.h
+++ b/include/allegro5/internal/aintern_haptic.h
@@ -43,8 +43,8 @@ typedef struct ALLEGRO_HAPTIC_DRIVER
    AL_METHOD(bool, play_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *, int));
    AL_METHOD(bool, stop_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *));   
    AL_METHOD(bool, is_effect_playing , (ALLEGRO_HAPTIC_EFFECT_ID *));   
-   AL_METHOD(bool, stop_all_efects   , (ALLEGRO_HAPTIC *));
    AL_METHOD(bool, release_effect    , (ALLEGRO_HAPTIC_EFFECT_ID *));
+   AL_METHOD(bool, release           , (ALLEGRO_HAPTIC *));
    
 } ALLEGRO_HAPTIC_DRIVER;
 
diff --git a/lib/Headers/allegro5/haptic.h b/lib/Headers/allegro5/haptic.h
index 2e5e1a3..7463bba 100644
--- a/lib/Headers/allegro5/haptic.h
+++ b/lib/Headers/allegro5/haptic.h
@@ -28,7 +28,8 @@
 
 /* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_CONSTANTS { 
+enum ALLEGRO_HAPTIC_CONSTANTS 
+{ 
   ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
   ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
   ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
@@ -46,7 +47,7 @@ enum ALLEGRO_HAPTIC_CONSTANTS {
   ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
   ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
   ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
-  ALLEGRO_HAPRIC_AZIMUTH      = 1 << 17,
+  ALLEGRO_HAPTIC_AZIMUTH      = 1 << 17,
 };
 
 
@@ -62,13 +63,14 @@ typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
  * Radius (if supported ) is the distance of the effect from the user 
  * as a value between 0 and 1. Normally it is 0. Radius is only supported if the 
  * device capabilities include ALLEGRO_HAPTIC_RADIUS .  
- * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 
- * horizontal plane, -M_PI points down, and M_PI points up.
+ * Azimuth is the angle of elevation, between -M_PI/2 and M_PI/2. 0 points to the 
+ * horizontal plane, -M_PI/2 points down, and M_PI/2 points up.
  * Azimuth is only supported if the device capabilities include 
  * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
-struct ALLEGRO_HAPTIC_DIRECTION {
+struct ALLEGRO_HAPTIC_DIRECTION 
+{
   double angle; 
   double radius;
   double azimuth;
@@ -79,13 +81,15 @@ struct ALLEGRO_HAPTIC_DIRECTION {
  * and 1.0 that mean no effect and full 100% effect. */
 
 /* Delay to start the replay and duration of the replay, expressed  in seconds. */
-struct ALLEGRO_HAPTIC_REPLAY {
+struct ALLEGRO_HAPTIC_REPLAY 
+{
     double length;
     double delay;
 };
 
 /* Envelope of the effect. */
-struct ALLEGRO_HAPTIC_ENVELOPE {
+struct ALLEGRO_HAPTIC_ENVELOPE 
+{
     double attack_length;
     double attack_level;
     double fade_length;
@@ -93,20 +97,23 @@ struct ALLEGRO_HAPTIC_ENVELOPE {
 };
 
 /* Constant effect.  Level is between 0.0 and 1.0. */
-struct ALLEGRO_HAPTIC_CONSTANT_EFFECT {
+struct ALLEGRO_HAPTIC_CONSTANT_EFFECT 
+{
     double level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
 /* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
-struct ALLEGRO_HAPTIC_RAMP_EFFECT {
+struct ALLEGRO_HAPTIC_RAMP_EFFECT 
+{
     double start_level;
     double end_level;
     struct ALLEGRO_HAPTIC_ENVELOPE envelope;
 };
 
 /* Condition effect. */
-struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
+struct ALLEGRO_HAPTIC_CONDITION_EFFECT 
+{
     double right_saturation;
     double left_saturation;
     double right_coeff;
@@ -116,7 +123,8 @@ struct ALLEGRO_HAPTIC_CONDITION_EFFECT {
 };
 
 /* Periodic (wave) effect. */
-struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
+struct ALLEGRO_HAPTIC_PERIODIC_EFFECT 
+{
     int waveform;
     double period;
     double magnitude;
@@ -130,12 +138,14 @@ struct ALLEGRO_HAPTIC_PERIODIC_EFFECT {
 
 /* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
  the strong and the weak rumble motors in the haptic device.  */
-struct ALLEGRO_HAPTIC_RUMBLE_EFFECT {
+struct ALLEGRO_HAPTIC_RUMBLE_EFFECT 
+{
     double strong_magnitude;
     double weak_magnitude;
 };
 
-union ALLEGRO_HAPTIC_EFFECT_UNION {
+union ALLEGRO_HAPTIC_EFFECT_UNION 
+{
     struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
     struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
     struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
@@ -143,29 +153,26 @@ union ALLEGRO_HAPTIC_EFFECT_UNION {
     struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
 };
 
-/* Type: ALLEGRO_HAPTIC_EFFECT. This neeeds to be filled in and uploaded to
- * the haptic device before it can be played back. 
+/* Type: ALLEGRO_HAPTIC_EFFECT
  */
-struct ALLEGRO_HAPTIC_EFFECT {
-        int                                type;
-        int                                id;
-        struct ALLEGRO_HAPTIC_DIRECTION    direction;
-        struct ALLEGRO_HAPTIC_REPLAY       replay;
-        union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
+struct ALLEGRO_HAPTIC_EFFECT 
+{
+  
+    int                                type;
+    struct ALLEGRO_HAPTIC_DIRECTION    direction;
+    struct ALLEGRO_HAPTIC_REPLAY       replay;
+    union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
 };
 
-
-/* Type: ALLEGRO_HAPTIC_EFFECT
- */
 typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
-
 /* Type: ALLEGRO_HAPTIC_EFFECT_ID
  */
 typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
 
-struct ALLEGRO_HAPTIC_EFFECT_ID {
+struct ALLEGRO_HAPTIC_EFFECT_ID 
+{
   ALLEGRO_HAPTIC        * _haptic;
   ALLEGRO_HAPTIC_EFFECT * _effect;
   int                     _id;
@@ -211,6 +218,10 @@ AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
  * device handle. Otherwise returns NULL. */
 AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
 
+/* Releases the haptic device when it's not needed anymore. Should also be used in 
+ * case the joystick configuration changed, such as when a joystick is hot plugged.  
+ */
+AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
 
 
 
@@ -247,8 +258,6 @@ AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HA
 
 /* Stops playing a haptic effect . */
 AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
-/* Stops playing all haptic effects on this device. */
-AL_FUNC(bool,   al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *));
 
 /* Returns true if the haptic effect is playing or false if not or if stopped. */
 AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
@@ -257,8 +266,6 @@ AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
  other effects to be uploaded. */
 AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
-
-
 /* Uploads a simple rumble effect to the haptic device and starts playback immediately.
  */
 AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
diff --git a/src/haptic.c b/src/haptic.c
index cf38874..2dc0e06 100644
--- a/src/haptic.c
+++ b/src/haptic.c
@@ -86,8 +86,6 @@ bool al_is_haptic_installed(void)
 }
 
 
-
-
 /* Function: al_is_joystick_haptic
  */
 bool al_is_joystick_haptic(ALLEGRO_JOYSTICK * dev) 
@@ -262,14 +260,6 @@ bool al_stop_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id)
     return haptic_driver->stop_effect(id);
 }
 
-/* Function: al_stop_all_haptic_effects
- */
-bool al_stop_all_haptic_effects (ALLEGRO_HAPTIC * hap) 
-{
-  return haptic_driver->stop_all_efects(hap);
-}
-
-
 /* Function: al_is_haptic_effect_playing
  */
 bool al_is_haptic_effect_playing (ALLEGRO_HAPTIC_EFFECT_ID * id) 
@@ -291,8 +281,7 @@ bool al_rumble_haptic (ALLEGRO_HAPTIC * hap,  double intensity, double duration,
 }
 
 
-/*
- * Function: al_release_haptic_effect 
+/* Function: al_release_haptic_effect 
  */
 bool al_release_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id) 
 {
@@ -300,6 +289,12 @@ bool al_release_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id)
 }
 
 
+/* Function: al_release_haptic
+ */
+bool al_release_haptic(ALLEGRO_HAPTIC * haptic) 
+{
+  return haptic_driver->release(haptic);
+}
 
 
 
diff --git a/src/linux/lhaptic.c b/src/linux/lhaptic.c
index a97b030..0b3366f 100644
--- a/src/linux/lhaptic.c
+++ b/src/linux/lhaptic.c
@@ -102,6 +102,8 @@ static ALLEGRO_HAPTIC * lhap_get_from_keyboard(ALLEGRO_KEYBOARD *dev);
 static ALLEGRO_HAPTIC * lhap_get_from_display(ALLEGRO_DISPLAY *dev);
 static ALLEGRO_HAPTIC * lhap_get_from_touch_input(ALLEGRO_TOUCH_INPUT *dev);
 
+static bool lhap_release(ALLEGRO_HAPTIC * haptic);
+
 static bool   lhap_get_active(ALLEGRO_HAPTIC * hap);
 static int    lhap_get_capabilities(ALLEGRO_HAPTIC * dev);   
 static double lhap_get_gain(ALLEGRO_HAPTIC * dev);
@@ -112,7 +114,6 @@ static bool lhap_is_effect_ok(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff);
 static bool lhap_upload_effect(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff, ALLEGRO_HAPTIC_EFFECT_ID * id);
 static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loop);
 static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
-static bool lhap_stop_all_effects(ALLEGRO_HAPTIC *dev);
 static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id);
 static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
 
@@ -149,8 +150,9 @@ ALLEGRO_HAPTIC_DRIVER hapdrv_linux =
    lhap_play_effect,
    lhap_stop_effect,
    lhap_is_effect_playing,
-   lhap_stop_all_effects,
-   lhap_release_effect
+   lhap_release_effect,
+   
+   lhap_release
 };
 
 ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver = &hapdrv_linux;
@@ -199,9 +201,6 @@ static ALLEGRO_HAPTIC_LINUX * lhap_from_al(ALLEGRO_HAPTIC * hap) {
   return (ALLEGRO_HAPTIC_LINUX *) (ptr - offsetof(ALLEGRO_HAPTIC_LINUX, parent));
 }
 
-
-
-
 static void lhap_exit_haptic() {
   al_destroy_mutex(haptic_mutex);
   return;
@@ -675,17 +674,15 @@ static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loops) {
   return true;  
 }
 
+
 static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
   struct input_event play;
   ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;    
-  int loops                   = 0;
-  
   if(!lhap) return false; 
   
-   
   play.type     = EV_FF;
   play.code     = id->_handle; 
-  loops         = (loops < 0 ) ? 1 : loops;
+  play.value    = 0;  
   
   if (write(lhap->fd, (const void*) &play, sizeof(play)) < 0) {
     return false;
@@ -694,20 +691,14 @@ static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
   return true;   
 }
 
-static bool lhap_stop_all_effects(ALLEGRO_HAPTIC * haptic) {  
-  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) haptic;    
-  
-  
-  return false;
-}
 
 static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id) {  
   double duration;
   ASSERT(id); 
   
   if(!id->_playing) return false;
-  /* Since there is no Linux api to test this, use a timer to check if the 
-   effect has been playing longe enough to be finsihed or not. */
+  /* Since AFAICS there is no Linux API to test this, use a timer to check if the 
+   effect has been playing long enough to be finished or not. */
   duration = lhap_effect_duration(id->_effect) * id->_loops;
   if((id->_started + duration) >= al_get_time()) return true;  
   return false;
@@ -725,3 +716,15 @@ static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
 }
 
 
+static bool lhap_release(ALLEGRO_HAPTIC * haptic) {
+  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(haptic);
+  
+  ASSERT(haptic);
+  
+  if(!lhap->in_use) return false;
+  
+  lhap->in_use = false;
+  lhap->fd     = -1;
+  return true;
+}
+
-- 
1.7.10.4


From 2d42545712265104cd5d69250ec49564256b8f67 Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 24 Jun 2013 14:32:32 +0200
Subject: [PATCH 07/10] Small haptic documentation fix.

---
 docs/src/refman/haptic.txt |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/src/refman/haptic.txt b/docs/src/refman/haptic.txt
index f22b94f..026bc83 100644
--- a/docs/src/refman/haptic.txt
+++ b/docs/src/refman/haptic.txt
@@ -327,7 +327,7 @@ The haptic effect must have been filled in completely and correctly.
 Uploads the haptic effect to the device. 
 The haptic effect must have been filled in completely and correctly.
 You must also pass in a pointer to a user allocated [ALLEGRO_HAPTIC_EFFECT_ID]. 
-It it is stored a reference to be used to control playback of the effect. 
+This `id` can be used to control playback of the effect. 
 Returns true if the effect was sucesfully uploaded, false if not.
 
 The same haptic effect can be uploaded several times, as long as care is taken to 
-- 
1.7.10.4


From c427a849036970ee1c10dc3bcbbd694d47bec4d3 Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 1 Jul 2013 15:28:58 +0200
Subject: [PATCH 08/10] Remove spurious spaces that prevented cosumentation
 from being built correctly.

---
 docs/src/refman/haptic.txt |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/docs/src/refman/haptic.txt b/docs/src/refman/haptic.txt
index 026bc83..2029592 100644
--- a/docs/src/refman/haptic.txt
+++ b/docs/src/refman/haptic.txt
@@ -222,7 +222,7 @@ This struct is used as a handle to control playback of a haptic effect.
 The struct should be considered opaque. It's implementation is visible merely to 
 allow allocation by the users of the Allegro library. 
 
-## API: al_install_haptic 
+## API: al_install_haptic
 
 Installs the haptic (force feedback) device subsystem. This must be called before 
 using any other haptic related functions. Returns true if the haptics subsystem
@@ -287,7 +287,7 @@ Should also be used in case the joystick configuration changed, such as when a
 joystick is hot plugged. 
 
 
-## API:  al_get_haptic_active 
+## API:  al_get_haptic_active
 
 Returns true if the haptic device can currently be used, false if not.
 
@@ -296,7 +296,7 @@ Returns true if the haptic device can currently be used, false if not.
 Returns an integer with or'ed values from [ALLEGRO_HAPTIC_CONSTANTS], 
 which, if set, indicate that the haptic device supports the given feature. 
 
-## API: al_set_haptic_gain 
+## API: al_set_haptic_gain
 
 Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
 it is as if every effect's intensity is multiplied by it. Gain is a value between 
@@ -305,7 +305,7 @@ it is as if every effect's intensity is multiplied by it. Gain is a value betwee
 If not, this function returns false, and all effects will be played without any gain 
 influence.
 
-## API: al_get_haptic_gain 
+## API: al_get_haptic_gain
 Returns the current gain of the device. Gain is much like volume for sound, 
 it is as if every effect's intensity is multiplied by it. Gain is a value between 
 0.0 and 1.0. Only works correctly if [al_get_haptic_capabilities] returns a value 
@@ -322,7 +322,7 @@ This depends on the platform and the device.
 Returns true if the haptic device can play the haptic effect as given, false if not.
 The haptic effect must have been filled in completely and correctly.
 
-## API: al_upload_haptic_effect 
+## API: al_upload_haptic_effect
 
 Uploads the haptic effect to the device. 
 The haptic effect must have been filled in completely and correctly.
@@ -333,7 +333,7 @@ Returns true if the effect was sucesfully uploaded, false if not.
 The same haptic effect can be uploaded several times, as long as care is taken to 
 pass in a different [ALLEGRO_HAPTIC_EFFECT_ID].
 
-## API: al_play_haptic_effect 
+## API: al_play_haptic_effect
 
 Plays back a previously uploaded haptic effect. The play_id must be a valid
 [ALLEGRO_HAPTIC_EFFECT_ID] obtained from [al_upload_haptic_effect], 
-- 
1.7.10.4


From e267384a0294c51ba42ca5fce7c172799d46ab84 Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 1 Jul 2013 15:44:21 +0200
Subject: [PATCH 09/10] Apply indent to beautify the haptics sources.

---
 include/allegro5/haptic.h                  |  281 +++----
 include/allegro5/internal/aintern_haptic.h |  109 +--
 lib/Headers/allegro5/haptic.h              |  281 +++----
 src/haptic.c                               |  157 ++--
 src/linux/lhaptic.c                        | 1139 ++++++++++++++++------------
 5 files changed, 1065 insertions(+), 902 deletions(-)

diff --git a/include/allegro5/haptic.h b/include/allegro5/haptic.h
index 7463bba..2ea8467 100644
--- a/include/allegro5/haptic.h
+++ b/include/allegro5/haptic.h
@@ -23,38 +23,39 @@
 #include "allegro5/joystick.h"
 
 #ifdef __cplusplus
-   extern "C" {
+extern "C"
+{
 #endif
 
 /* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_CONSTANTS 
-{ 
-  ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
-  ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
-  ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
-  ALLEGRO_HAPTIC_SPRING       = 1 << 3,
-  ALLEGRO_HAPTIC_FRICTION     = 1 << 4,
-  ALLEGRO_HAPTIC_DAMPER       = 1 << 5,
-  ALLEGRO_HAPTIC_INERTIA      = 1 << 6,
-  ALLEGRO_HAPTIC_RAMP         = 1 << 7,
-  ALLEGRO_HAPTIC_SQUARE       = 1 << 8,
-  ALLEGRO_HAPTIC_TRIANGLE     = 1 << 9,
-  ALLEGRO_HAPTIC_SINE         = 1 << 10,
-  ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
-  ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
-  ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
-  ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
-  ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
-  ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
-  ALLEGRO_HAPTIC_AZIMUTH      = 1 << 17,
-};
+   enum ALLEGRO_HAPTIC_CONSTANTS
+   {
+      ALLEGRO_HAPTIC_RUMBLE = 1 << 0,
+      ALLEGRO_HAPTIC_PERIODIC = 1 << 1,
+      ALLEGRO_HAPTIC_CONSTANT = 1 << 2,
+      ALLEGRO_HAPTIC_SPRING = 1 << 3,
+      ALLEGRO_HAPTIC_FRICTION = 1 << 4,
+      ALLEGRO_HAPTIC_DAMPER = 1 << 5,
+      ALLEGRO_HAPTIC_INERTIA = 1 << 6,
+      ALLEGRO_HAPTIC_RAMP = 1 << 7,
+      ALLEGRO_HAPTIC_SQUARE = 1 << 8,
+      ALLEGRO_HAPTIC_TRIANGLE = 1 << 9,
+      ALLEGRO_HAPTIC_SINE = 1 << 10,
+      ALLEGRO_HAPTIC_SAW_UP = 1 << 11,
+      ALLEGRO_HAPTIC_SAW_DOWN = 1 << 12,
+      ALLEGRO_HAPTIC_CUSTOM = 1 << 13,
+      ALLEGRO_HAPTIC_GAIN = 1 << 14,
+      ALLEGRO_HAPTIC_ANGLE = 1 << 15,
+      ALLEGRO_HAPTIC_RADIUS = 1 << 16,
+      ALLEGRO_HAPTIC_AZIMUTH = 1 << 17,
+   };
 
 
 
 /* Type: ALLEGRO_HAPTIC
  */
-typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
+   typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
 
 /* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
  * An angle 0 means oriented towards the user, M_PI is away from the user 
@@ -69,206 +70,217 @@ typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
  * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
-struct ALLEGRO_HAPTIC_DIRECTION 
-{
-  double angle; 
-  double radius;
-  double azimuth;
-};
+   struct ALLEGRO_HAPTIC_DIRECTION
+   {
+      double angle;
+      double radius;
+      double azimuth;
+   };
 
 /* In all of the following structs, the doubles that express duration represent 
  * time in seconds. The double that represent levels of intensity are between 0.0 
  * and 1.0 that mean no effect and full 100% effect. */
 
 /* Delay to start the replay and duration of the replay, expressed  in seconds. */
-struct ALLEGRO_HAPTIC_REPLAY 
-{
-    double length;
-    double delay;
-};
+   struct ALLEGRO_HAPTIC_REPLAY
+   {
+      double length;
+      double delay;
+   };
 
 /* Envelope of the effect. */
-struct ALLEGRO_HAPTIC_ENVELOPE 
-{
-    double attack_length;
-    double attack_level;
-    double fade_length;
-    double fade_level;
-};
+   struct ALLEGRO_HAPTIC_ENVELOPE
+   {
+      double attack_length;
+      double attack_level;
+      double fade_length;
+      double fade_level;
+   };
 
 /* Constant effect.  Level is between 0.0 and 1.0. */
-struct ALLEGRO_HAPTIC_CONSTANT_EFFECT 
-{
-    double level;
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-};
+   struct ALLEGRO_HAPTIC_CONSTANT_EFFECT
+   {
+      double level;
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+   };
 
 /* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
-struct ALLEGRO_HAPTIC_RAMP_EFFECT 
-{
-    double start_level;
-    double end_level;
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-};
+   struct ALLEGRO_HAPTIC_RAMP_EFFECT
+   {
+      double start_level;
+      double end_level;
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+   };
 
 /* Condition effect. */
-struct ALLEGRO_HAPTIC_CONDITION_EFFECT 
-{
-    double right_saturation;
-    double left_saturation;
-    double right_coeff;
-    double left_coeff;
-    double deadband;
-    double center;
-};
+   struct ALLEGRO_HAPTIC_CONDITION_EFFECT
+   {
+      double right_saturation;
+      double left_saturation;
+      double right_coeff;
+      double left_coeff;
+      double deadband;
+      double center;
+   };
 
 /* Periodic (wave) effect. */
-struct ALLEGRO_HAPTIC_PERIODIC_EFFECT 
-{
-    int waveform;
-    double period;
-    double magnitude;
-    double offset;
-    double phase;
-    
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-    int    custom_len;
-    double *custom_data;
-};
+   struct ALLEGRO_HAPTIC_PERIODIC_EFFECT
+   {
+      int waveform;
+      double period;
+      double magnitude;
+      double offset;
+      double phase;
+
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+      int custom_len;
+      double *custom_data;
+   };
 
 /* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
  the strong and the weak rumble motors in the haptic device.  */
-struct ALLEGRO_HAPTIC_RUMBLE_EFFECT 
-{
-    double strong_magnitude;
-    double weak_magnitude;
-};
-
-union ALLEGRO_HAPTIC_EFFECT_UNION 
-{
-    struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
-    struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
-    struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
-    struct ALLEGRO_HAPTIC_CONDITION_EFFECT  condition; 
-    struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
-};
+   struct ALLEGRO_HAPTIC_RUMBLE_EFFECT
+   {
+      double strong_magnitude;
+      double weak_magnitude;
+   };
+
+   union ALLEGRO_HAPTIC_EFFECT_UNION
+   {
+      struct ALLEGRO_HAPTIC_CONSTANT_EFFECT constant;
+      struct ALLEGRO_HAPTIC_RAMP_EFFECT ramp;
+      struct ALLEGRO_HAPTIC_PERIODIC_EFFECT periodic;
+      struct ALLEGRO_HAPTIC_CONDITION_EFFECT condition;
+      struct ALLEGRO_HAPTIC_RUMBLE_EFFECT rumble;
+   };
 
 /* Type: ALLEGRO_HAPTIC_EFFECT
  */
-struct ALLEGRO_HAPTIC_EFFECT 
-{
-  
-    int                                type;
-    struct ALLEGRO_HAPTIC_DIRECTION    direction;
-    struct ALLEGRO_HAPTIC_REPLAY       replay;
-    union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
-};
+   struct ALLEGRO_HAPTIC_EFFECT
+   {
 
-typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
+      int type;
+      struct ALLEGRO_HAPTIC_DIRECTION direction;
+      struct ALLEGRO_HAPTIC_REPLAY replay;
+      union ALLEGRO_HAPTIC_EFFECT_UNION data;
+   };
+
+   typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
 /* Type: ALLEGRO_HAPTIC_EFFECT_ID
  */
-typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
+   typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
 
-struct ALLEGRO_HAPTIC_EFFECT_ID 
-{
-  ALLEGRO_HAPTIC        * _haptic;
-  ALLEGRO_HAPTIC_EFFECT * _effect;
-  int                     _id;
-  int                     _handle;
-  bool                    _playing;  
-  double                  _started;
-  int                     _loops; 
-};
+   struct ALLEGRO_HAPTIC_EFFECT_ID
+   {
+      ALLEGRO_HAPTIC *_haptic;
+      ALLEGRO_HAPTIC_EFFECT *_effect;
+      int _id;
+      int _handle;
+      bool _playing;
+      double _started;
+      int _loops;
+   };
 
 
 /* Installs the haptic (force feedback) device subsystem. */
-AL_FUNC(bool,             al_install_haptic          , (void));
+    AL_FUNC(bool, al_install_haptic, (void));
 /* Uninstalls the haptic device subsystem. */
-AL_FUNC(void,             al_uninstall_haptic        , (void));
+    AL_FUNC(void, al_uninstall_haptic, (void));
 /* Returns true if the haptic device subsystem is installed, false if not. */
-AL_FUNC(bool,             al_is_haptic_installed     , (void));
+    AL_FUNC(bool, al_is_haptic_installed, (void));
 
 /* Returns true if the mouse has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+    AL_FUNC(bool, al_is_mouse_haptic, (ALLEGRO_MOUSE *));
 /* Returns true if the joystick has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+    AL_FUNC(bool, al_is_joystick_haptic, (ALLEGRO_JOYSTICK *));
 /* Returns true if the keyboard has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_keyboard_haptic      , (ALLEGRO_KEYBOARD *));
+    AL_FUNC(bool, al_is_keyboard_haptic, (ALLEGRO_KEYBOARD *));
 /* Returns true if the display has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_display_haptic       , (ALLEGRO_DISPLAY *));
+    AL_FUNC(bool, al_is_display_haptic, (ALLEGRO_DISPLAY *));
 /* Returns true if the touch input has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_touch_input_haptic   , (ALLEGRO_TOUCH_INPUT *));
+    AL_FUNC(bool, al_is_touch_input_haptic, (ALLEGRO_TOUCH_INPUT *));
 
 
 /* If the mouse has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse    , (ALLEGRO_MOUSE *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse, (ALLEGRO_MOUSE *));
 /* If the mouse has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick , (ALLEGRO_JOYSTICK *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick,
+            (ALLEGRO_JOYSTICK *));
 /* If the keyboard has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard , (ALLEGRO_KEYBOARD *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard,
+            (ALLEGRO_KEYBOARD *));
 /* If the display has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display, (ALLEGRO_DISPLAY *));
 /* If the touch input has haptic capabilities, returns the associated haptic 
  * device handle. Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input,
+            (ALLEGRO_TOUCH_INPUT *));
 
 /* Releases the haptic device when it's not needed anymore. Should also be used in 
  * case the joystick configuration changed, such as when a joystick is hot plugged.  
  */
-AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
+    AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
 
 
 
 /* Returns true if the haptic device can currently be used, false if not.*/
-AL_FUNC(bool,   al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+    AL_FUNC(bool, al_get_haptic_active, (ALLEGRO_HAPTIC *));
 
 /* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if
  set indicate that the haptic device supports the given feature. */
-AL_FUNC(int,    al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
+    AL_FUNC(int, al_get_haptic_capabilities, (ALLEGRO_HAPTIC *));
 
 /* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
  it is as if every effect's intensity is multiplied by it. Gain is a value between 
  0.0 and 1.0. Returns true if set sucessfully, false if not.*/
-AL_FUNC(bool,   al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
+    AL_FUNC(bool, al_set_haptic_gain, (ALLEGRO_HAPTIC *, double gain));
 /* Returns the current gain of the device. */
-AL_FUNC(double, al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
+    AL_FUNC(double, al_get_haptic_gain, (ALLEGRO_HAPTIC *));
 
 
 /* Returns the maximum amount of haptic effects that can be uploaded to the device. */
-AL_FUNC(int,    al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
+    AL_FUNC(int, al_get_num_haptic_effects, (ALLEGRO_HAPTIC *));
 
 /* Returns true if the haptic device can play the haptic effect as given, false if not. */
-AL_FUNC(bool,   al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+    AL_FUNC(bool, al_is_haptic_effect_ok,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
 
 /* Uploads the haptic effect to the device. In play_id, a handle is stored that is 
  a reference to be used to control playback of the effect. */
-AL_FUNC(bool,   al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+    AL_FUNC(bool, al_upload_haptic_effect,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *,
+             ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
 /* Plays back a previously uploaded haptic effect. */
-AL_FUNC(bool,   al_play_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
+    AL_FUNC(bool, al_play_haptic_effect,
+            (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
 
 /* Uploads and immediately plays back the haptic effect to the device. */
-AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+    AL_FUNC(bool, al_upload_and_play_haptic_effect,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop,
+             ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
 /* Stops playing a haptic effect . */
-AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_stop_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Returns true if the haptic effect is playing or false if not or if stopped. */
-AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Releases the haptic effect from the device it has been uploaded to, allowing for 
  other effects to be uploaded. */
-AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Uploads a simple rumble effect to the haptic device and starts playback immediately.
  */
-AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_rumble_haptic,
+            (ALLEGRO_HAPTIC *, double intensity, double duration,
+             ALLEGRO_HAPTIC_EFFECT_ID *));
 
 
 
@@ -279,4 +291,3 @@ AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double du
 #endif
 
 #endif
-
diff --git a/include/allegro5/internal/aintern_haptic.h b/include/allegro5/internal/aintern_haptic.h
index ebce39c..74149e6 100644
--- a/include/allegro5/internal/aintern_haptic.h
+++ b/include/allegro5/internal/aintern_haptic.h
@@ -7,49 +7,54 @@
 #include "allegro5/internal/aintern_events.h"
 
 #ifdef __cplusplus
-   extern "C" {
+extern "C"
+{
 #endif
 
 /* Haptic devices driver virtual table.  */
-typedef struct ALLEGRO_HAPTIC_DRIVER
-{
-   int          hapdrv_id;
-   const char * hapdrv_name;
-   const char * hapdrv_desc;
-   const char * hapdrv_ascii_name;
-   AL_METHOD(bool, init_haptic, (void));
-   AL_METHOD(void, exit_haptic, (void));
-   
-   AL_METHOD(bool, is_mouse_haptic   , (ALLEGRO_MOUSE *));
-   AL_METHOD(bool, is_joystick_haptic, (ALLEGRO_JOYSTICK *));
-   AL_METHOD(bool, is_keyboard_haptic, (ALLEGRO_KEYBOARD *));
-   AL_METHOD(bool, is_display_haptic , (ALLEGRO_DISPLAY *));
-   AL_METHOD(bool, is_touch_input_haptic , (ALLEGRO_TOUCH_INPUT *));
-   
-   AL_METHOD(ALLEGRO_HAPTIC *, get_from_mouse   , (ALLEGRO_MOUSE *));
-   AL_METHOD(ALLEGRO_HAPTIC *, get_from_joystick, (ALLEGRO_JOYSTICK *));
-   AL_METHOD(ALLEGRO_HAPTIC *, get_from_keyboard, (ALLEGRO_KEYBOARD *));
-   AL_METHOD(ALLEGRO_HAPTIC *, get_from_display , (ALLEGRO_DISPLAY *));
-   AL_METHOD(ALLEGRO_HAPTIC *, get_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
-
-   AL_METHOD(bool  , get_active        , (ALLEGRO_HAPTIC *)); 
-   AL_METHOD(int   , get_capabilities  , (ALLEGRO_HAPTIC *));   
-   AL_METHOD(double, get_gain          , (ALLEGRO_HAPTIC *));
-   AL_METHOD(bool  , set_gain          , (ALLEGRO_HAPTIC *, double));
-   AL_METHOD(int   , get_num_effects   , (ALLEGRO_HAPTIC *));   
-   
-   AL_METHOD(bool, is_effect_ok      , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
-   AL_METHOD(bool, upload_effect     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID *));
-   AL_METHOD(bool, play_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *, int));
-   AL_METHOD(bool, stop_effect       , (ALLEGRO_HAPTIC_EFFECT_ID *));   
-   AL_METHOD(bool, is_effect_playing , (ALLEGRO_HAPTIC_EFFECT_ID *));   
-   AL_METHOD(bool, release_effect    , (ALLEGRO_HAPTIC_EFFECT_ID *));
-   AL_METHOD(bool, release           , (ALLEGRO_HAPTIC *));
-   
-} ALLEGRO_HAPTIC_DRIVER;
-
-
-extern ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver;
+   typedef struct ALLEGRO_HAPTIC_DRIVER
+   {
+      int hapdrv_id;
+      const char *hapdrv_name;
+      const char *hapdrv_desc;
+      const char *hapdrv_ascii_name;
+       AL_METHOD(bool, init_haptic, (void));
+       AL_METHOD(void, exit_haptic, (void));
+
+       AL_METHOD(bool, is_mouse_haptic, (ALLEGRO_MOUSE *));
+       AL_METHOD(bool, is_joystick_haptic, (ALLEGRO_JOYSTICK *));
+       AL_METHOD(bool, is_keyboard_haptic, (ALLEGRO_KEYBOARD *));
+       AL_METHOD(bool, is_display_haptic, (ALLEGRO_DISPLAY *));
+       AL_METHOD(bool, is_touch_input_haptic, (ALLEGRO_TOUCH_INPUT *));
+
+       AL_METHOD(ALLEGRO_HAPTIC *, get_from_mouse, (ALLEGRO_MOUSE *));
+       AL_METHOD(ALLEGRO_HAPTIC *, get_from_joystick, (ALLEGRO_JOYSTICK *));
+       AL_METHOD(ALLEGRO_HAPTIC *, get_from_keyboard, (ALLEGRO_KEYBOARD *));
+       AL_METHOD(ALLEGRO_HAPTIC *, get_from_display, (ALLEGRO_DISPLAY *));
+       AL_METHOD(ALLEGRO_HAPTIC *, get_from_touch_input,
+                 (ALLEGRO_TOUCH_INPUT *));
+
+       AL_METHOD(bool, get_active, (ALLEGRO_HAPTIC *));
+       AL_METHOD(int, get_capabilities, (ALLEGRO_HAPTIC *));
+       AL_METHOD(double, get_gain, (ALLEGRO_HAPTIC *));
+       AL_METHOD(bool, set_gain, (ALLEGRO_HAPTIC *, double));
+       AL_METHOD(int, get_num_effects, (ALLEGRO_HAPTIC *));
+
+       AL_METHOD(bool, is_effect_ok,
+                 (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+       AL_METHOD(bool, upload_effect,
+                 (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *,
+                  ALLEGRO_HAPTIC_EFFECT_ID *));
+       AL_METHOD(bool, play_effect, (ALLEGRO_HAPTIC_EFFECT_ID *, int));
+       AL_METHOD(bool, stop_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+       AL_METHOD(bool, is_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
+       AL_METHOD(bool, release_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+       AL_METHOD(bool, release, (ALLEGRO_HAPTIC *));
+
+   } ALLEGRO_HAPTIC_DRIVER;
+
+
+   extern ALLEGRO_HAPTIC_DRIVER *_al_haptic_driver;
 
 
 
@@ -63,11 +68,11 @@ extern ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver;
    };
 
 #define _AL_HAPTIC_INFO_NAME_MAX            256
-   
-/* Can upload at most 32 haptic effects at the same time. */   
-#define _AL_HAPTIC_EFFECT_PLAYBACK_MAX      32    
 
-   
+/* Can upload at most 32 haptic effects at the same time. */
+#define _AL_HAPTIC_EFFECT_PLAYBACK_MAX      32
+
+
 #define _AL_HAPTIC_FROM_JOYSTICK        1
 #define _AL_HAPTIC_FROM_MOUSE           2
 #define _AL_HAPTIC_FROM_KEYBOARD        3
@@ -75,17 +80,17 @@ extern ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver;
 #define _AL_HAPTIC_FROM_TOUCH_INPUT     5
 
 
-struct ALLEGRO_HAPTIC
-{
-  int    from;
-  void * device;
-  double gain;
-};
+   struct ALLEGRO_HAPTIC
+   {
+      int from;
+      void *device;
+      double gain;
+   };
 
-void _al_generate_haptic_event(ALLEGRO_EVENT *event);
+   void _al_generate_haptic_event(ALLEGRO_EVENT * event);
 
 #ifdef __cplusplus
-   }
+}
 #endif
 
 #endif
diff --git a/lib/Headers/allegro5/haptic.h b/lib/Headers/allegro5/haptic.h
index 7463bba..2ea8467 100644
--- a/lib/Headers/allegro5/haptic.h
+++ b/lib/Headers/allegro5/haptic.h
@@ -23,38 +23,39 @@
 #include "allegro5/joystick.h"
 
 #ifdef __cplusplus
-   extern "C" {
+extern "C"
+{
 #endif
 
 /* Enum: ALLEGRO_HAPTIC_CONSTANTS
  */
-enum ALLEGRO_HAPTIC_CONSTANTS 
-{ 
-  ALLEGRO_HAPTIC_RUMBLE       = 1 << 0,
-  ALLEGRO_HAPTIC_PERIODIC     = 1 << 1,
-  ALLEGRO_HAPTIC_CONSTANT     = 1 << 2,
-  ALLEGRO_HAPTIC_SPRING       = 1 << 3,
-  ALLEGRO_HAPTIC_FRICTION     = 1 << 4,
-  ALLEGRO_HAPTIC_DAMPER       = 1 << 5,
-  ALLEGRO_HAPTIC_INERTIA      = 1 << 6,
-  ALLEGRO_HAPTIC_RAMP         = 1 << 7,
-  ALLEGRO_HAPTIC_SQUARE       = 1 << 8,
-  ALLEGRO_HAPTIC_TRIANGLE     = 1 << 9,
-  ALLEGRO_HAPTIC_SINE         = 1 << 10,
-  ALLEGRO_HAPTIC_SAW_UP       = 1 << 11,
-  ALLEGRO_HAPTIC_SAW_DOWN     = 1 << 12,
-  ALLEGRO_HAPTIC_CUSTOM       = 1 << 13,  
-  ALLEGRO_HAPTIC_GAIN         = 1 << 14,   
-  ALLEGRO_HAPTIC_ANGLE        = 1 << 15,
-  ALLEGRO_HAPTIC_RADIUS       = 1 << 16,
-  ALLEGRO_HAPTIC_AZIMUTH      = 1 << 17,
-};
+   enum ALLEGRO_HAPTIC_CONSTANTS
+   {
+      ALLEGRO_HAPTIC_RUMBLE = 1 << 0,
+      ALLEGRO_HAPTIC_PERIODIC = 1 << 1,
+      ALLEGRO_HAPTIC_CONSTANT = 1 << 2,
+      ALLEGRO_HAPTIC_SPRING = 1 << 3,
+      ALLEGRO_HAPTIC_FRICTION = 1 << 4,
+      ALLEGRO_HAPTIC_DAMPER = 1 << 5,
+      ALLEGRO_HAPTIC_INERTIA = 1 << 6,
+      ALLEGRO_HAPTIC_RAMP = 1 << 7,
+      ALLEGRO_HAPTIC_SQUARE = 1 << 8,
+      ALLEGRO_HAPTIC_TRIANGLE = 1 << 9,
+      ALLEGRO_HAPTIC_SINE = 1 << 10,
+      ALLEGRO_HAPTIC_SAW_UP = 1 << 11,
+      ALLEGRO_HAPTIC_SAW_DOWN = 1 << 12,
+      ALLEGRO_HAPTIC_CUSTOM = 1 << 13,
+      ALLEGRO_HAPTIC_GAIN = 1 << 14,
+      ALLEGRO_HAPTIC_ANGLE = 1 << 15,
+      ALLEGRO_HAPTIC_RADIUS = 1 << 16,
+      ALLEGRO_HAPTIC_AZIMUTH = 1 << 17,
+   };
 
 
 
 /* Type: ALLEGRO_HAPTIC
  */
-typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
+   typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
 
 /* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI.
  * An angle 0 means oriented towards the user, M_PI is away from the user 
@@ -69,206 +70,217 @@ typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC;
  * ALLEGRO_HAPTIC_AZIMUTH.
  * 
  */
-struct ALLEGRO_HAPTIC_DIRECTION 
-{
-  double angle; 
-  double radius;
-  double azimuth;
-};
+   struct ALLEGRO_HAPTIC_DIRECTION
+   {
+      double angle;
+      double radius;
+      double azimuth;
+   };
 
 /* In all of the following structs, the doubles that express duration represent 
  * time in seconds. The double that represent levels of intensity are between 0.0 
  * and 1.0 that mean no effect and full 100% effect. */
 
 /* Delay to start the replay and duration of the replay, expressed  in seconds. */
-struct ALLEGRO_HAPTIC_REPLAY 
-{
-    double length;
-    double delay;
-};
+   struct ALLEGRO_HAPTIC_REPLAY
+   {
+      double length;
+      double delay;
+   };
 
 /* Envelope of the effect. */
-struct ALLEGRO_HAPTIC_ENVELOPE 
-{
-    double attack_length;
-    double attack_level;
-    double fade_length;
-    double fade_level;
-};
+   struct ALLEGRO_HAPTIC_ENVELOPE
+   {
+      double attack_length;
+      double attack_level;
+      double fade_length;
+      double fade_level;
+   };
 
 /* Constant effect.  Level is between 0.0 and 1.0. */
-struct ALLEGRO_HAPTIC_CONSTANT_EFFECT 
-{
-    double level;
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-};
+   struct ALLEGRO_HAPTIC_CONSTANT_EFFECT
+   {
+      double level;
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+   };
 
 /* Ramp effect. Both start_level and end level are between 0.0 and 1.0.  */
-struct ALLEGRO_HAPTIC_RAMP_EFFECT 
-{
-    double start_level;
-    double end_level;
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-};
+   struct ALLEGRO_HAPTIC_RAMP_EFFECT
+   {
+      double start_level;
+      double end_level;
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+   };
 
 /* Condition effect. */
-struct ALLEGRO_HAPTIC_CONDITION_EFFECT 
-{
-    double right_saturation;
-    double left_saturation;
-    double right_coeff;
-    double left_coeff;
-    double deadband;
-    double center;
-};
+   struct ALLEGRO_HAPTIC_CONDITION_EFFECT
+   {
+      double right_saturation;
+      double left_saturation;
+      double right_coeff;
+      double left_coeff;
+      double deadband;
+      double center;
+   };
 
 /* Periodic (wave) effect. */
-struct ALLEGRO_HAPTIC_PERIODIC_EFFECT 
-{
-    int waveform;
-    double period;
-    double magnitude;
-    double offset;
-    double phase;
-    
-    struct ALLEGRO_HAPTIC_ENVELOPE envelope;
-    int    custom_len;
-    double *custom_data;
-};
+   struct ALLEGRO_HAPTIC_PERIODIC_EFFECT
+   {
+      int waveform;
+      double period;
+      double magnitude;
+      double offset;
+      double phase;
+
+      struct ALLEGRO_HAPTIC_ENVELOPE envelope;
+      int custom_len;
+      double *custom_data;
+   };
 
 /* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 
  the strong and the weak rumble motors in the haptic device.  */
-struct ALLEGRO_HAPTIC_RUMBLE_EFFECT 
-{
-    double strong_magnitude;
-    double weak_magnitude;
-};
-
-union ALLEGRO_HAPTIC_EFFECT_UNION 
-{
-    struct ALLEGRO_HAPTIC_CONSTANT_EFFECT   constant;
-    struct ALLEGRO_HAPTIC_RAMP_EFFECT       ramp;
-    struct ALLEGRO_HAPTIC_PERIODIC_EFFECT   periodic;
-    struct ALLEGRO_HAPTIC_CONDITION_EFFECT  condition; 
-    struct ALLEGRO_HAPTIC_RUMBLE_EFFECT     rumble;
-};
+   struct ALLEGRO_HAPTIC_RUMBLE_EFFECT
+   {
+      double strong_magnitude;
+      double weak_magnitude;
+   };
+
+   union ALLEGRO_HAPTIC_EFFECT_UNION
+   {
+      struct ALLEGRO_HAPTIC_CONSTANT_EFFECT constant;
+      struct ALLEGRO_HAPTIC_RAMP_EFFECT ramp;
+      struct ALLEGRO_HAPTIC_PERIODIC_EFFECT periodic;
+      struct ALLEGRO_HAPTIC_CONDITION_EFFECT condition;
+      struct ALLEGRO_HAPTIC_RUMBLE_EFFECT rumble;
+   };
 
 /* Type: ALLEGRO_HAPTIC_EFFECT
  */
-struct ALLEGRO_HAPTIC_EFFECT 
-{
-  
-    int                                type;
-    struct ALLEGRO_HAPTIC_DIRECTION    direction;
-    struct ALLEGRO_HAPTIC_REPLAY       replay;
-    union ALLEGRO_HAPTIC_EFFECT_UNION  data; 
-};
+   struct ALLEGRO_HAPTIC_EFFECT
+   {
 
-typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
+      int type;
+      struct ALLEGRO_HAPTIC_DIRECTION direction;
+      struct ALLEGRO_HAPTIC_REPLAY replay;
+      union ALLEGRO_HAPTIC_EFFECT_UNION data;
+   };
+
+   typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT;
 
 
 /* Type: ALLEGRO_HAPTIC_EFFECT_ID
  */
-typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
+   typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID;
 
-struct ALLEGRO_HAPTIC_EFFECT_ID 
-{
-  ALLEGRO_HAPTIC        * _haptic;
-  ALLEGRO_HAPTIC_EFFECT * _effect;
-  int                     _id;
-  int                     _handle;
-  bool                    _playing;  
-  double                  _started;
-  int                     _loops; 
-};
+   struct ALLEGRO_HAPTIC_EFFECT_ID
+   {
+      ALLEGRO_HAPTIC *_haptic;
+      ALLEGRO_HAPTIC_EFFECT *_effect;
+      int _id;
+      int _handle;
+      bool _playing;
+      double _started;
+      int _loops;
+   };
 
 
 /* Installs the haptic (force feedback) device subsystem. */
-AL_FUNC(bool,             al_install_haptic          , (void));
+    AL_FUNC(bool, al_install_haptic, (void));
 /* Uninstalls the haptic device subsystem. */
-AL_FUNC(void,             al_uninstall_haptic        , (void));
+    AL_FUNC(void, al_uninstall_haptic, (void));
 /* Returns true if the haptic device subsystem is installed, false if not. */
-AL_FUNC(bool,             al_is_haptic_installed     , (void));
+    AL_FUNC(bool, al_is_haptic_installed, (void));
 
 /* Returns true if the mouse has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_mouse_haptic         , (ALLEGRO_MOUSE *));
+    AL_FUNC(bool, al_is_mouse_haptic, (ALLEGRO_MOUSE *));
 /* Returns true if the joystick has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_joystick_haptic      , (ALLEGRO_JOYSTICK *));
+    AL_FUNC(bool, al_is_joystick_haptic, (ALLEGRO_JOYSTICK *));
 /* Returns true if the keyboard has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_keyboard_haptic      , (ALLEGRO_KEYBOARD *));
+    AL_FUNC(bool, al_is_keyboard_haptic, (ALLEGRO_KEYBOARD *));
 /* Returns true if the display has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_display_haptic       , (ALLEGRO_DISPLAY *));
+    AL_FUNC(bool, al_is_display_haptic, (ALLEGRO_DISPLAY *));
 /* Returns true if the touch input has haptic capabilities, false if not.*/
-AL_FUNC(bool,             al_is_touch_input_haptic   , (ALLEGRO_TOUCH_INPUT *));
+    AL_FUNC(bool, al_is_touch_input_haptic, (ALLEGRO_TOUCH_INPUT *));
 
 
 /* If the mouse has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse    , (ALLEGRO_MOUSE *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse, (ALLEGRO_MOUSE *));
 /* If the mouse has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick , (ALLEGRO_JOYSTICK *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick,
+            (ALLEGRO_JOYSTICK *));
 /* If the keyboard has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard , (ALLEGRO_KEYBOARD *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard,
+            (ALLEGRO_KEYBOARD *));
 /* If the display has haptic capabilities, returns the associated haptic device handle. 
  * Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display  , (ALLEGRO_DISPLAY *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display, (ALLEGRO_DISPLAY *));
 /* If the touch input has haptic capabilities, returns the associated haptic 
  * device handle. Otherwise returns NULL. */
-AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *));
+    AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input,
+            (ALLEGRO_TOUCH_INPUT *));
 
 /* Releases the haptic device when it's not needed anymore. Should also be used in 
  * case the joystick configuration changed, such as when a joystick is hot plugged.  
  */
-AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
+    AL_FUNC(bool, al_release_haptic, (ALLEGRO_HAPTIC *));
 
 
 
 /* Returns true if the haptic device can currently be used, false if not.*/
-AL_FUNC(bool,   al_get_haptic_active       , (ALLEGRO_HAPTIC *));
+    AL_FUNC(bool, al_get_haptic_active, (ALLEGRO_HAPTIC *));
 
 /* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if
  set indicate that the haptic device supports the given feature. */
-AL_FUNC(int,    al_get_haptic_capabilities , (ALLEGRO_HAPTIC *));
+    AL_FUNC(int, al_get_haptic_capabilities, (ALLEGRO_HAPTIC *));
 
 /* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 
  it is as if every effect's intensity is multiplied by it. Gain is a value between 
  0.0 and 1.0. Returns true if set sucessfully, false if not.*/
-AL_FUNC(bool,   al_set_haptic_gain         , (ALLEGRO_HAPTIC *, double gain));
+    AL_FUNC(bool, al_set_haptic_gain, (ALLEGRO_HAPTIC *, double gain));
 /* Returns the current gain of the device. */
-AL_FUNC(double, al_get_haptic_gain         , (ALLEGRO_HAPTIC *));
+    AL_FUNC(double, al_get_haptic_gain, (ALLEGRO_HAPTIC *));
 
 
 /* Returns the maximum amount of haptic effects that can be uploaded to the device. */
-AL_FUNC(int,    al_get_num_haptic_effects  , (ALLEGRO_HAPTIC *));
+    AL_FUNC(int, al_get_num_haptic_effects, (ALLEGRO_HAPTIC *));
 
 /* Returns true if the haptic device can play the haptic effect as given, false if not. */
-AL_FUNC(bool,   al_is_haptic_effect_ok     , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
+    AL_FUNC(bool, al_is_haptic_effect_ok,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *));
 
 /* Uploads the haptic effect to the device. In play_id, a handle is stored that is 
  a reference to be used to control playback of the effect. */
-AL_FUNC(bool,   al_upload_haptic_effect    , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+    AL_FUNC(bool, al_upload_haptic_effect,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *,
+             ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
 /* Plays back a previously uploaded haptic effect. */
-AL_FUNC(bool,   al_play_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
+    AL_FUNC(bool, al_play_haptic_effect,
+            (ALLEGRO_HAPTIC_EFFECT_ID *, int loop));
 
 /* Uploads and immediately plays back the haptic effect to the device. */
-AL_FUNC(bool,   al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop, ALLEGRO_HAPTIC_EFFECT_ID * play_id));
+    AL_FUNC(bool, al_upload_and_play_haptic_effect,
+            (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop,
+             ALLEGRO_HAPTIC_EFFECT_ID * play_id));
 
 /* Stops playing a haptic effect . */
-AL_FUNC(bool,   al_stop_haptic_effect      , (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_stop_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Returns true if the haptic effect is playing or false if not or if stopped. */
-AL_FUNC(bool,   al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Releases the haptic effect from the device it has been uploaded to, allowing for 
  other effects to be uploaded. */
-AL_FUNC(bool,   al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_release_haptic_effect, (ALLEGRO_HAPTIC_EFFECT_ID *));
 
 /* Uploads a simple rumble effect to the haptic device and starts playback immediately.
  */
-AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double duration, ALLEGRO_HAPTIC_EFFECT_ID *));
+    AL_FUNC(bool, al_rumble_haptic,
+            (ALLEGRO_HAPTIC *, double intensity, double duration,
+             ALLEGRO_HAPTIC_EFFECT_ID *));
 
 
 
@@ -279,4 +291,3 @@ AL_FUNC(bool,   al_rumble_haptic, (ALLEGRO_HAPTIC *, double intensity, double du
 #endif
 
 #endif
-
diff --git a/src/haptic.c b/src/haptic.c
index 2dc0e06..2a2407c 100644
--- a/src/haptic.c
+++ b/src/haptic.c
@@ -88,98 +88,99 @@ bool al_is_haptic_installed(void)
 
 /* Function: al_is_joystick_haptic
  */
-bool al_is_joystick_haptic(ALLEGRO_JOYSTICK * dev) 
+bool al_is_joystick_haptic(ALLEGRO_JOYSTICK * dev)
 {
-  ASSERT(dev);
+   ASSERT(dev);
 
-  return haptic_driver->is_joystick_haptic(dev);
+   return haptic_driver->is_joystick_haptic(dev);
 }
 
 /* Function: al_is_mouse_haptic
  */
-bool al_is_mouse_haptic(ALLEGRO_MOUSE * mouse) 
+bool al_is_mouse_haptic(ALLEGRO_MOUSE * mouse)
 {
-  ASSERT(mouse);
+   ASSERT(mouse);
 
-  return haptic_driver->is_mouse_haptic(mouse);
+   return haptic_driver->is_mouse_haptic(mouse);
 }
 
 /* Function: al_is_keyboard_haptic
  */
-bool al_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev) 
+bool al_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev)
 {
-  ASSERT(dev);
+   ASSERT(dev);
 
-  return haptic_driver->is_keyboard_haptic(dev);
+   return haptic_driver->is_keyboard_haptic(dev);
 }
 
 /* Function: al_is_display_haptic
  */
-bool al_is_display_haptic(ALLEGRO_DISPLAY * dev) 
+bool al_is_display_haptic(ALLEGRO_DISPLAY * dev)
 {
-  ASSERT(dev);
+   ASSERT(dev);
 
-  return haptic_driver->is_display_haptic(dev);
+   return haptic_driver->is_display_haptic(dev);
 }
 
 
 /* Function: al_get_haptic_from_joystick
  */
-ALLEGRO_HAPTIC * al_get_haptic_from_joystick (ALLEGRO_JOYSTICK * dev) 
+ALLEGRO_HAPTIC *al_get_haptic_from_joystick(ALLEGRO_JOYSTICK * dev)
 {
-  ASSERT(dev);
-  
-  return haptic_driver->get_from_joystick(dev);
+   ASSERT(dev);
+
+   return haptic_driver->get_from_joystick(dev);
 }
 
 /* Function: al_get_haptic_from_mouse
  */
-ALLEGRO_HAPTIC * al_get_haptic_from_mouse (ALLEGRO_MOUSE * dev) 
+ALLEGRO_HAPTIC *al_get_haptic_from_mouse(ALLEGRO_MOUSE * dev)
 {
-  ASSERT(dev);
-  
-  return haptic_driver->get_from_mouse(dev);
+   ASSERT(dev);
+
+   return haptic_driver->get_from_mouse(dev);
 }
 
 /* Function: al_get_haptic_from_keyboard
  */
-ALLEGRO_HAPTIC * al_get_haptic_from_keyboard(ALLEGRO_KEYBOARD * dev) 
+ALLEGRO_HAPTIC *al_get_haptic_from_keyboard(ALLEGRO_KEYBOARD * dev)
 {
-  ASSERT(dev);
-  
-  return haptic_driver->get_from_keyboard(dev);
+   ASSERT(dev);
+
+   return haptic_driver->get_from_keyboard(dev);
 }
 
 /* Function: al_get_haptic_from_display
  */
-ALLEGRO_HAPTIC * al_get_haptic_from_display(ALLEGRO_DISPLAY * dev) 
+ALLEGRO_HAPTIC *al_get_haptic_from_display(ALLEGRO_DISPLAY * dev)
 {
-  ASSERT(dev);
-  
-  return haptic_driver->get_from_display(dev);
+   ASSERT(dev);
+
+   return haptic_driver->get_from_display(dev);
 }
 
 /* Function: al_get_haptic_from_touch_input
  */
-ALLEGRO_HAPTIC * al_get_haptic_from_touch_input(ALLEGRO_TOUCH_INPUT * dev) {
-  ASSERT(dev);
-  
-  return haptic_driver->get_from_touch_input(dev);
+ALLEGRO_HAPTIC *al_get_haptic_from_touch_input(ALLEGRO_TOUCH_INPUT * dev)
+{
+   ASSERT(dev);
+
+   return haptic_driver->get_from_touch_input(dev);
 }
 
 /* Function: al_get_haptic_active
  */
-bool al_get_haptic_active(ALLEGRO_HAPTIC *hap)
+bool al_get_haptic_active(ALLEGRO_HAPTIC * hap)
 {
    ASSERT(hap);
-   
+
    return haptic_driver->get_active(hap);
 }
 
 
 /* Function: al_get_haptic_flags
  */
-int al_get_haptic_capabilities(ALLEGRO_HAPTIC *hap)
+int al_get_haptic_capabilities(ALLEGRO_HAPTIC * hap)
 {
    ASSERT(hap);
 
@@ -190,25 +191,25 @@ int al_get_haptic_capabilities(ALLEGRO_HAPTIC *hap)
 
 /* Function: al_get_haptic_gain
  */
-double al_get_haptic_gain (ALLEGRO_HAPTIC * hap) 
+double al_get_haptic_gain(ALLEGRO_HAPTIC * hap)
 {
    ASSERT(hap);
-   
+
    return haptic_driver->get_gain(hap);
 }
 
 /* Function: al_set_haptic_gain
  */
-bool al_set_haptic_gain (ALLEGRO_HAPTIC * hap, double gain) 
+bool al_set_haptic_gain(ALLEGRO_HAPTIC * hap, double gain)
 {
-  ASSERT(hap);
-     
-  return haptic_driver->set_gain(hap, gain);
+   ASSERT(hap);
+
+   return haptic_driver->set_gain(hap, gain);
 }
 
 /* Function: al_get_num_haptic_effects
  */
-int al_get_num_haptic_effects (ALLEGRO_HAPTIC * hap) 
+int al_get_num_haptic_effects(ALLEGRO_HAPTIC * hap)
 {
    ASSERT(hap);
 
@@ -217,86 +218,88 @@ int al_get_num_haptic_effects (ALLEGRO_HAPTIC * hap)
 
 /* Function: al_is_haptic_effect_ok
  */
-bool al_is_haptic_effect_ok(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect) 
+bool al_is_haptic_effect_ok(ALLEGRO_HAPTIC * hap,
+                            ALLEGRO_HAPTIC_EFFECT * effect)
 {
-  ASSERT(hap);
-     
-  return haptic_driver->is_effect_ok(hap, effect);
+   ASSERT(hap);
+
+   return haptic_driver->is_effect_ok(hap, effect);
 }
 
 
 /* Function: al_upload_haptic_effect 
  */
-bool al_upload_haptic_effect(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect,  ALLEGRO_HAPTIC_EFFECT_ID * id) 
+bool al_upload_haptic_effect(ALLEGRO_HAPTIC * hap,
+                             ALLEGRO_HAPTIC_EFFECT * effect,
+                             ALLEGRO_HAPTIC_EFFECT_ID * id)
 {
-  ASSERT(hap);  
-  
-  return haptic_driver->upload_effect(hap, effect, id);
+   ASSERT(hap);
+
+   return haptic_driver->upload_effect(hap, effect, id);
 }
 
 
 /* Function: al_play_haptic_effect
  */
-bool al_play_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id, int loop) 
+bool al_play_haptic_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loop)
 {
-  return haptic_driver->play_effect(id, loop);
+   return haptic_driver->play_effect(id, loop);
 }
 
 
 /* Function: al_upload_and_play_haptic_effect
  */
-bool al_upload_and_play_haptic_effect 
-(ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect , int loop, ALLEGRO_HAPTIC_EFFECT_ID * id) 
+bool al_upload_and_play_haptic_effect
+    (ALLEGRO_HAPTIC * hap, ALLEGRO_HAPTIC_EFFECT * effect, int loop,
+     ALLEGRO_HAPTIC_EFFECT_ID * id)
 {
-  if (!al_upload_haptic_effect(hap, effect, id)) return false;
-  return al_play_haptic_effect(id, loop);
+   if (!al_upload_haptic_effect(hap, effect, id))
+      return false;
+   return al_play_haptic_effect(id, loop);
 }
 
 
 /* Function: al_stop_haptic_effect
  */
-bool al_stop_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id) 
+bool al_stop_haptic_effect(ALLEGRO_HAPTIC_EFFECT_ID * id)
 {
-    return haptic_driver->stop_effect(id);
+   return haptic_driver->stop_effect(id);
 }
 
 /* Function: al_is_haptic_effect_playing
  */
-bool al_is_haptic_effect_playing (ALLEGRO_HAPTIC_EFFECT_ID * id) 
+bool al_is_haptic_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id)
 {
-  return haptic_driver->is_effect_playing(id);
+   return haptic_driver->is_effect_playing(id);
 }
 
 
 /* Function: al_rumble_haptic
  */
-bool al_rumble_haptic (ALLEGRO_HAPTIC * hap,  double intensity, double duration,  ALLEGRO_HAPTIC_EFFECT_ID * id) {
-  ALLEGRO_HAPTIC_EFFECT effect;
-  effect.type                           = ALLEGRO_HAPTIC_RUMBLE;
-  effect.data.rumble.strong_magnitude   = intensity;
-  effect.data.rumble.weak_magnitude     = intensity;  
-  effect.replay.delay                   = 0.0;
-  effect.replay.length                  = duration;
-  return al_upload_and_play_haptic_effect(hap, &effect, 1, id);
+bool al_rumble_haptic(ALLEGRO_HAPTIC * hap, double intensity, double duration,
+                      ALLEGRO_HAPTIC_EFFECT_ID * id)
+{
+   ALLEGRO_HAPTIC_EFFECT effect;
+   effect.type = ALLEGRO_HAPTIC_RUMBLE;
+   effect.data.rumble.strong_magnitude = intensity;
+   effect.data.rumble.weak_magnitude = intensity;
+   effect.replay.delay = 0.0;
+   effect.replay.length = duration;
+   return al_upload_and_play_haptic_effect(hap, &effect, 1, id);
 }
 
 
 /* Function: al_release_haptic_effect 
  */
-bool al_release_haptic_effect (ALLEGRO_HAPTIC_EFFECT_ID * id) 
+bool al_release_haptic_effect(ALLEGRO_HAPTIC_EFFECT_ID * id)
 {
-  return haptic_driver->release_effect(id);
+   return haptic_driver->release_effect(id);
 }
 
 
 /* Function: al_release_haptic
  */
-bool al_release_haptic(ALLEGRO_HAPTIC * haptic) 
+bool al_release_haptic(ALLEGRO_HAPTIC * haptic)
 {
-  return haptic_driver->release(haptic);
+   return haptic_driver->release(haptic);
 }
-
-
-
-
-
diff --git a/src/linux/lhaptic.c b/src/linux/lhaptic.c
index 0b3366f..ab5f0e8 100644
--- a/src/linux/lhaptic.c
+++ b/src/linux/lhaptic.c
@@ -23,9 +23,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <linux/input.h>
-#include <fcntl.h>      
-#include <limits.h>     
-#include <errno.h>      
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
 #include <math.h>
 #include <glob.h>
 
@@ -48,9 +48,9 @@
 
 
 #if defined(ALLEGRO_HAVE_SYS_INOTIFY_H) && defined(ALLEGRO_HAVE_SYS_TIMERFD_H)
-   #define SUPPORT_HOTPLUG
-   #include <sys/inotify.h>
-   #include <sys/timerfd.h>
+#define SUPPORT_HOTPLUG
+#include <sys/inotify.h>
+#include <sys/timerfd.h>
 #endif
 
 ALLEGRO_DEBUG_CHANNEL("lhaptic");
@@ -96,66 +96,68 @@ static bool lhap_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev);
 static bool lhap_is_display_haptic(ALLEGRO_DISPLAY * dev);
 static bool lhap_is_touch_input_haptic(ALLEGRO_TOUCH_INPUT * dev);
 
-static ALLEGRO_HAPTIC * lhap_get_from_mouse(ALLEGRO_MOUSE *dev);
-static ALLEGRO_HAPTIC * lhap_get_from_joystick(ALLEGRO_JOYSTICK *dev);
-static ALLEGRO_HAPTIC * lhap_get_from_keyboard(ALLEGRO_KEYBOARD *dev);
-static ALLEGRO_HAPTIC * lhap_get_from_display(ALLEGRO_DISPLAY *dev);
-static ALLEGRO_HAPTIC * lhap_get_from_touch_input(ALLEGRO_TOUCH_INPUT *dev);
+static ALLEGRO_HAPTIC *lhap_get_from_mouse(ALLEGRO_MOUSE * dev);
+static ALLEGRO_HAPTIC *lhap_get_from_joystick(ALLEGRO_JOYSTICK * dev);
+static ALLEGRO_HAPTIC *lhap_get_from_keyboard(ALLEGRO_KEYBOARD * dev);
+static ALLEGRO_HAPTIC *lhap_get_from_display(ALLEGRO_DISPLAY * dev);
+static ALLEGRO_HAPTIC *lhap_get_from_touch_input(ALLEGRO_TOUCH_INPUT * dev);
 
 static bool lhap_release(ALLEGRO_HAPTIC * haptic);
 
-static bool   lhap_get_active(ALLEGRO_HAPTIC * hap);
-static int    lhap_get_capabilities(ALLEGRO_HAPTIC * dev);   
+static bool lhap_get_active(ALLEGRO_HAPTIC * hap);
+static int lhap_get_capabilities(ALLEGRO_HAPTIC * dev);
 static double lhap_get_gain(ALLEGRO_HAPTIC * dev);
-static bool   lhap_set_gain(ALLEGRO_HAPTIC * dev, double);
-static int    lhap_get_num_effects(ALLEGRO_HAPTIC * dev);   
-
-static bool lhap_is_effect_ok(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff);
-static bool lhap_upload_effect(ALLEGRO_HAPTIC *dev, ALLEGRO_HAPTIC_EFFECT *eff, ALLEGRO_HAPTIC_EFFECT_ID * id);
+static bool lhap_set_gain(ALLEGRO_HAPTIC * dev, double);
+static int lhap_get_num_effects(ALLEGRO_HAPTIC * dev);
+
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * dev,
+                              ALLEGRO_HAPTIC_EFFECT * eff);
+static bool lhap_upload_effect(ALLEGRO_HAPTIC * dev,
+                               ALLEGRO_HAPTIC_EFFECT * eff,
+                               ALLEGRO_HAPTIC_EFFECT_ID * id);
 static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loop);
 static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
 static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id);
 static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id);
 
 /* The haptics driver vtable. */
-ALLEGRO_HAPTIC_DRIVER hapdrv_linux = 
-{
+ALLEGRO_HAPTIC_DRIVER hapdrv_linux = {
    _ALLEGRO_HAPDRV_LINUX,
    "",
    "",
    "Linux haptic(s)",
    lhap_init_haptic,
    lhap_exit_haptic,
-   
+
    lhap_is_mouse_haptic,
    lhap_is_joystick_haptic,
    lhap_is_keyboard_haptic,
    lhap_is_display_haptic,
    lhap_is_touch_input_haptic,
-      
+
    lhap_get_from_mouse,
    lhap_get_from_joystick,
    lhap_get_from_keyboard,
    lhap_get_from_display,
    lhap_get_from_touch_input,
-   
+
    lhap_get_active,
    lhap_get_capabilities,
    lhap_get_gain,
    lhap_set_gain,
    lhap_get_num_effects,
-   
+
    lhap_is_effect_ok,
    lhap_upload_effect,
    lhap_play_effect,
    lhap_stop_effect,
    lhap_is_effect_playing,
    lhap_release_effect,
-   
+
    lhap_release
 };
 
-ALLEGRO_HAPTIC_DRIVER * _al_haptic_driver = &hapdrv_linux;
+ALLEGRO_HAPTIC_DRIVER *_al_haptic_driver = &hapdrv_linux;
 
 ALLEGRO_HAPTIC_DRIVER *_al_linux_haptic_driver(void)
 {
@@ -166,239 +168,339 @@ ALLEGRO_HAPTIC_DRIVER *_al_linux_haptic_driver(void)
 
 // static unsigned                 num_haptics = 0;  
 /* number of haptics known to the user */
-static ALLEGRO_HAPTIC_LINUX     haptics[HAPTICS_MAX];
-static ALLEGRO_MUTEX          * haptic_mutex = NULL;
-
-
-static bool lhap_init_haptic(void) {
-  int index;
-  haptic_mutex = al_create_mutex();
-  if (!haptic_mutex) return false;
-  for (index = 0; index < HAPTICS_MAX; index ++) {
-    haptics[index].in_use = false;
-  }
-  
-  return true;
-}
-
-static ALLEGRO_HAPTIC_LINUX * lhap_get_available_haptic() {
-  int index;
-  haptic_mutex = al_create_mutex();
-  if(!haptic_mutex) return false;
-  for (index = 0; index < HAPTICS_MAX; index ++) {
-    if(!haptics[index].in_use) {
-      haptics[index].in_use = true;
-      return haptics + index;
-    }
-  }
-  return NULL;
-}
+static ALLEGRO_HAPTIC_LINUX haptics[HAPTICS_MAX];
+static ALLEGRO_MUTEX *haptic_mutex = NULL;
 
-/* Converts a generic haptic device to a linux specific one. */
-static ALLEGRO_HAPTIC_LINUX * lhap_from_al(ALLEGRO_HAPTIC * hap) {
-  void * ptr = hap;
-  if (!ptr) return NULL;
-  return (ALLEGRO_HAPTIC_LINUX *) (ptr - offsetof(ALLEGRO_HAPTIC_LINUX, parent));
+
+static bool lhap_init_haptic(void)
+{
+   int index;
+   haptic_mutex = al_create_mutex();
+   if (!haptic_mutex)
+      return false;
+   for (index = 0; index < HAPTICS_MAX; index++) {
+      haptics[index].in_use = false;
+   }
+
+   return true;
 }
 
-static void lhap_exit_haptic() {
-  al_destroy_mutex(haptic_mutex);
-  return;
+static ALLEGRO_HAPTIC_LINUX *lhap_get_available_haptic()
+{
+   int index;
+   haptic_mutex = al_create_mutex();
+   if (!haptic_mutex)
+      return false;
+   for (index = 0; index < HAPTICS_MAX; index++) {
+      if (!haptics[index].in_use) {
+         haptics[index].in_use = true;
+         return haptics + index;
+      }
+   }
+   return NULL;
 }
 
+/* Converts a generic haptic device to a linux specific one. */
+static ALLEGRO_HAPTIC_LINUX *lhap_from_al(ALLEGRO_HAPTIC * hap)
+{
+   void *ptr = hap;
+   if (!ptr)
+      return NULL;
+   return (ALLEGRO_HAPTIC_LINUX *) (ptr -
+                                    offsetof(ALLEGRO_HAPTIC_LINUX, parent));
+}
 
-static bool lhap_type2lin(__u16 * res, int type) {
-  ASSERT(res);
-  
-  switch (type) {
-    case ALLEGRO_HAPTIC_RUMBLE          : (*res) = FF_RUMBLE       ; break;
-    case ALLEGRO_HAPTIC_PERIODIC        : (*res) = FF_PERIODIC     ; break;
-    case ALLEGRO_HAPTIC_CONSTANT        : (*res) = FF_CONSTANT     ; break;
-    case ALLEGRO_HAPTIC_SPRING          : (*res) = FF_SPRING       ; break;
-    case ALLEGRO_HAPTIC_FRICTION        : (*res) = FF_FRICTION     ; break;
-    case ALLEGRO_HAPTIC_DAMPER          : (*res) = FF_DAMPER       ; break;
-    case ALLEGRO_HAPTIC_INERTIA         : (*res) = FF_INERTIA      ; break;
-    case ALLEGRO_HAPTIC_RAMP            : (*res) = FF_RAMP         ; break;
-    default: 
-      return false;
-  }
-  return true;
+static void lhap_exit_haptic()
+{
+   al_destroy_mutex(haptic_mutex);
+   return;
 }
 
-static bool lhap_wave2lin(__u16 * res, int type) {
-  ASSERT(res);
-  
-  switch (type) {
-    case ALLEGRO_HAPTIC_SQUARE          : (*res) = FF_SQUARE       ; break;
-    case ALLEGRO_HAPTIC_TRIANGLE        : (*res) = FF_TRIANGLE     ; break;
-    case ALLEGRO_HAPTIC_SINE            : (*res) = FF_SINE         ; break;
-    case ALLEGRO_HAPTIC_SAW_UP          : (*res) = FF_SAW_UP       ; break;
-    case ALLEGRO_HAPTIC_SAW_DOWN        : (*res) = FF_SAW_DOWN     ; break;
-    case ALLEGRO_HAPTIC_CUSTOM          : (*res) = FF_CUSTOM       ; break;    
-    default: 
-      return false;
-  }
-  return true;
+
+static bool lhap_type2lin(__u16 * res, int type)
+{
+   ASSERT(res);
+
+   switch (type) {
+      case ALLEGRO_HAPTIC_RUMBLE:
+         (*res) = FF_RUMBLE;
+         break;
+      case ALLEGRO_HAPTIC_PERIODIC:
+         (*res) = FF_PERIODIC;
+         break;
+      case ALLEGRO_HAPTIC_CONSTANT:
+         (*res) = FF_CONSTANT;
+         break;
+      case ALLEGRO_HAPTIC_SPRING:
+         (*res) = FF_SPRING;
+         break;
+      case ALLEGRO_HAPTIC_FRICTION:
+         (*res) = FF_FRICTION;
+         break;
+      case ALLEGRO_HAPTIC_DAMPER:
+         (*res) = FF_DAMPER;
+         break;
+      case ALLEGRO_HAPTIC_INERTIA:
+         (*res) = FF_INERTIA;
+         break;
+      case ALLEGRO_HAPTIC_RAMP:
+         (*res) = FF_RAMP;
+         break;
+      default:
+         return false;
+   }
+   return true;
+}
+
+static bool lhap_wave2lin(__u16 * res, int type)
+{
+   ASSERT(res);
+
+   switch (type) {
+      case ALLEGRO_HAPTIC_SQUARE:
+         (*res) = FF_SQUARE;
+         break;
+      case ALLEGRO_HAPTIC_TRIANGLE:
+         (*res) = FF_TRIANGLE;
+         break;
+      case ALLEGRO_HAPTIC_SINE:
+         (*res) = FF_SINE;
+         break;
+      case ALLEGRO_HAPTIC_SAW_UP:
+         (*res) = FF_SAW_UP;
+         break;
+      case ALLEGRO_HAPTIC_SAW_DOWN:
+         (*res) = FF_SAW_DOWN;
+         break;
+      case ALLEGRO_HAPTIC_CUSTOM:
+         (*res) = FF_CUSTOM;
+         break;
+      default:
+         return false;
+   }
+   return true;
 }
 
 /* converts the time in seconds to a linux compatible time. Return false if
  out of bounds. */
-static bool lhap_time2lin(__u16 * res, double sec) {
-  ASSERT(res); 
-  
-  if (sec < 0.0)        return false; 
-  if (sec > 32.767)     return false;
-  (*res) = (__u16) round(sec * 1000.0);
-  return true;
+static bool lhap_time2lin(__u16 * res, double sec)
+{
+   ASSERT(res);
+
+   if (sec < 0.0)
+      return false;
+   if (sec > 32.767)
+      return false;
+   (*res) = (__u16) round(sec * 1000.0);
+   return true;
 }
 
 /* converts the time in seconds to a linux compatible time. 
  * Return false if out of bounds. This one allows negative times. */
-static bool lhap_stime2lin(__s16 * res, double sec) {
-  ASSERT(res); 
-  
-  if (sec < -32.767)    return false; 
-  if (sec > 32.767)     return false;
-  (*res) = (__s16) round(sec * 1000.0);
-  return true;
+static bool lhap_stime2lin(__s16 * res, double sec)
+{
+   ASSERT(res);
+
+   if (sec < -32.767)
+      return false;
+   if (sec > 32.767)
+      return false;
+   (*res) = (__s16) round(sec * 1000.0);
+   return true;
 }
 
 
 /* Converts replay data to linux. */
-static bool lhap_replay2lin(struct ff_replay * lin, struct ALLEGRO_HAPTIC_REPLAY * al) {
-  if(!lhap_time2lin(&lin->delay, al->delay))  return false;
-  if(!lhap_time2lin(&lin->length, al->length)) return false;
-  return true;
+static bool lhap_replay2lin(struct ff_replay *lin,
+                            struct ALLEGRO_HAPTIC_REPLAY *al)
+{
+   if (!lhap_time2lin(&lin->delay, al->delay))
+      return false;
+   if (!lhap_time2lin(&lin->length, al->length))
+      return false;
+   return true;
 }
 
 /* Converts the level in range 0.0 to 1.0 to a linux compatible level. 
  * Returns false if out of bounds. */
-static bool lhap_level2lin(__u16 * res, double level) {
-  ASSERT(res);   
-  if (level < 0.0)        return false; 
-  if (level > 1.0)        return false;
-  (*res) = (__u16) round(level * ((double) 0x7fff));
-  return true;
+static bool lhap_level2lin(__u16 * res, double level)
+{
+   ASSERT(res);
+   if (level < 0.0)
+      return false;
+   if (level > 1.0)
+      return false;
+   (*res) = (__u16) round(level * ((double)0x7fff));
+   return true;
 }
 
 
 /* Converts the level in range -1.0 to 1.0 to a linux compatible level. 
  * Returns false if out of bounds. */
-static bool lhap_slevel2lin(__s16 * res, double level) {
-  ASSERT(res);   
-  if (level < -1.0)        return false; 
-  if (level > 1.0)        return false;
-  (*res) = (__s16) round(level * ((double) 0x7ffe));
-  return true;
+static bool lhap_slevel2lin(__s16 * res, double level)
+{
+   ASSERT(res);
+   if (level < -1.0)
+      return false;
+   if (level > 1.0)
+      return false;
+   (*res) = (__s16) round(level * ((double)0x7ffe));
+   return true;
 }
 
 
 /* Converts an allegro haptic effect envelope to the linux structure. */
-static bool lhap_envelope2lin(struct ff_envelope * lin, struct ALLEGRO_HAPTIC_ENVELOPE * al) {
-  if (!lhap_time2lin(&lin->attack_length, al->attack_length)) return false;
-  if (!lhap_time2lin(&lin->fade_length  , al->fade_length)) return false;
-  if (!lhap_level2lin(&lin->attack_level, al->attack_level)) return false;
-  if (!lhap_level2lin(&lin->fade_level, al->fade_level)) return false;
-  return true;
+static bool lhap_envelope2lin(struct ff_envelope *lin,
+                              struct ALLEGRO_HAPTIC_ENVELOPE *al)
+{
+   if (!lhap_time2lin(&lin->attack_length, al->attack_length))
+      return false;
+   if (!lhap_time2lin(&lin->fade_length, al->fade_length))
+      return false;
+   if (!lhap_level2lin(&lin->attack_level, al->attack_level))
+      return false;
+   if (!lhap_level2lin(&lin->fade_level, al->fade_level))
+      return false;
+   return true;
 }
 
 /* Converts a rumble effect to linux. */
-static bool lhap_rumble2lin(struct ff_rumble_effect * lin, struct ALLEGRO_HAPTIC_RUMBLE_EFFECT * al) {
-  if(!lhap_level2lin(&lin->strong_magnitude, al->strong_magnitude)) return false;
-  if(!lhap_level2lin(&lin->weak_magnitude  , al->weak_magnitude)) return false;
-  return true;
+static bool lhap_rumble2lin(struct ff_rumble_effect *lin,
+                            struct ALLEGRO_HAPTIC_RUMBLE_EFFECT *al)
+{
+   if (!lhap_level2lin(&lin->strong_magnitude, al->strong_magnitude))
+      return false;
+   if (!lhap_level2lin(&lin->weak_magnitude, al->weak_magnitude))
+      return false;
+   return true;
 }
 
 
 /* Converts a constant effect to linux. */
-static bool lhap_constant2lin(struct ff_constant_effect * lin, struct ALLEGRO_HAPTIC_CONSTANT_EFFECT * al) {
-  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
-  if(!lhap_slevel2lin(&lin->level, al->level)) return false;  
-  return true;
+static bool lhap_constant2lin(struct ff_constant_effect *lin,
+                              struct ALLEGRO_HAPTIC_CONSTANT_EFFECT *al)
+{
+   if (!lhap_envelope2lin(&lin->envelope, &al->envelope))
+      return false;
+   if (!lhap_slevel2lin(&lin->level, al->level))
+      return false;
+   return true;
 }
 
 /* Converts a ramp effect to linux. */
-static bool lhap_ramp2lin(struct ff_ramp_effect * lin, struct ALLEGRO_HAPTIC_RAMP_EFFECT * al) {
-  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
-  if(!lhap_slevel2lin(&lin->start_level, al->start_level)) return false;
-  if(!lhap_slevel2lin(&lin->end_level, al->end_level)) return false;
-  return true;
+static bool lhap_ramp2lin(struct ff_ramp_effect *lin,
+                          struct ALLEGRO_HAPTIC_RAMP_EFFECT *al)
+{
+   if (!lhap_envelope2lin(&lin->envelope, &al->envelope))
+      return false;
+   if (!lhap_slevel2lin(&lin->start_level, al->start_level))
+      return false;
+   if (!lhap_slevel2lin(&lin->end_level, al->end_level))
+      return false;
+   return true;
 }
 
 /* Converts a ramp effect to linux. */
-static bool lhap_condition2lin(struct ff_condition_effect * lin, struct ALLEGRO_HAPTIC_CONDITION_EFFECT * al) {
-  if(!lhap_slevel2lin(&lin->center      , al->center)) return false;
-  if(!lhap_level2lin(&lin->deadband    , al->deadband)) return false;
-  if(!lhap_slevel2lin(&lin->right_coeff , al->right_coeff)) return false;
-  if(!lhap_level2lin(&lin->right_saturation , al->right_saturation)) return false;  
-  if(!lhap_slevel2lin(&lin->left_coeff  , al->left_coeff)) return false;
-  if(!lhap_level2lin(&lin->left_saturation , al->left_saturation)) return false;
-  return true;
+static bool lhap_condition2lin(struct ff_condition_effect *lin,
+                               struct ALLEGRO_HAPTIC_CONDITION_EFFECT *al)
+{
+   if (!lhap_slevel2lin(&lin->center, al->center))
+      return false;
+   if (!lhap_level2lin(&lin->deadband, al->deadband))
+      return false;
+   if (!lhap_slevel2lin(&lin->right_coeff, al->right_coeff))
+      return false;
+   if (!lhap_level2lin(&lin->right_saturation, al->right_saturation))
+      return false;
+   if (!lhap_slevel2lin(&lin->left_coeff, al->left_coeff))
+      return false;
+   if (!lhap_level2lin(&lin->left_saturation, al->left_saturation))
+      return false;
+   return true;
 }
 
 
 /* converts a periodic effect  to linux */
-static bool lhap_periodic2lin(struct ff_periodic_effect * lin, struct ALLEGRO_HAPTIC_PERIODIC_EFFECT * al) {
-  if(!lhap_slevel2lin(&lin->magnitude, al->magnitude)) return false;
-  if(!lhap_stime2lin(&lin->offset, al->offset)) return false;
-  if(!lhap_time2lin(&lin->period, al->period)) return false;
-  if(!lhap_time2lin(&lin->phase, al->phase)) return false;
-  if(!lhap_wave2lin(&lin->waveform, al->waveform)) return false; 
-  if (al->custom_data) {
-    /* Custom data is not supported yet, because currently no Linux 
-     * haptic driver supports it. 
-     */
-    return false;
-  }
-  if(!lhap_envelope2lin(&lin->envelope , &al->envelope)) return false;
-  return true;
+static bool lhap_periodic2lin(struct ff_periodic_effect *lin,
+                              struct ALLEGRO_HAPTIC_PERIODIC_EFFECT *al)
+{
+   if (!lhap_slevel2lin(&lin->magnitude, al->magnitude))
+      return false;
+   if (!lhap_stime2lin(&lin->offset, al->offset))
+      return false;
+   if (!lhap_time2lin(&lin->period, al->period))
+      return false;
+   if (!lhap_time2lin(&lin->phase, al->phase))
+      return false;
+   if (!lhap_wave2lin(&lin->waveform, al->waveform))
+      return false;
+   if (al->custom_data) {
+      /* Custom data is not supported yet, because currently no Linux 
+       * haptic driver supports it. 
+       */
+      return false;
+   }
+   if (!lhap_envelope2lin(&lin->envelope, &al->envelope))
+      return false;
+   return true;
 }
 
 /* Converts allegro haptic effect to linux haptic effect. */
-static bool lhap_effect2lin(struct ff_effect * lin, ALLEGRO_HAPTIC_EFFECT * al) {
-  if(!lhap_type2lin(&lin->type, al->type)) return false;
-  /* lin_effect->replay = effect->re; */
-  lin->direction = (__u16) round(((double)0xC000 * al->direction.angle) / (2 * M_PI));
-  lin->id        = -1;
-  if(!lhap_replay2lin(&lin->replay, &al->replay)) return false;
-  switch(lin->type) {
-    case FF_RUMBLE:
-      if(!lhap_rumble2lin(&lin->u.rumble, &al->data.rumble)) return false;
-      break;
-    case FF_PERIODIC:      
-      if(!lhap_periodic2lin(&lin->u.periodic, &al->data.periodic)) return false;
-      break;
-    case FF_CONSTANT: 
-      if(!lhap_constant2lin(&lin->u.constant, &al->data.constant)) return false;
-      break;
-    
-    case FF_RAMP:
-    if(!lhap_ramp2lin(&lin->u.ramp, &al->data.ramp)) return false;
-      break;
-    
-    case FF_SPRING:
-    case FF_FRICTION:
-    case FF_DAMPER:
-    case FF_INERTIA:      
-      if(!lhap_condition2lin(&lin->u.condition[0],  &al->data.condition)) return false;
-    break;
-    default:
-      return false;      
-  }
-     
-  return true;
-}
-
-
-
-static bool lhap_get_active(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(haptic);
-  return lhap->in_use;
-}
-
-static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * mouse) {
-  (void) mouse;
-  return false;
+static bool lhap_effect2lin(struct ff_effect *lin, ALLEGRO_HAPTIC_EFFECT * al)
+{
+   if (!lhap_type2lin(&lin->type, al->type))
+      return false;
+   /* lin_effect->replay = effect->re; */
+   lin->direction =
+       (__u16) round(((double)0xC000 * al->direction.angle) / (2 * M_PI));
+   lin->id = -1;
+   if (!lhap_replay2lin(&lin->replay, &al->replay))
+      return false;
+   switch (lin->type) {
+      case FF_RUMBLE:
+         if (!lhap_rumble2lin(&lin->u.rumble, &al->data.rumble))
+            return false;
+         break;
+      case FF_PERIODIC:
+         if (!lhap_periodic2lin(&lin->u.periodic, &al->data.periodic))
+            return false;
+         break;
+      case FF_CONSTANT:
+         if (!lhap_constant2lin(&lin->u.constant, &al->data.constant))
+            return false;
+         break;
+
+      case FF_RAMP:
+         if (!lhap_ramp2lin(&lin->u.ramp, &al->data.ramp))
+            return false;
+         break;
+
+      case FF_SPRING:
+      case FF_FRICTION:
+      case FF_DAMPER:
+      case FF_INERTIA:
+         if (!lhap_condition2lin(&lin->u.condition[0], &al->data.condition))
+            return false;
+         break;
+      default:
+         return false;
+   }
+
+   return true;
+}
+
+
+
+static bool lhap_get_active(ALLEGRO_HAPTIC * haptic)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(haptic);
+   return lhap->in_use;
+}
+
+static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * mouse)
+{
+   (void)mouse;
+   return false;
 }
 
 #define LONG_BITS (sizeof(long) * 8)
@@ -407,324 +509,355 @@ static bool lhap_is_mouse_haptic(ALLEGRO_MOUSE * mouse) {
 #define TEST_BIT(nr, addr) \
     (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
 
-bool lhap_fd_can_ff(int fd) 
+bool lhap_fd_can_ff(int fd)
 {
-  long bitmask[NLONGS(EV_CNT)]   = {0};
-      
-  if (ioctl (fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
-    return false;
-  }
-  if (TEST_BIT(EV_FF, bitmask)) {
-     return true;
-  }
-  return false;
+   long bitmask[NLONGS(EV_CNT)] = { 0 };
+
+   if (ioctl(fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask) < 0) {
+      return false;
+   }
+   if (TEST_BIT(EV_FF, bitmask)) {
+      return true;
+   }
+   return false;
 }
 
 
 
 
-static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK * joy) {
-  // int newfd = -1;
-  ALLEGRO_JOYSTICK_LINUX * ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
-  if (!al_is_joystick_installed())      return false;
-  if (!al_get_joystick_active(joy))     return false;  
-  if (ljoy->fd <= 0)                    return false; 
-  // al_cstr(ljoy->device_name)
-  // newfd = open("/dev/input/event8", O_RDWR);  
-  // close(newfd);
-  return lhap_fd_can_ff(ljoy->fd); 
+static bool lhap_is_joystick_haptic(ALLEGRO_JOYSTICK * joy)
+{
+   // int newfd = -1;
+   ALLEGRO_JOYSTICK_LINUX *ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
+   if (!al_is_joystick_installed())
+      return false;
+   if (!al_get_joystick_active(joy))
+      return false;
+   if (ljoy->fd <= 0)
+      return false;
+   // al_cstr(ljoy->device_name)
+   // newfd = open("/dev/input/event8", O_RDWR);  
+   // close(newfd);
+   return lhap_fd_can_ff(ljoy->fd);
 }
 
-static bool lhap_is_display_haptic (ALLEGRO_DISPLAY * dev) {
-  (void) dev;
-  return false;
+static bool lhap_is_display_haptic(ALLEGRO_DISPLAY * dev)
+{
+   (void)dev;
+   return false;
 }
 
-static bool lhap_is_keyboard_haptic (ALLEGRO_KEYBOARD * dev) {
-  (void) dev;
-  return false;
+static bool lhap_is_keyboard_haptic(ALLEGRO_KEYBOARD * dev)
+{
+   (void)dev;
+   return false;
 }
 
-static bool lhap_is_touch_input_haptic (ALLEGRO_TOUCH_INPUT * dev) {
-  (void) dev;
-  return false;
+static bool lhap_is_touch_input_haptic(ALLEGRO_TOUCH_INPUT * dev)
+{
+   (void)dev;
+   return false;
 }
 
 
-static ALLEGRO_HAPTIC *  lhap_get_from_mouse(ALLEGRO_MOUSE * mouse) 
+static ALLEGRO_HAPTIC *lhap_get_from_mouse(ALLEGRO_MOUSE * mouse)
 {
-  (void) mouse;
-  return NULL;
+   (void)mouse;
+   return NULL;
 }
 
 
 #define TEST_CAPA(BIT, MASK, CAP, ALCAPA) do { \
   if (TEST_BIT(FF_PERIODIC, bitmask)) { cap |= ALCAPA; } \
 } while (0)
-  
-
-static bool get_haptic_capabilities(int fd, int * capabilities) {
-
-  int cap = 0;
-  // unsigned long device_bits[(EV_MAX + 8) / sizeof(unsigned long)];  
-  unsigned long bitmask[NLONGS(FF_CNT)]   = {0};
-  if (ioctl (fd, EVIOCGBIT(EV_FF, sizeof(bitmask)), bitmask) < 0) {
-    perror ("EVIOCGBIT ioctl failed");
-    fprintf(stderr, "For fd %d\n", fd);
-    return false;
-  }
-  TEST_CAPA(FF_PERIODIC, bitmask, cap, ALLEGRO_HAPTIC_PERIODIC); 
-  TEST_CAPA(FF_RUMBLE, bitmask, cap, ALLEGRO_HAPTIC_RUMBLE); 
-  TEST_CAPA(FF_CONSTANT, bitmask, cap, ALLEGRO_HAPTIC_CONSTANT);
-  TEST_CAPA(FF_SPRING, bitmask, cap, ALLEGRO_HAPTIC_SPRING); 
-  TEST_CAPA(FF_FRICTION, bitmask, cap, ALLEGRO_HAPTIC_FRICTION);   
-  TEST_CAPA(FF_DAMPER, bitmask, cap, ALLEGRO_HAPTIC_DAMPER);   
-  TEST_CAPA(FF_INERTIA, bitmask, cap, ALLEGRO_HAPTIC_INERTIA); 
-  TEST_CAPA(FF_RAMP, bitmask, cap, ALLEGRO_HAPTIC_RAMP); 
-  TEST_CAPA(FF_SQUARE, bitmask, cap, ALLEGRO_HAPTIC_SQUARE); 
-  TEST_CAPA(FF_TRIANGLE, bitmask, cap, ALLEGRO_HAPTIC_TRIANGLE); 
-  TEST_CAPA(FF_SINE, bitmask, cap, ALLEGRO_HAPTIC_SINE); 
-  TEST_CAPA(FF_SAW_UP, bitmask, cap, ALLEGRO_HAPTIC_SAW_UP); 
-  TEST_CAPA(FF_SAW_DOWN, bitmask, cap, ALLEGRO_HAPTIC_SAW_DOWN); 
-  TEST_CAPA(FF_CUSTOM, bitmask, cap, ALLEGRO_HAPTIC_CUSTOM); 
-  TEST_CAPA(FF_GAIN, bitmask, cap, ALLEGRO_HAPTIC_GAIN); 
-  
-  (*capabilities) = cap;
-  
-  return true;
-}
-
-static ALLEGRO_HAPTIC *  lhap_get_from_joystick(ALLEGRO_JOYSTICK * joy) 
-{
-  int index;
-  ALLEGRO_HAPTIC_LINUX *lhap;
-  ALLEGRO_JOYSTICK_LINUX * ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
-  
-  if (!al_is_joystick_haptic(joy)) return NULL;  
-  
-  al_lock_mutex(haptic_mutex);
-  
-  lhap = lhap_get_available_haptic();
-  if (!lhap) return NULL;
-  
-  lhap->parent.device = joy; 
-  lhap->parent.from   = _AL_HAPTIC_FROM_JOYSTICK;
-  
-  
-  lhap->fd            = ljoy->fd;
-  lhap->in_use        = true;
-  for (index = 0; index < HAPTICS_EFFECTS_MAX; index ++) {
-    lhap->effects[index] = -1; // negative means not in use. 
-  }
-  lhap->parent.gain   = 1.0;
-  get_haptic_capabilities(lhap->fd, &lhap->flags);
-  al_unlock_mutex(haptic_mutex);
-  return &(lhap->parent);
-}
-
-static ALLEGRO_HAPTIC * lhap_get_from_display (ALLEGRO_DISPLAY * dev) 
-{
-  (void) dev;
-  return NULL;
-}
-
-static  ALLEGRO_HAPTIC * lhap_get_from_keyboard (ALLEGRO_KEYBOARD * dev) 
-{
-  (void) dev;
-  return NULL;
-}
-
-static ALLEGRO_HAPTIC * lhap_get_from_touch_input (ALLEGRO_TOUCH_INPUT * dev) 
-{
-  (void) dev;
-  return NULL;
-}
-
-
-static int lhap_get_capabilities (ALLEGRO_HAPTIC * dev) 
-{
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
-  return lhap->flags;
-}
-
-
-static double lhap_get_gain(ALLEGRO_HAPTIC * dev) {
-  (void) dev;
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
-  /* Unfortunately there seems to be no API to GET gain, only to set?! 
-   * So, retururn the stored gain.
-   */
-  return lhap->parent.gain;
-}
-
-static bool lhap_set_gain(ALLEGRO_HAPTIC * dev, double gain) {  
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
-  struct input_event ie ;  
-  lhap->parent.gain     = gain;
-  timerclear(&ie.time); 
-  ie.type     = EV_FF;
-  ie.code     = FF_GAIN;
-  ie.value    =  (__s32)((double)0xFFFF * gain);
-  if (write(lhap->fd, &ie, sizeof(ie)) < 0) {
-    return false;
-  }
-  return true;
-}
-
-int lhap_get_num_effects (ALLEGRO_HAPTIC * dev) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
-  int n_effects; /* Number of effects the device can play at the same time */
-  
-  if (ioctl(lhap->fd, EVIOCGEFFECTS, &n_effects) < 0) {
-    perror("Cannot check amount of effects");
-    fprintf(stderr, "on FD %d\n", lhap->fd);
-    return HAPTICS_EFFECTS_MAX;
-  } 
-  if (n_effects > HAPTICS_EFFECTS_MAX) return HAPTICS_EFFECTS_MAX;
-  return n_effects;
-}
-
-
-static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * haptic, ALLEGRO_HAPTIC_EFFECT * effect) {
-  struct ff_effect leff;
-  int caps = al_get_haptic_capabilities(haptic);
-  if(!((caps & effect->type) == effect->type)) return false;  
-  if(!lhap_effect2lin(&leff, effect)) return false;
-  return true;  
-}
-
-static double lhap_effect_duration(ALLEGRO_HAPTIC_EFFECT * effect) {
-  return effect->replay.delay + effect->replay.length;   
-}
-
-
-static bool lhap_upload_effect(ALLEGRO_HAPTIC * dev, ALLEGRO_HAPTIC_EFFECT * effect, ALLEGRO_HAPTIC_EFFECT_ID * id) { 
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(dev);
-  struct ff_effect leff;
-  int index;
-  int found = -1;
-  
-  ASSERT(dev);
-  ASSERT(id);
-  ASSERT(effect);
-  
-  /* set id's values to indicate failure. */
-  id->_haptic   = NULL;
-  id->_effect   = NULL;
-  id->_id       = -1;
-  id->_handle   = -1;
-  
-  
-  if(!lhap_effect2lin(&leff, effect)) { 
-    return false;
-  }
-  
-  leff.id = -1;
-  
-  /* Find empty spot for effect . */
-  for(index = 0; index < al_get_num_haptic_effects(dev); index ++) {
-    if(lhap->effects[index] < 0) {
-      found = index; 
-      break;
-    }
-  }
-  
-  /* No more space for an effect. */
-  if(found < 0) {
-    return false;
-  }
-  
-  /* Upload effect. */
-  if (ioctl(lhap->fd, EVIOCSFF, &leff) < 0 ) {
-    return false;
-  }
-  
-  id->_haptic   = dev;
-  id->_effect   = effect;
-  id->_id       = found;
-  id->_handle   = leff.id;
-  id->_playing  = false;
-    
-  return true;
-}
-
-static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loops) {
-  struct input_event     play;
-  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;    
-  int fd                     ;
-  
-  if(!lhap) return false; 
-  
-  fd = lhap->fd;
-  
-  timerclear(&play.time);
-  play.type     = EV_FF;
-  play.code     = id->_handle; 
-  loops         = (loops < 0 ) ? 1 : loops; 
-  play.value    = loops; /* play: 1, stop: 0 */
-   
-  if (write(fd, (const void*) &play, sizeof(play)) < 0) {    
-    perror("Effect play failed.");
-    return false;
-  }
-  id->_playing = true;
-  id->_started = al_get_time(); 
-  id->_loops   = loops;
-  
-  return true;  
-}
-
-
-static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
-  struct input_event play;
-  ALLEGRO_HAPTIC_LINUX * lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;    
-  if(!lhap) return false; 
-  
-  play.type     = EV_FF;
-  play.code     = id->_handle; 
-  play.value    = 0;  
-  
-  if (write(lhap->fd, (const void*) &play, sizeof(play)) < 0) {
-    return false;
-  }
-  id->_playing  = false;
-  return true;   
-}
-
-
-static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id) {  
-  double duration;
-  ASSERT(id); 
-  
-  if(!id->_playing) return false;
-  /* Since AFAICS there is no Linux API to test this, use a timer to check if the 
-   effect has been playing long enough to be finished or not. */
-  duration = lhap_effect_duration(id->_effect) * id->_loops;
-  if((id->_started + duration) >= al_get_time()) return true;  
-  return false;
-}
-
-static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id) {
-  ALLEGRO_HAPTIC_LINUX * lhap =  (ALLEGRO_HAPTIC_LINUX *) id->_haptic;  
-  lhap_stop_effect(id);
-  
-  if (ioctl(lhap->fd, EVIOCRMFF, id->_handle) < 0) {
-    return false;
-  }  
-  lhap->effects[id->_id] = -1; // negative means not in use.
-  return true;
-}
-
-
-static bool lhap_release(ALLEGRO_HAPTIC * haptic) {
-  ALLEGRO_HAPTIC_LINUX * lhap = lhap_from_al(haptic);
-  
-  ASSERT(haptic);
-  
-  if(!lhap->in_use) return false;
-  
-  lhap->in_use = false;
-  lhap->fd     = -1;
-  return true;
+
+
+static bool get_haptic_capabilities(int fd, int *capabilities)
+{
+
+   int cap = 0;
+   // unsigned long device_bits[(EV_MAX + 8) / sizeof(unsigned long)];  
+   unsigned long bitmask[NLONGS(FF_CNT)] = { 0 };
+   if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(bitmask)), bitmask) < 0) {
+      perror("EVIOCGBIT ioctl failed");
+      fprintf(stderr, "For fd %d\n", fd);
+      return false;
+   }
+   TEST_CAPA(FF_PERIODIC, bitmask, cap, ALLEGRO_HAPTIC_PERIODIC);
+   TEST_CAPA(FF_RUMBLE, bitmask, cap, ALLEGRO_HAPTIC_RUMBLE);
+   TEST_CAPA(FF_CONSTANT, bitmask, cap, ALLEGRO_HAPTIC_CONSTANT);
+   TEST_CAPA(FF_SPRING, bitmask, cap, ALLEGRO_HAPTIC_SPRING);
+   TEST_CAPA(FF_FRICTION, bitmask, cap, ALLEGRO_HAPTIC_FRICTION);
+   TEST_CAPA(FF_DAMPER, bitmask, cap, ALLEGRO_HAPTIC_DAMPER);
+   TEST_CAPA(FF_INERTIA, bitmask, cap, ALLEGRO_HAPTIC_INERTIA);
+   TEST_CAPA(FF_RAMP, bitmask, cap, ALLEGRO_HAPTIC_RAMP);
+   TEST_CAPA(FF_SQUARE, bitmask, cap, ALLEGRO_HAPTIC_SQUARE);
+   TEST_CAPA(FF_TRIANGLE, bitmask, cap, ALLEGRO_HAPTIC_TRIANGLE);
+   TEST_CAPA(FF_SINE, bitmask, cap, ALLEGRO_HAPTIC_SINE);
+   TEST_CAPA(FF_SAW_UP, bitmask, cap, ALLEGRO_HAPTIC_SAW_UP);
+   TEST_CAPA(FF_SAW_DOWN, bitmask, cap, ALLEGRO_HAPTIC_SAW_DOWN);
+   TEST_CAPA(FF_CUSTOM, bitmask, cap, ALLEGRO_HAPTIC_CUSTOM);
+   TEST_CAPA(FF_GAIN, bitmask, cap, ALLEGRO_HAPTIC_GAIN);
+
+   (*capabilities) = cap;
+
+   return true;
+}
+
+static ALLEGRO_HAPTIC *lhap_get_from_joystick(ALLEGRO_JOYSTICK * joy)
+{
+   int index;
+   ALLEGRO_HAPTIC_LINUX *lhap;
+   ALLEGRO_JOYSTICK_LINUX *ljoy = (ALLEGRO_JOYSTICK_LINUX *) joy;
+
+   if (!al_is_joystick_haptic(joy))
+      return NULL;
+
+   al_lock_mutex(haptic_mutex);
+
+   lhap = lhap_get_available_haptic();
+   if (!lhap)
+      return NULL;
+
+   lhap->parent.device = joy;
+   lhap->parent.from = _AL_HAPTIC_FROM_JOYSTICK;
+
+
+   lhap->fd = ljoy->fd;
+   lhap->in_use = true;
+   for (index = 0; index < HAPTICS_EFFECTS_MAX; index++) {
+      lhap->effects[index] = -1;        // negative means not in use. 
+   }
+   lhap->parent.gain = 1.0;
+   get_haptic_capabilities(lhap->fd, &lhap->flags);
+   al_unlock_mutex(haptic_mutex);
+   return &(lhap->parent);
+}
+
+static ALLEGRO_HAPTIC *lhap_get_from_display(ALLEGRO_DISPLAY * dev)
+{
+   (void)dev;
+   return NULL;
+}
+
+static ALLEGRO_HAPTIC *lhap_get_from_keyboard(ALLEGRO_KEYBOARD * dev)
+{
+   (void)dev;
+   return NULL;
+}
+
+static ALLEGRO_HAPTIC *lhap_get_from_touch_input(ALLEGRO_TOUCH_INPUT * dev)
+{
+   (void)dev;
+   return NULL;
+}
+
+
+static int lhap_get_capabilities(ALLEGRO_HAPTIC * dev)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(dev);
+   return lhap->flags;
 }
 
+
+static double lhap_get_gain(ALLEGRO_HAPTIC * dev)
+{
+   (void)dev;
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(dev);
+   /* Unfortunately there seems to be no API to GET gain, only to set?! 
+    * So, retururn the stored gain.
+    */
+   return lhap->parent.gain;
+}
+
+static bool lhap_set_gain(ALLEGRO_HAPTIC * dev, double gain)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(dev);
+   struct input_event ie;
+   lhap->parent.gain = gain;
+   timerclear(&ie.time);
+   ie.type = EV_FF;
+   ie.code = FF_GAIN;
+   ie.value = (__s32) ((double)0xFFFF * gain);
+   if (write(lhap->fd, &ie, sizeof(ie)) < 0) {
+      return false;
+   }
+   return true;
+}
+
+int lhap_get_num_effects(ALLEGRO_HAPTIC * dev)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(dev);
+   int n_effects;               /* Number of effects the device can play at the same time */
+
+   if (ioctl(lhap->fd, EVIOCGEFFECTS, &n_effects) < 0) {
+      perror("Cannot check amount of effects");
+      fprintf(stderr, "on FD %d\n", lhap->fd);
+      return HAPTICS_EFFECTS_MAX;
+   }
+   if (n_effects > HAPTICS_EFFECTS_MAX)
+      return HAPTICS_EFFECTS_MAX;
+   return n_effects;
+}
+
+
+static bool lhap_is_effect_ok(ALLEGRO_HAPTIC * haptic,
+                              ALLEGRO_HAPTIC_EFFECT * effect)
+{
+   struct ff_effect leff;
+   int caps = al_get_haptic_capabilities(haptic);
+   if (!((caps & effect->type) == effect->type))
+      return false;
+   if (!lhap_effect2lin(&leff, effect))
+      return false;
+   return true;
+}
+
+static double lhap_effect_duration(ALLEGRO_HAPTIC_EFFECT * effect)
+{
+   return effect->replay.delay + effect->replay.length;
+}
+
+
+static bool lhap_upload_effect(ALLEGRO_HAPTIC * dev,
+                               ALLEGRO_HAPTIC_EFFECT * effect,
+                               ALLEGRO_HAPTIC_EFFECT_ID * id)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(dev);
+   struct ff_effect leff;
+   int index;
+   int found = -1;
+
+   ASSERT(dev);
+   ASSERT(id);
+   ASSERT(effect);
+
+   /* set id's values to indicate failure. */
+   id->_haptic = NULL;
+   id->_effect = NULL;
+   id->_id = -1;
+   id->_handle = -1;
+
+
+   if (!lhap_effect2lin(&leff, effect)) {
+      return false;
+   }
+
+   leff.id = -1;
+
+   /* Find empty spot for effect . */
+   for (index = 0; index < al_get_num_haptic_effects(dev); index++) {
+      if (lhap->effects[index] < 0) {
+         found = index;
+         break;
+      }
+   }
+
+   /* No more space for an effect. */
+   if (found < 0) {
+      return false;
+   }
+
+   /* Upload effect. */
+   if (ioctl(lhap->fd, EVIOCSFF, &leff) < 0) {
+      return false;
+   }
+
+   id->_haptic = dev;
+   id->_effect = effect;
+   id->_id = found;
+   id->_handle = leff.id;
+   id->_playing = false;
+
+   return true;
+}
+
+static bool lhap_play_effect(ALLEGRO_HAPTIC_EFFECT_ID * id, int loops)
+{
+   struct input_event play;
+   ALLEGRO_HAPTIC_LINUX *lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;
+   int fd;
+
+   if (!lhap)
+      return false;
+
+   fd = lhap->fd;
+
+   timerclear(&play.time);
+   play.type = EV_FF;
+   play.code = id->_handle;
+   loops = (loops < 0) ? 1 : loops;
+   play.value = loops;          /* play: 1, stop: 0 */
+
+   if (write(fd, (const void *)&play, sizeof(play)) < 0) {
+      perror("Effect play failed.");
+      return false;
+   }
+   id->_playing = true;
+   id->_started = al_get_time();
+   id->_loops = loops;
+
+   return true;
+}
+
+
+static bool lhap_stop_effect(ALLEGRO_HAPTIC_EFFECT_ID * id)
+{
+   struct input_event play;
+   ALLEGRO_HAPTIC_LINUX *lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;
+   if (!lhap)
+      return false;
+
+   play.type = EV_FF;
+   play.code = id->_handle;
+   play.value = 0;
+
+   if (write(lhap->fd, (const void *)&play, sizeof(play)) < 0) {
+      return false;
+   }
+   id->_playing = false;
+   return true;
+}
+
+
+static bool lhap_is_effect_playing(ALLEGRO_HAPTIC_EFFECT_ID * id)
+{
+   double duration;
+   ASSERT(id);
+
+   if (!id->_playing)
+      return false;
+   /* Since AFAICS there is no Linux API to test this, use a timer to check if the 
+      effect has been playing long enough to be finished or not. */
+   duration = lhap_effect_duration(id->_effect) * id->_loops;
+   if ((id->_started + duration) >= al_get_time())
+      return true;
+   return false;
+}
+
+static bool lhap_release_effect(ALLEGRO_HAPTIC_EFFECT_ID * id)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = (ALLEGRO_HAPTIC_LINUX *) id->_haptic;
+   lhap_stop_effect(id);
+
+   if (ioctl(lhap->fd, EVIOCRMFF, id->_handle) < 0) {
+      return false;
+   }
+   lhap->effects[id->_id] = -1; // negative means not in use.
+   return true;
+}
+
+
+static bool lhap_release(ALLEGRO_HAPTIC * haptic)
+{
+   ALLEGRO_HAPTIC_LINUX *lhap = lhap_from_al(haptic);
+
+   ASSERT(haptic);
+
+   if (!lhap->in_use)
+      return false;
+
+   lhap->in_use = false;
+   lhap->fd = -1;
+   return true;
+}
-- 
1.7.10.4


From 9b8365e190b1a021ed6c78069112508c72c46ca6 Mon Sep 17 00:00:00 2001
From: Beoran <beoran@xxxxxxxxx>
Date: Mon, 1 Jul 2013 15:45:27 +0200
Subject: [PATCH 10/10] Bugfix of ex_joystick_events. Prevent double free of
 font on progrem end.

---
 examples/ex_joystick_events.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/examples/ex_joystick_events.c b/examples/ex_joystick_events.c
index b0eca96..6fe5ae2 100644
--- a/examples/ex_joystick_events.c
+++ b/examples/ex_joystick_events.c
@@ -287,8 +287,6 @@ int main(void)
    
    al_destroy_font(font);
 
-   al_destroy_font(font);
-
    return 0;
 }
 
-- 
1.7.10.4



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/