[PATCH 01/24] Add ff-memless-next module
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
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