[PATCH 01/24] Add ff-memless-next module

2014-04-09 Thread Michal Malý
Add ff-memless-next module

Signed-off-by: Michal Malý 
Tested-by: Elias Vanderstuyft 
---
 drivers/input/Kconfig |   11 +
 drivers/input/Makefile|1 +
 drivers/input/ff-memless-next.c   | 1036 +
 include/linux/input/ff-memless-next.h |  149 +
 4 files changed, 1197 insertions(+)
 create mode 100644 drivers/input/ff-memless-next.c
 create mode 100644 include/linux/input/ff-memless-next.h

diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index a11ff74..3780962 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -38,6 +38,17 @@ config INPUT_FF_MEMLESS
  To compile this driver as a module, choose M here: the
  module will be called ff-memless.
 
+config INPUT_FF_MEMLESS_NEXT
+   tristate "New version of support for memoryless force-feedback devices"
+   help
+ Say Y here to enable a new version of support for memoryless force
+ feedback devices.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ff-memless-next.
+
 config INPUT_POLLDEV
tristate "Polled input device skeleton"
help
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 5ca3f63..b4f11f5 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT) += input-core.o
 input-core-y := input.o input-compat.o input-mt.o ff-core.o
 
 obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
+obj-$(CONFIG_INPUT_FF_MEMLESS_NEXT)+= ff-memless-next.o
 obj-$(CONFIG_INPUT_POLLDEV)+= input-polldev.o
 obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
 obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o
diff --git a/drivers/input/ff-memless-next.c b/drivers/input/ff-memless-next.c
new file mode 100644
index 000..f343865
--- /dev/null
+++ b/drivers/input/ff-memless-next.c
@@ -0,0 +1,1036 @@
+/*
+ * Force feedback support for memoryless devices
+ *
+ * This module is based on "ff-memless" orignally written by Anssi Hannula.
+ * It is extended to support all force feedback effects currently supported
+ * by the Linux input stack.
+ * Logic of emulation of FF_RUMBLE through FF_PERIODIC provided by
+ * Elias Vanderstuyft 
+ *
+ * Copyright(c) 2014 Michal "MadCatX" Maly 
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal \"MadCatX\" Maly");
+MODULE_DESCRIPTION("Force feedback support for memoryless force feedback 
devices");
+
+#define FF_MAX_EFFECTS 16
+#define FF_MIN_EFFECT_LENGTH ((1000 / CONFIG_HZ) + 1)
+#define FF_EFFECT_STARTED 1
+#define FF_EFFECT_PLAYING 2
+#define FF_EFFECT_EMULATED 3
+
+enum mlnx_emulate {
+   EMUL_NOTHING,   /* Do not emulate anything */
+   EMUL_RUMBLE,/* Emulate FF_RUMBLE with FF_PERIODIC */
+   EMUL_PERIODIC   /* Emulate FF_PERIODIC with FF_RUMBLE */
+};
+
+struct mlnx_effect {
+   struct ff_effect effect;
+   unsigned long flags;
+   unsigned long begin_at;
+   unsigned long stop_at;
+   unsigned long updated_at;
+   unsigned long attack_stop;
+   unsigned long fade_begin;
+   int repeat;
+};
+
+struct mlnx_device {
+   u8 combinable_playing;
+   u8 rumble_playing;
+   unsigned long update_rate_jiffies;
+   void *private;
+   struct mlnx_effect effects[FF_MAX_EFFECTS];
+   u16 gain;
+   struct timer_list timer;
+   struct input_dev *dev;
+   enum mlnx_emulate emul;
+
+   int (*control_effect)(struct input_dev *, void *,
+ const struct mlnx_effect_command *);
+};
+
+static s32 mlnx_calculate_x_force(const s32 level,
+ const u16 direction)
+{
+   s32 new = (level * -fixp_sin(direction)) >> FRAC_N;
+   pr_debug("x force: %d\n", new);
+   return new;
+}
+
+static s32 mlnx_calculate_y_force(const s32 level,
+ const u16 direction)
+{
+   s32 new = (level * fixp_cos(direction)) >> FRAC_N;
+   pr_debug("y force: %d\n", new);
+   return new;
+}
+
+static bool mlnx_is_combinable(const struct ff_effect *effect)
+{
+   switch (effect->type) {
+   case FF_CONSTANT:
+   case FF_PERIODIC:
+   case FF_RAMP:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static bool mlnx_is_conditional(const struct ff_effect *effect)
+{
+   switch (effect->type) {
+   case FF_DAMPER:
+   case FF_FRICTION:
+   case FF_INERTIA:
+   case FF_SPRING:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static void mlnx_clr_emulated(struct mlnx_effect *mlnxeff)
+{
+   __clear_bit(FF_EFFECT_EMULATED, >flags);
+}
+
+static void mlnx_clr_playing(struct mlnx_effect *mlnxeff)
+{
+   

[PATCH 01/24] Add ff-memless-next module

2014-04-09 Thread Michal Malý
Add ff-memless-next module

Signed-off-by: Michal Malý madcatxs...@devoid-pointer.net
Tested-by: Elias Vanderstuyft elias@gmail.com
---
 drivers/input/Kconfig |   11 +
 drivers/input/Makefile|1 +
 drivers/input/ff-memless-next.c   | 1036 +
 include/linux/input/ff-memless-next.h |  149 +
 4 files changed, 1197 insertions(+)
 create mode 100644 drivers/input/ff-memless-next.c
 create mode 100644 include/linux/input/ff-memless-next.h

diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index a11ff74..3780962 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -38,6 +38,17 @@ config INPUT_FF_MEMLESS
  To compile this driver as a module, choose M here: the
  module will be called ff-memless.
 
+config INPUT_FF_MEMLESS_NEXT
+   tristate New version of support for memoryless force-feedback devices
+   help
+ Say Y here to enable a new version of support for memoryless force
+ feedback devices.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ff-memless-next.
+
 config INPUT_POLLDEV
tristate Polled input device skeleton
help
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 5ca3f63..b4f11f5 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT) += input-core.o
 input-core-y := input.o input-compat.o input-mt.o ff-core.o
 
 obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
+obj-$(CONFIG_INPUT_FF_MEMLESS_NEXT)+= ff-memless-next.o
 obj-$(CONFIG_INPUT_POLLDEV)+= input-polldev.o
 obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
 obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o
diff --git a/drivers/input/ff-memless-next.c b/drivers/input/ff-memless-next.c
new file mode 100644
index 000..f343865
--- /dev/null
+++ b/drivers/input/ff-memless-next.c
@@ -0,0 +1,1036 @@
+/*
+ * Force feedback support for memoryless devices
+ *
+ * This module is based on ff-memless orignally written by Anssi Hannula.
+ * It is extended to support all force feedback effects currently supported
+ * by the Linux input stack.
+ * Logic of emulation of FF_RUMBLE through FF_PERIODIC provided by
+ * Elias Vanderstuyft elias@gmail.com
+ *
+ * Copyright(c) 2014 Michal MadCatX Maly madcatxs...@devoid-pointer.net
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME :  fmt
+
+#include linux/slab.h
+#include linux/module.h
+#include linux/mutex.h
+#include linux/spinlock.h
+#include linux/jiffies.h
+#include linux/fixp-arith.h
+#include linux/input/ff-memless-next.h
+
+MODULE_LICENSE(GPL);
+MODULE_AUTHOR(Michal \MadCatX\ Maly);
+MODULE_DESCRIPTION(Force feedback support for memoryless force feedback 
devices);
+
+#define FF_MAX_EFFECTS 16
+#define FF_MIN_EFFECT_LENGTH ((1000 / CONFIG_HZ) + 1)
+#define FF_EFFECT_STARTED 1
+#define FF_EFFECT_PLAYING 2
+#define FF_EFFECT_EMULATED 3
+
+enum mlnx_emulate {
+   EMUL_NOTHING,   /* Do not emulate anything */
+   EMUL_RUMBLE,/* Emulate FF_RUMBLE with FF_PERIODIC */
+   EMUL_PERIODIC   /* Emulate FF_PERIODIC with FF_RUMBLE */
+};
+
+struct mlnx_effect {
+   struct ff_effect effect;
+   unsigned long flags;
+   unsigned long begin_at;
+   unsigned long stop_at;
+   unsigned long updated_at;
+   unsigned long attack_stop;
+   unsigned long fade_begin;
+   int repeat;
+};
+
+struct mlnx_device {
+   u8 combinable_playing;
+   u8 rumble_playing;
+   unsigned long update_rate_jiffies;
+   void *private;
+   struct mlnx_effect effects[FF_MAX_EFFECTS];
+   u16 gain;
+   struct timer_list timer;
+   struct input_dev *dev;
+   enum mlnx_emulate emul;
+
+   int (*control_effect)(struct input_dev *, void *,
+ const struct mlnx_effect_command *);
+};
+
+static s32 mlnx_calculate_x_force(const s32 level,
+ const u16 direction)
+{
+   s32 new = (level * -fixp_sin(direction))  FRAC_N;
+   pr_debug(x force: %d\n, new);
+   return new;
+}
+
+static s32 mlnx_calculate_y_force(const s32 level,
+ const u16 direction)
+{
+   s32 new = (level * fixp_cos(direction))  FRAC_N;
+   pr_debug(y force: %d\n, new);
+   return new;
+}
+
+static bool mlnx_is_combinable(const struct ff_effect *effect)
+{
+   switch (effect-type) {
+   case FF_CONSTANT:
+   case FF_PERIODIC:
+   case FF_RAMP:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static bool mlnx_is_conditional(const struct ff_effect *effect)
+{
+   switch (effect-type) {
+   case FF_DAMPER:
+   case FF_FRICTION:
+   case FF_INERTIA:
+   case FF_SPRING:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static void